mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-30 13:31:07 +01:00
extract some COI handle into network-util, add --enable-coi command line flag and adopt in main handler
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { COI } from 'vs/base/common/network';
|
||||||
import { globals } from 'vs/base/common/platform';
|
import { globals } from 'vs/base/common/platform';
|
||||||
import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker';
|
import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker';
|
||||||
|
|
||||||
@@ -41,7 +42,12 @@ export function getWorkerBootstrapUrl(scriptPath: string, label: string): string
|
|||||||
const blob = new Blob([js], { type: 'application/javascript' });
|
const blob = new Blob([js], { type: 'application/javascript' });
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
return scriptPath + '#' + label;
|
|
||||||
|
const result = new URL(scriptPath);
|
||||||
|
COI.addSearchParam(result.searchParams, true, true);
|
||||||
|
result.hash = label;
|
||||||
|
return result.href;
|
||||||
|
|
||||||
}
|
}
|
||||||
// ESM-comment-end
|
// ESM-comment-end
|
||||||
|
|
||||||
|
|||||||
@@ -251,3 +251,53 @@ class FileAccessImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FileAccess = new FileAccessImpl();
|
export const FileAccess = new FileAccessImpl();
|
||||||
|
|
||||||
|
|
||||||
|
export namespace COI {
|
||||||
|
|
||||||
|
const coiHeaders = new Map<'3' | '2' | '1' | string, Record<string, string>>([
|
||||||
|
['1', { 'Cross-Origin-Opener-Policy': 'same-origin' }],
|
||||||
|
['2', { 'Cross-Origin-Embedder-Policy': 'require-corp' }],
|
||||||
|
['3', { 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Embedder-Policy': 'require-corp' }],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const CoopAndCoep = Object.freeze(coiHeaders.get('3'));
|
||||||
|
|
||||||
|
const coiSearchParamName = 'vscode-coi';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract desired headers from `vscode-coi` invocation
|
||||||
|
*/
|
||||||
|
export function getHeadersFromQuery(url: string | URI | URL): Record<string, string> | undefined {
|
||||||
|
let params: URLSearchParams | undefined;
|
||||||
|
if (typeof url === 'string') {
|
||||||
|
params = new URL(url).searchParams;
|
||||||
|
} else if (url instanceof URL) {
|
||||||
|
params = url.searchParams;
|
||||||
|
} else if (URI.isUri(url)) {
|
||||||
|
params = new URL(url.toString(true)).searchParams;
|
||||||
|
}
|
||||||
|
const value = params?.get(coiSearchParamName);
|
||||||
|
if (!value) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return coiHeaders.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the `vscode-coi` query attribute based on wanting `COOP` and `COEP`. Will be a noop when `crossOriginIsolated`
|
||||||
|
* isn't enabled the current context
|
||||||
|
*/
|
||||||
|
export function addSearchParam(urlOrSearch: URLSearchParams | Record<string, string>, coop: boolean, coep: boolean): void {
|
||||||
|
if (!globalThis.crossOriginIsolated) {
|
||||||
|
// depends on the current context being COI
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const value = coop && coep ? '3' : coep ? '2' : '1';
|
||||||
|
if (urlOrSearch instanceof URLSearchParams) {
|
||||||
|
urlOrSearch.set(coiSearchParamName, value);
|
||||||
|
} else {
|
||||||
|
(<Record<string, string>>urlOrSearch)[coiSearchParamName] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ export interface NativeParsedArgs {
|
|||||||
'profile'?: string;
|
'profile'?: string;
|
||||||
'profile-temp'?: boolean;
|
'profile-temp'?: boolean;
|
||||||
|
|
||||||
|
'enable-coi'?: boolean;
|
||||||
|
|
||||||
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
||||||
'no-proxy-server'?: boolean;
|
'no-proxy-server'?: boolean;
|
||||||
'no-sandbox'?: boolean;
|
'no-sandbox'?: boolean;
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ export interface INativeEnvironmentService extends IEnvironmentService {
|
|||||||
// --- use keytar for credentials
|
// --- use keytar for credentials
|
||||||
disableKeytar?: boolean;
|
disableKeytar?: boolean;
|
||||||
|
|
||||||
|
crossOriginIsolated?: boolean;
|
||||||
|
|
||||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
//
|
//
|
||||||
// NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE.
|
// NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE.
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export class EnvironmentMainService extends NativeEnvironmentService implements
|
|||||||
@memoize
|
@memoize
|
||||||
get disableKeytar(): boolean { return !!this.args['disable-keytar']; }
|
get disableKeytar(): boolean { return !!this.args['disable-keytar']; }
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
get crossOriginIsolated(): boolean { return !!this.args['enable-coi']; }
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
get codeCachePath(): string | undefined { return process.env['VSCODE_CODE_CACHE_PATH'] || undefined; }
|
get codeCachePath(): string | undefined { return process.env['VSCODE_CODE_CACHE_PATH'] || undefined; }
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
|
|||||||
'editSessionId': { type: 'string' },
|
'editSessionId': { type: 'string' },
|
||||||
'locate-shell-integration-path': { type: 'string', args: ['bash', 'pwsh', 'zsh', 'fish'] },
|
'locate-shell-integration-path': { type: 'string', args: ['bash', 'pwsh', 'zsh', 'fish'] },
|
||||||
|
|
||||||
|
'enable-coi': { type: 'boolean' },
|
||||||
|
|
||||||
// chromium flags
|
// chromium flags
|
||||||
'no-proxy-server': { type: 'boolean' },
|
'no-proxy-server': { type: 'boolean' },
|
||||||
// Minimist incorrectly parses keys that start with `--no`
|
// Minimist incorrectly parses keys that start with `--no`
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { session } from 'electron';
|
|||||||
import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain';
|
import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain';
|
||||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { TernarySearchTree } from 'vs/base/common/map';
|
import { TernarySearchTree } from 'vs/base/common/map';
|
||||||
import { FileAccess, Schemas } from 'vs/base/common/network';
|
import { COI, FileAccess, Schemas } from 'vs/base/common/network';
|
||||||
import { extname, normalize } from 'vs/base/common/path';
|
import { extname, normalize } from 'vs/base/common/path';
|
||||||
import { isLinux } from 'vs/base/common/platform';
|
import { isLinux } from 'vs/base/common/platform';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
@@ -27,7 +27,7 @@ export class ProtocolMainService extends Disposable implements IProtocolMainServ
|
|||||||
private readonly validExtensions = new Set(['.svg', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']); // https://github.com/microsoft/vscode/issues/119384
|
private readonly validExtensions = new Set(['.svg', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']); // https://github.com/microsoft/vscode/issues/119384
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@INativeEnvironmentService environmentService: INativeEnvironmentService,
|
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
|
||||||
@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,
|
@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,
|
||||||
@ILogService private readonly logService: ILogService
|
@ILogService private readonly logService: ILogService
|
||||||
) {
|
) {
|
||||||
@@ -94,9 +94,18 @@ export class ProtocolMainService extends Disposable implements IProtocolMainServ
|
|||||||
private handleResourceRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback): void {
|
private handleResourceRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback): void {
|
||||||
const path = this.requestToNormalizedFilePath(request);
|
const path = this.requestToNormalizedFilePath(request);
|
||||||
|
|
||||||
|
let headers: Record<string, string> | undefined;
|
||||||
|
if (this.environmentService.crossOriginIsolated) {
|
||||||
|
if (path.endsWith('/workbench.html')) {
|
||||||
|
headers = COI.CoopAndCoep;
|
||||||
|
} else {
|
||||||
|
headers = COI.getHeadersFromQuery(request.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first check by validRoots
|
// first check by validRoots
|
||||||
if (this.validRoots.findSubstr(path)) {
|
if (this.validRoots.findSubstr(path)) {
|
||||||
return callback({ path });
|
return callback({ path, headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
// then check by validExtensions
|
// then check by validExtensions
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { streamToBuffer, VSBufferReadableStream } from 'vs/base/common/buffer';
|
|||||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { Schemas } from 'vs/base/common/network';
|
import { COI, Schemas } from 'vs/base/common/network';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
@@ -532,9 +532,8 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
|
|||||||
params.purpose = options.purpose;
|
params.purpose = options.purpose;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalThis.crossOriginIsolated) {
|
|
||||||
params['vscode-coi'] = '3'; /*COOP+COEP*/
|
COI.addSearchParam(params, true, true);
|
||||||
}
|
|
||||||
|
|
||||||
const queryString = new URLSearchParams(params).toString();
|
const queryString = new URLSearchParams(params).toString();
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { generateUuid } from 'vs/base/common/uuid';
|
|||||||
import { canceled, onUnexpectedError } from 'vs/base/common/errors';
|
import { canceled, onUnexpectedError } from 'vs/base/common/errors';
|
||||||
import { Barrier } from 'vs/base/common/async';
|
import { Barrier } from 'vs/base/common/async';
|
||||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||||
import { FileAccess } from 'vs/base/common/network';
|
import { COI, FileAccess } from 'vs/base/common/network';
|
||||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||||
import { parentOriginHash } from 'vs/workbench/browser/webview';
|
import { parentOriginHash } from 'vs/workbench/browser/webview';
|
||||||
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||||
@@ -86,9 +86,8 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
|||||||
if (this._environmentService.debugExtensionHost && this._environmentService.debugRenderer) {
|
if (this._environmentService.debugExtensionHost && this._environmentService.debugRenderer) {
|
||||||
suffixSearchParams.set('debugged', '1');
|
suffixSearchParams.set('debugged', '1');
|
||||||
}
|
}
|
||||||
if (globalThis.crossOriginIsolated) {
|
COI.addSearchParam(suffixSearchParams, true, true);
|
||||||
suffixSearchParams.set('vscode-coi', '3' /*COOP+COEP*/);
|
|
||||||
}
|
|
||||||
const suffix = `?${suffixSearchParams.toString()}`;
|
const suffix = `?${suffixSearchParams.toString()}`;
|
||||||
|
|
||||||
const iframeModulePath = 'vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html';
|
const iframeModulePath = 'vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html';
|
||||||
|
|||||||
Reference in New Issue
Block a user