UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

159 lines (158 loc) 6.56 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc, d; if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); }; }; import { session } from 'electron'; import { Disposable, toDisposable } from '@sussudio/base/common/lifecycle.mjs'; import { COI, FileAccess, Schemas } from '@sussudio/base/common/network.mjs'; import { basename, extname, normalize } from '@sussudio/base/common/path.mjs'; import { isLinux } from '@sussudio/base/common/platform.mjs'; import { TernarySearchTree } from '@sussudio/base/common/ternarySearchTree.mjs'; import { URI } from '@sussudio/base/common/uri.mjs'; import { generateUuid } from '@sussudio/base/common/uuid.mjs'; import { validatedIpcMain } from '@sussudio/base/parts/ipc/electron-main/ipcMain.mjs'; import { INativeEnvironmentService } from '../../environment/common/environment.mjs'; import { ILogService } from '../../log/common/log.mjs'; import { IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.mjs'; let ProtocolMainService = class ProtocolMainService extends Disposable { environmentService; logService; validRoots = TernarySearchTree.forPaths(!isLinux); validExtensions = new Set(['.svg', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']); // https://github.com/microsoft/vscode/issues/119384 constructor(environmentService, userDataProfilesService, logService) { super(); this.environmentService = environmentService; this.logService = logService; // Define an initial set of roots we allow loading from // - appRoot : all files installed as part of the app // - extensions : all files shipped from extensions // - storage : all files in global and workspace storage (https://github.com/microsoft/vscode/issues/116735) this.addValidFileRoot(environmentService.appRoot); this.addValidFileRoot(environmentService.extensionsPath); this.addValidFileRoot(userDataProfilesService.defaultProfile.globalStorageHome.fsPath); this.addValidFileRoot(environmentService.workspaceStorageHome.fsPath); // Handle protocols this.handleProtocols(); } handleProtocols() { const { defaultSession } = session; // Register vscode-file:// handler defaultSession.protocol.registerFileProtocol(Schemas.vscodeFileResource, (request, callback) => this.handleResourceRequest(request, callback), ); // Block any file:// access defaultSession.protocol.interceptFileProtocol(Schemas.file, (request, callback) => this.handleFileRequest(request, callback), ); // Cleanup this._register( toDisposable(() => { defaultSession.protocol.unregisterProtocol(Schemas.vscodeFileResource); defaultSession.protocol.uninterceptProtocol(Schemas.file); }), ); } addValidFileRoot(root) { // Pass to `normalize` because we later also do the // same for all paths to check against. const normalizedRoot = normalize(root); if (!this.validRoots.get(normalizedRoot)) { this.validRoots.set(normalizedRoot, true); return toDisposable(() => this.validRoots.delete(normalizedRoot)); } return Disposable.None; } //#region file:// handleFileRequest(request, callback) { const uri = URI.parse(request.url); this.logService.error( `Refused to load resource ${uri.fsPath} from ${Schemas.file}: protocol (original URL: ${request.url})`, ); return callback({ error: -3 /* ABORTED */ }); } //#endregion //#region vscode-file:// handleResourceRequest(request, callback) { const path = this.requestToNormalizedFilePath(request); let headers; if (this.environmentService.crossOriginIsolated) { if (basename(path) === 'workbench.html' || basename(path) === 'workbench-dev.html') { headers = COI.CoopAndCoep; } else { headers = COI.getHeadersFromQuery(request.url); } } // first check by validRoots if (this.validRoots.findSubstr(path)) { return callback({ path, headers }); } // then check by validExtensions if (this.validExtensions.has(extname(path).toLowerCase())) { return callback({ path }); } // finally block to load the resource this.logService.error( `${Schemas.vscodeFileResource}: Refused to load resource ${path} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`, ); return callback({ error: -3 /* ABORTED */ }); } requestToNormalizedFilePath(request) { // 1.) Use `URI.parse()` util from us to convert the raw // URL into our URI. const requestUri = URI.parse(request.url); // 2.) Use `FileAccess.asFileUri` to convert back from a // `vscode-file:` URI to a `file:` URI. const unnormalizedFileUri = FileAccess.uriToFileUri(requestUri); // 3.) Strip anything from the URI that could result in // relative paths (such as "..") by using `normalize` return normalize(unnormalizedFileUri.fsPath); } //#endregion //#region IPC Object URLs createIPCObjectUrl() { let obj = undefined; // Create unique URI const resource = URI.from({ scheme: 'vscode', path: generateUuid(), }); // Install IPC handler const channel = resource.toString(); const handler = async () => obj; validatedIpcMain.handle(channel, handler); this.logService.trace(`IPC Object URL: Registered new channel ${channel}.`); return { resource, update: (updatedObj) => (obj = updatedObj), dispose: () => { this.logService.trace(`IPC Object URL: Removed channel ${channel}.`); validatedIpcMain.removeHandler(channel); }, }; } }; ProtocolMainService = __decorate( [__param(0, INativeEnvironmentService), __param(1, IUserDataProfilesService), __param(2, ILogService)], ProtocolMainService, ); export { ProtocolMainService };