diff --git a/packages/plugin-ext/src/common/hash-uuid.ts b/packages/plugin-ext/src/common/hash-uuid.ts new file mode 100644 index 0000000000000..db6a7a7086fc1 --- /dev/null +++ b/packages/plugin-ext/src/common/hash-uuid.ts @@ -0,0 +1,27 @@ +// ***************************************************************************** +// Copyright (C) 2024 EclipseSource and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { v5 } from 'uuid'; + +const NAMESPACE = '4c90ee4f-d952-44b1-83ca-f04121ab8e05'; +/** + * This function will hash the given value. The result will be a uuid. + * @param value the string to hash + * @returns a uuid + */ +export function hashValue(value: string): string { + return v5(value, NAMESPACE); +} diff --git a/packages/plugin-ext/src/main/browser/webview/webview-widget-factory.ts b/packages/plugin-ext/src/main/browser/webview/webview-widget-factory.ts index aec77f37c448e..3df41ad91a5e3 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview-widget-factory.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview-widget-factory.ts @@ -17,8 +17,7 @@ import { interfaces } from '@theia/core/shared/inversify'; import { WebviewWidget, WebviewWidgetIdentifier, WebviewWidgetExternalEndpoint } from './webview'; import { WebviewEnvironment } from './webview-environment'; -import { StorageService } from '@theia/core/lib/browser'; -import { v4 } from 'uuid'; +import { hashValue } from '../../../common/hash-uuid'; export class WebviewWidgetFactory { @@ -32,7 +31,7 @@ export class WebviewWidgetFactory { async createWidget(identifier: WebviewWidgetIdentifier): Promise { const externalEndpoint = await this.container.get(WebviewEnvironment).externalEndpoint(); - let endpoint = externalEndpoint.replace('{{uuid}}', identifier.viewId ? await this.getOrigin(this.container.get(StorageService), identifier.viewId) : identifier.id); + let endpoint = externalEndpoint.replace('{{uuid}}', identifier.viewId ? hashValue(identifier.viewId) : identifier.id); if (endpoint[endpoint.length - 1] === '/') { endpoint = endpoint.slice(0, endpoint.length - 1); } @@ -42,16 +41,4 @@ export class WebviewWidgetFactory { return child.get(WebviewWidget); } - protected async getOrigin(storageService: StorageService, viewId: string): Promise { - const key = 'plugin-view-registry.origin.' + viewId; - const origin = await storageService.getData(key); - if (!origin) { - const newOrigin = v4(); - storageService.setData(key, newOrigin); - return newOrigin; - } else { - return origin; - } - } - } diff --git a/packages/plugin-ext/src/plugin/webview-views.ts b/packages/plugin-ext/src/plugin/webview-views.ts index 04d66415b79e3..259c7fa38730c 100644 --- a/packages/plugin-ext/src/plugin/webview-views.ts +++ b/packages/plugin-ext/src/plugin/webview-views.ts @@ -27,6 +27,7 @@ import { WebviewImpl, WebviewsExtImpl } from './webviews'; import { WebviewViewProvider } from '@theia/plugin'; import { Emitter, Event } from '@theia/core/lib/common/event'; import * as theia from '@theia/plugin'; +import { hashValue } from '../common/hash-uuid'; export class WebviewViewsExtImpl implements WebviewViewsExt { @@ -82,7 +83,7 @@ export class WebviewViewsExtImpl implements WebviewViewsExt { const { provider, plugin } = entry; - const webviewNoPanel = this.webviewsExt.createNewWebview({}, plugin, handle); + const webviewNoPanel = this.webviewsExt.createNewWebview({}, plugin, handle, hashValue(viewType)); const revivedView = new WebviewViewExtImpl(handle, this.proxy, viewType, title, webviewNoPanel, true); this.webviewViews.set(handle, revivedView); await provider.resolveWebviewView(revivedView, { state }, cancellation); diff --git a/packages/plugin-ext/src/plugin/webviews.ts b/packages/plugin-ext/src/plugin/webviews.ts index c107ced1af6be..90959d9bda290 100644 --- a/packages/plugin-ext/src/plugin/webviews.ts +++ b/packages/plugin-ext/src/plugin/webviews.ts @@ -23,6 +23,7 @@ import { fromViewColumn, toViewColumn, toWebviewPanelShowOptions } from './type- import { Disposable, WebviewPanelTargetArea, URI } from './types-impl'; import { WorkspaceExtImpl } from './workspace'; import { PluginIconPath } from './plugin-icon-path'; +import { hashValue } from '../common/hash-uuid'; export class WebviewsExtImpl implements WebviewsExt { private readonly proxy: WebviewsMain; @@ -96,7 +97,7 @@ export class WebviewsExtImpl implements WebviewsExt { } const { serializer, plugin } = entry; - const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin); + const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin, hashValue(viewType)); const revivedPanel = new WebviewPanelImpl(viewId, this.proxy, viewType, title, toViewColumn(viewState.position)!, options, webview); revivedPanel.setActive(viewState.active); revivedPanel.setVisible(viewState.visible); @@ -131,7 +132,7 @@ export class WebviewsExtImpl implements WebviewsExt { throw new Error('Webviews are not initialized'); } const webviewShowOptions = toWebviewPanelShowOptions(showOptions); - const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin); + const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin, hashValue(viewType)); const panel = new WebviewPanelImpl(viewId, this.proxy, viewType, title, webviewShowOptions, options, webview); this.webviewPanels.set(viewId, panel); return panel; @@ -140,12 +141,13 @@ export class WebviewsExtImpl implements WebviewsExt { createNewWebview( options: theia.WebviewPanelOptions & theia.WebviewOptions, plugin: Plugin, - viewId: string + viewId: string, + origin?: string ): WebviewImpl { if (!this.initData) { throw new Error('Webviews are not initialized'); } - const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin); + const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin, origin); this.webviews.set(viewId, webview); return webview; } @@ -201,7 +203,8 @@ export class WebviewImpl implements theia.Webview { options: theia.WebviewOptions, private readonly initData: WebviewInitData, private readonly workspace: WorkspaceExtImpl, - readonly plugin: Plugin + readonly plugin: Plugin, + private readonly origin?: string ) { this._options = options; } @@ -219,12 +222,12 @@ export class WebviewImpl implements theia.Webview { .replace('{{scheme}}', resource.scheme) .replace('{{authority}}', resource.authority) .replace('{{path}}', resource.path.replace(/^\//, '')) - .replace('{{uuid}}', this.viewId); + .replace('{{uuid}}', this.origin ?? this.viewId); return URI.parse(uri); } get cspSource(): string { - return this.initData.webviewCspSource.replace('{{uuid}}', this.viewId); + return this.initData.webviewCspSource.replace('{{uuid}}', this.origin ?? this.viewId); } get html(): string {