diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index ad6c84bc650..49ff0bdce96 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -148,7 +148,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook)); const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors)); const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService)); - const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, initData.environment)); + const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, { ...initData.environment, remote: initData.remote })); const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol, extHostLogService)); const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, uriTransformer, extHostDocuments, extHostCommands, extHostDiagnostics, extHostLogService, extHostApiDeprecation)); const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures)); @@ -161,7 +161,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol)); const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol)); const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands)); - const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment, extHostWorkspace, extHostLogService, extHostApiDeprecation)); + const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, { ...initData.environment, remote: initData.remote }, extHostWorkspace, extHostLogService, extHostApiDeprecation)); const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace)); const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels)); const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews)); diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 53df9db9f42..3f91dd9e8f9 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -184,7 +184,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message); }, asWebviewUri(uri: URI) { - return asWebviewUri(that._initData.environment, String(handle), uri); + return asWebviewUri({ ...that._initData.environment, remote: that._initData.remote }, String(handle), uri); }, // --- priority updateNotebookAffinity(notebook, priority) { diff --git a/src/vs/workbench/api/common/shared/webview.ts b/src/vs/workbench/api/common/shared/webview.ts index 851a56985db..f1de57db839 100644 --- a/src/vs/workbench/api/common/shared/webview.ts +++ b/src/vs/workbench/api/common/shared/webview.ts @@ -10,21 +10,29 @@ export interface WebviewInitData { readonly isExtensionDevelopmentDebug: boolean; readonly webviewResourceRoot: string; readonly webviewCspSource: string; + readonly remote: { readonly authority: string | undefined }; } +/** + * Construct a uri that can load resources inside a webview + * + * We encode the resource component of the uri so that on the main thread + * we know where to load the resource from (remote or truly local): + * + * ```txt + * /remote-authority?/scheme/resource-authority/path... + * ``` + */ export function asWebviewUri( initData: WebviewInitData, uuid: string, resource: vscode.Uri, ): vscode.Uri { const uri = initData.webviewResourceRoot - // Make sure we preserve the scheme of the resource but convert it into a normal path segment - // The scheme is important as we need to know if we are requesting a local or a remote resource. - .replace('{{resource}}', resource.scheme + withoutScheme(resource)) + .replace('{{resource}}', (initData.remote.authority ?? '') + '/' + resource.scheme + '/' + encodeURIComponent(resource.authority) + resource.path) .replace('{{uuid}}', uuid); - return URI.parse(uri); -} - -function withoutScheme(resource: vscode.Uri): string { - return resource.toString().replace(/^\S+?:/, ''); + return URI.parse(uri).with({ + fragment: resource.fragment, + query: resource.query, + }); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 6c9e63fae23..024304755bf 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -24,6 +24,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { asWebviewUri } from 'vs/workbench/api/common/shared/webview'; import { CellEditState, ICellOutputViewModel, ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping'; @@ -31,7 +32,6 @@ import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/vie import { INotebookKernel, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview'; -import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; interface BaseToWebviewMessage { @@ -731,13 +731,13 @@ export class BackLayerWebView extends Disposable { if (!subRenderers.has(renderer.dependsOn)) { subRenderers.set(renderer.dependsOn, []); } - const entryPoint = asWebviewUri(this.environmentService, this.id, renderer.entrypoint); + const entryPoint = this.asWebviewUri(renderer.entrypoint); subRenderers.get(renderer.dependsOn)!.push({ entrypoint: entryPoint.toString(true) }); } } return topLevelMarkdownRenderers.map((renderer) => { - const src = asWebviewUri(this.environmentService, this.id, renderer.entrypoint); + const src = this.asWebviewUri(renderer.entrypoint); return { entrypoint: src.toString(), dependencies: subRenderers.get(renderer.id) || [], @@ -745,6 +745,15 @@ export class BackLayerWebView extends Disposable { }); } + private asWebviewUri(uri: URI) { + return asWebviewUri({ + isExtensionDevelopmentDebug: this.environmentService.isExtensionDevelopment, + webviewCspSource: this.environmentService.webviewCspSource, + webviewResourceRoot: this.environmentService.webviewResourceRoot, + remote: { authority: undefined } // TODO + }, this.id, uri); + } + postKernelMessage(message: any) { this._sendMessageToWebview({ __vscode_notebook_message: true, @@ -775,11 +784,11 @@ export class BackLayerWebView extends Disposable { resolveFunc = resolve; }); - const baseUrl = asWebviewUri(this.environmentService, this.id, dirname(this.documentUri)); + const baseUrl = this.asWebviewUri(dirname(this.documentUri)); if (!isWeb) { const loaderUri = FileAccess.asFileUri('vs/loader.js', require); - const loader = asWebviewUri(this.environmentService, this.id, loaderUri); + const loader = this.asWebviewUri(loaderUri); coreDependencies = `