mirror of https://github.com/coder/code-server.git
135 lines
6.6 KiB
Diff
135 lines
6.6 KiB
Diff
Serve webviews from the same origin
|
|
|
|
Normally webviews are served from vscode-webview.net but we would rather them be
|
|
self-hosted.
|
|
|
|
When doing this CSP will block resources (for example when viewing images) so
|
|
add 'self' to the CSP to fix that.
|
|
|
|
Additionally the service worker defaults to handling *all* requests made to the
|
|
current host but when self-hosting the webview this will end up including the
|
|
webview HTML itself which means these requests will fail since the communication
|
|
channel between the webview and the main thread has not been set up yet as the
|
|
webview itself is not ready yet (it has no HTML and therefore no script either).
|
|
Since this code exists only for the authentication case we can just skip it when
|
|
it is served from the current host as authentication is not a problem if the
|
|
request is not cross-origin.
|
|
|
|
There is also an origin check we bypass (this seems to be related to how the
|
|
webview host is separate by default but we serve on the same host).
|
|
|
|
To test, open a few types of webviews (images, markdown, extension details, etc).
|
|
|
|
Make sure to update the hash. To do so:
|
|
1. run code-server
|
|
2. open any webview (i.e. preview Markdown)
|
|
3. see error in console and copy hash
|
|
|
|
That will test the hash change in pre/index.html
|
|
|
|
Double-check the console to make sure there are no console errors for the webWorkerExtensionHostIframe
|
|
which also requires a hash change.
|
|
|
|
parentOriginHash changes
|
|
|
|
This fixes webviews from not working properly due to a change upstream.
|
|
Upstream added a check to ensure parent authority is encoded into the webview
|
|
origin. Since our webview origin is the parent authority, we can bypass this
|
|
check.
|
|
|
|
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
===================================================================
|
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
|
@@ -225,7 +225,7 @@ export class BrowserWorkbenchEnvironment
|
|
|
|
@memoize
|
|
get webviewExternalEndpoint(): string {
|
|
- const endpoint = this.options.webviewEndpoint
|
|
+ const endpoint = (this.options.webviewEndpoint && new URL(this.options.webviewEndpoint, window.location.toString()).toString())
|
|
|| this.productService.webviewContentExternalBaseUrlTemplate
|
|
|| 'https://{{uuid}}.vscode-cdn.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
|
|
|
|
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|
===================================================================
|
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|
@@ -316,6 +316,7 @@ export class WebClientServer {
|
|
|
|
const workbenchWebConfiguration = {
|
|
remoteAuthority,
|
|
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
|
_wrapWebWorkerExtHostInIframe,
|
|
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
|
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
|
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
|
===================================================================
|
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
|
@@ -5,7 +5,7 @@
|
|
<meta charset="UTF-8">
|
|
|
|
<meta http-equiv="Content-Security-Policy"
|
|
- content="default-src 'none'; script-src 'sha256-N4YFn5ze5crjPqMK/opogKs7bSGWtf3lmjV/3LfbSOs=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
|
+ content="default-src 'none'; script-src 'sha256-B5FRTRmagxqZ2yiS/ip5EgFZJPHAF0G0O3NgwgN6hhg=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
|
|
|
<!-- Disable pinch zooming -->
|
|
<meta name="viewport"
|
|
@@ -334,6 +334,12 @@
|
|
|
|
const hostname = location.hostname;
|
|
|
|
+ // It is safe to run if we are on the same host.
|
|
+ const parent = new URL(parentOrigin)
|
|
+ if (parent.hostname === hostname) {
|
|
+ return start(parentOrigin)
|
|
+ }
|
|
+
|
|
if (!crypto.subtle) {
|
|
// cannot validate, not running in a secure context
|
|
throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
|
|
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
===================================================================
|
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
@@ -333,6 +333,12 @@
|
|
|
|
const hostname = location.hostname;
|
|
|
|
+ // It is safe to run if we are on the same host.
|
|
+ const parent = new URL(parentOrigin)
|
|
+ if (parent.hostname === hostname) {
|
|
+ return start(parentOrigin)
|
|
+ }
|
|
+
|
|
if (!crypto.subtle) {
|
|
// cannot validate, not running in a secure context
|
|
throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
|
|
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
|
===================================================================
|
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
|
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
|
@@ -4,7 +4,7 @@
|
|
<meta http-equiv="Content-Security-Policy" content="
|
|
default-src 'none';
|
|
child-src 'self' data: blob:;
|
|
- script-src 'self' 'unsafe-eval' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' https:;
|
|
+ script-src 'self' 'unsafe-eval' 'sha256-TkIM/TmudlFEe0ZRp0ptvN54LClwk30Rql4ZPE0hm/I=' https:;
|
|
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
|
</head>
|
|
<body>
|
|
@@ -23,6 +23,13 @@
|
|
// validation not requested
|
|
return start();
|
|
}
|
|
+
|
|
+ // It is safe to run if we are on the same host.
|
|
+ const parent = new URL(parentOrigin)
|
|
+ if (parent.hostname === hostname) {
|
|
+ return start()
|
|
+ }
|
|
+
|
|
if (!crypto.subtle) {
|
|
// cannot validate, not running in a secure context
|
|
return sendError(new Error(`Cannot validate in current context!`));
|