commit in route

This commit is contained in:
Martin Aeschlimann 2022-04-11 21:33:50 +02:00
parent e14b203fe2
commit fda5b84d5d
No known key found for this signature in database
GPG key ID: 2609A01E695523E3
5 changed files with 84 additions and 55 deletions

View file

@ -6,12 +6,12 @@
"display": "standalone",
"icons": [
{
"src": "/code-192.png",
"src": "code-192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/code-512.png",
"src": "code-512.png",
"type": "image/png",
"sizes": "512x512"
}

View file

@ -11,8 +11,8 @@
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Code">
<link rel="apple-touch-icon" href="/code-192.png" />
<link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
,
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@ -26,22 +26,23 @@
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
</head>
<body aria-label="">
</body>
<!-- Startup (do not modify order of script tags!) -->
<script src="./static/out/vs/loader.js"></script>
<script src="./static/out/vs/webPackagePaths.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/webPackagePaths.js"></script>
<script>
let baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
Object.keys(self.webPackagePaths).map(function (key, index) {
self.webPackagePaths[key] = `${window.location.origin}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
self.webPackagePaths[key] = `${baseUrl}/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
});
require.config({
baseUrl: `${window.location.origin}/static/out`,
baseUrl: `${baseUrl}/out`,
recordStats: true,
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {

View file

@ -11,7 +11,7 @@
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Code">
<link rel="apple-touch-icon" href="/code-192.png" />
<link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@ -23,9 +23,9 @@
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
</head>
@ -33,14 +33,15 @@
</body>
<!-- Startup (do not modify order of script tags!) -->
<script src="./static/out/vs/loader.js"></script>
<script src="./static/out/vs/webPackagePaths.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/webPackagePaths.js"></script>
<script>
let baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
Object.keys(self.webPackagePaths).map(function (key, index) {
self.webPackagePaths[key] = `${window.location.origin}/static/node_modules/${key}/${self.webPackagePaths[key]}`;
self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`;
});
require.config({
baseUrl: `${window.location.origin}/static/out`,
baseUrl: `${baseUrl}/out`,
recordStats: true,
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
@ -53,7 +54,7 @@
<script>
performance.mark('code/willLoadWorkbenchMain');
</script>
<script src="./static/out/vs/workbench/workbench.web.main.nls.js"></script>
<script src="./static/out/vs/workbench/workbench.web.main.js"></script>
<script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.nls.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.js"></script>
</html>

View file

@ -192,6 +192,10 @@ class LocalStorageURLCallbackProvider extends Disposable implements IURLCallback
private checkCallbacksTimeout: unknown | undefined = undefined;
private onDidChangeLocalStorageDisposable: IDisposable | undefined;
constructor(private readonly _callbackRoute: string) {
super();
}
create(options: Partial<UriComponents> = {}): URI {
const id = ++LocalStorageURLCallbackProvider.REQUEST_ID;
const queryParams: string[] = [`vscode-reqid=${id}`];
@ -215,7 +219,7 @@ class LocalStorageURLCallbackProvider extends Disposable implements IURLCallback
this.startListening();
}
return URI.parse(window.location.href).with({ path: '/callback', query: queryParams.join('&') });
return URI.parse(window.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
}
private startListening(): void {
@ -492,7 +496,7 @@ function doCreateUri(path: string, queryValues: Map<string, string>): URI {
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}
const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
// Create workbench
create(document.body, {
@ -501,7 +505,7 @@ function doCreateUri(path: string, queryValues: Map<string, string>): URI {
enabled: config.settingsSyncOptions.enabled,
} : undefined,
workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider() // with a remote, we don't use a local credentials provider
});
})();

View file

@ -78,11 +78,15 @@ export async function serveFile(logService: ILogService, req: http.IncomingMessa
}
const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
const CHARCODE_SLASH = '/'.charCodeAt(0);
export class WebClientServer {
private readonly _webExtensionResourceUrlTemplate: URI | undefined;
private readonly _staticRoute;
private readonly _callbackRoute;
constructor(
private readonly _connectionToken: ServerConnectionToken,
@IServerEnvironmentService private readonly _environmentService: IServerEnvironmentService,
@ -91,6 +95,9 @@ export class WebClientServer {
@IProductService private readonly _productService: IProductService,
) {
this._webExtensionResourceUrlTemplate = this._productService.extensionsGallery?.resourceUrlTemplate ? URI.parse(this._productService.extensionsGallery.resourceUrlTemplate) : undefined;
const qualityAndCommit = `${_productService.quality ?? 'oss'}-${_productService.commit ?? 'dev'}`;
this._staticRoute = `/${qualityAndCommit}/static`;
this._callbackRoute = `/${qualityAndCommit}/callback`;
}
/**
@ -102,16 +109,13 @@ export class WebClientServer {
try {
const pathname = parsedUrl.pathname!;
if (pathname === '/favicon.ico' || pathname === '/manifest.json' || pathname === '/code-192.png' || pathname === '/code-512.png') {
return serveFile(this._logService, req, res, join(APP_ROOT, 'resources', 'server', pathname.substr(1)));
}
if (/^\/static\//.test(pathname)) {
if (pathname.startsWith(this._staticRoute) && pathname.charCodeAt(this._staticRoute.length) === CHARCODE_SLASH) {
return this._handleStatic(req, res, parsedUrl);
}
if (pathname === '/') {
return this._handleRoot(req, res, parsedUrl);
}
if (pathname === '/callback') {
if (pathname === this._callbackRoute) {
// callback support
return this._handleCallback(res);
}
@ -137,9 +141,9 @@ export class WebClientServer {
// Strip `/static/` from the path
const normalizedPathname = decodeURIComponent(parsedUrl.pathname!); // support paths that are uri-encoded (e.g. spaces => %20)
const relativeFilePath = normalize(normalizedPathname.substr('/static/'.length));
const relativeFilePath = normalizedPathname.substring(this._staticRoute.length + 1);
const filePath = join(APP_ROOT, relativeFilePath);
const filePath = join(APP_ROOT, relativeFilePath); // join also normalizes the path
if (!isEqualOrParent(filePath, APP_ROOT, !isLinux)) {
return serveError(req, res, 400, `Bad request.`);
}
@ -259,8 +263,8 @@ export class WebClientServer {
return serveError(req, res, 400, `Bad request.`);
}
function escapeAttribute(value: string): string {
return value.replace(/"/g, '&quot;');
function asJSON(value: unknown): string {
return JSON.stringify(value).replace(/"/g, '&quot;');
}
let _wrapWebWorkerExtHostInIframe: undefined | false = undefined;
@ -279,28 +283,47 @@ export class WebClientServer {
accessToken: this._environmentService.args['github-auth'],
scopes: [['user:email'], ['repo']]
} : undefined;
const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority,
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
scheme: 'http',
authority: remoteAuthority,
path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
}).toString(true)
} : undefined
}
})))
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '');
const workbenchWebConfiguration = {
remoteAuthority,
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
scheme: 'http',
authority: remoteAuthority,
path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
}).toString(true)
} : undefined
},
callbackRoute: this._callbackRoute
};
const values: { [key: string]: string } = {
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
WORKBENCH_WEB_BASE_URL: this._staticRoute,
};
//if (!this._environmentService.isBuilt) {
//values.WORKBENCH_BUILTIN_EXTENSIONS = //get built in extensions
//}
let data;
try {
const workbenchTemplate = (await util.promisify(fs.readFile)(filePath)).toString();
data = workbenchTemplate.replace(/\{\{([^}]+)\}\}/g, (_, key) => values[key] ?? 'undefined');
} catch (e) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
return res.end('Not found');
}
const cspDirectives = [
'default-src \'self\';',