|
| 1 | +/*--------------------------------------------------------------------------------------------- |
| 2 | + * Copyright (c) Microsoft Corporation. All rights reserved. |
| 3 | + * Licensed under the MIT License. See License.txt in the project root for license information. |
| 4 | + *--------------------------------------------------------------------------------------------*/ |
| 5 | + |
| 6 | +import { VSBuffer, encodeBase64 } from 'vs/base/common/buffer'; |
| 7 | +import { Event } from 'vs/base/common/event'; |
| 8 | +import { Disposable } from 'vs/base/common/lifecycle'; |
| 9 | +import { getMediaOrTextMime } from 'vs/base/common/mime'; |
| 10 | +import { Schemas } from 'vs/base/common/network'; |
| 11 | +import { URI } from 'vs/base/common/uri'; |
| 12 | +import { IServerChannel } from 'vs/base/parts/ipc/common/ipc'; |
| 13 | +import { FileOperationError, FileOperationResult, IFileContent, IFileService } from 'vs/platform/files/common/files'; |
| 14 | +import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; |
| 15 | +import { NODE_REMOTE_RESOURCE_CHANNEL_NAME, NODE_REMOTE_RESOURCE_IPC_METHOD_NAME, NodeRemoteResourceResponse } from 'vs/platform/remote/common/electronRemoteResources'; |
| 16 | + |
| 17 | +export class ElectronRemoteResourceLoader extends Disposable { |
| 18 | + constructor( |
| 19 | + private readonly windowId: number, |
| 20 | + @IMainProcessService mainProcessService: IMainProcessService, |
| 21 | + @IFileService private readonly fileService: IFileService, |
| 22 | + ) { |
| 23 | + super(); |
| 24 | + |
| 25 | + const channel: IServerChannel = { |
| 26 | + listen<T>(_: unknown, event: string): Event<T> { |
| 27 | + throw new Error(`Event not found: ${event}`); |
| 28 | + }, |
| 29 | + |
| 30 | + call: (_: unknown, command: string, arg?: any): Promise<any> => { |
| 31 | + switch (command) { |
| 32 | + case NODE_REMOTE_RESOURCE_IPC_METHOD_NAME: return this.doRequest(URI.revive(arg[0])); |
| 33 | + } |
| 34 | + |
| 35 | + throw new Error(`Call not found: ${command}`); |
| 36 | + } |
| 37 | + }; |
| 38 | + |
| 39 | + mainProcessService.registerChannel(NODE_REMOTE_RESOURCE_CHANNEL_NAME, channel); |
| 40 | + } |
| 41 | + |
| 42 | + private async doRequest(uri: URI): Promise<NodeRemoteResourceResponse> { |
| 43 | + let content: IFileContent; |
| 44 | + try { |
| 45 | + const params = new URLSearchParams(uri.query); |
| 46 | + const actual = uri.with({ |
| 47 | + scheme: params.get('scheme')!, |
| 48 | + authority: params.get('authority')!, |
| 49 | + query: '', |
| 50 | + }); |
| 51 | + content = await this.fileService.readFile(actual); |
| 52 | + } catch (e) { |
| 53 | + const str = encodeBase64(VSBuffer.fromString(e.message)); |
| 54 | + if (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_NOT_FOUND) { |
| 55 | + return { statusCode: 404, body: str }; |
| 56 | + } else { |
| 57 | + return { statusCode: 500, body: str }; |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + const mimeType = uri.path && getMediaOrTextMime(uri.path); |
| 62 | + return { statusCode: 200, body: encodeBase64(content.value), mimeType }; |
| 63 | + } |
| 64 | + |
| 65 | + public getResourceUriProvider() { |
| 66 | + return (uri: URI) => uri.with({ |
| 67 | + scheme: Schemas.vscodeRemoteResource, |
| 68 | + authority: `window:${this.windowId}`, |
| 69 | + query: new URLSearchParams({ authority: uri.authority, scheme: uri.scheme }).toString(), |
| 70 | + }); |
| 71 | + } |
| 72 | +} |
0 commit comments