From f4c58486f4a33b8c61f30a244374ef0d27dc19c3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 10 Oct 2022 21:15:14 -0700 Subject: [PATCH] Run all webview panels of a given viewtype in the same origin (#163236) For #132464 --- .../api/browser/mainThreadWebviewPanels.ts | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts index d33c3fba499f2..d50996eacd172 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts @@ -6,12 +6,16 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { Disposable, DisposableMap } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; +import { generateUuid } from 'vs/base/common/uuid'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { MainThreadWebviews, reviveWebviewContentOptions, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput'; import { WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager'; @@ -75,6 +79,43 @@ class WebviewViewTypeTransformer { } } +/** + * Stores the unique origins for webviews. + * + * These are randomly generated, but keyed on extension and webview viewType. + */ +class WebviewOriginStore { + + private readonly memento: Memento; + private readonly state: MementoObject; + + constructor( + storageKey: string, + @IStorageService storageService: IStorageService, + ) { + this.memento = new Memento(storageKey, storageService); + this.state = this.memento.getMemento(StorageScope.APPLICATION, StorageTarget.MACHINE); + } + + public getOrigin(extId: ExtensionIdentifier, viewType: string): string { + const key = this.getKey(extId, viewType); + + const existing = this.state[key]; + if (existing && typeof existing === 'string') { + return existing; + } + + const newOrigin = generateUuid(); + this.state[key] = newOrigin; + this.memento.saveMemento(); + return newOrigin; + } + + private getKey(extId: ExtensionIdentifier, viewType: string): string { + return JSON.stringify([extId.value, viewType]); + } +} + export class MainThreadWebviewPanels extends Disposable implements extHostProtocol.MainThreadWebviewPanelsShape { private readonly webviewPanelViewType = new WebviewViewTypeTransformer('mainThreadWebview-'); @@ -85,6 +126,8 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc private readonly _revivers = this._register(new DisposableMap()); + private readonly webviewOriginStore: WebviewOriginStore; + constructor( context: IExtHostContext, private readonly _mainThreadWebviews: MainThreadWebviews, @@ -92,11 +135,14 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, @IEditorService private readonly _editorService: IEditorService, @IExtensionService extensionService: IExtensionService, + @IStorageService storageService: IStorageService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, ) { super(); + this.webviewOriginStore = new WebviewOriginStore('mainThreadWebviewPanel.origins', storageService); + this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviewPanels); this._register(_editorService.onDidActiveEditorChange(() => { @@ -152,9 +198,11 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc } : {}; const extension = reviveWebviewExtension(extensionData); + const origin = this.webviewOriginStore.getOrigin(extension.id, viewType); const webview = this._webviewWorkbenchService.openWebview({ id: handle, + origin, providedViewType: viewType, options: reviveWebviewOptions(initData.panelOptions), contentOptions: reviveWebviewContentOptions(initData.webviewOptions),