提交 4d88b39b 编写于 作者: M Matt Bierner

Split up main thread webview services

上级 a6103e8f
......@@ -54,7 +54,7 @@ import './mainThreadTreeViews';
import './mainThreadDownloadService';
import './mainThreadUrls';
import './mainThreadWindow';
import './mainThreadWebview';
import './mainThreadWebviewPanelsAndViews';
import './mainThreadWorkspace';
import './mainThreadComments';
import './mainThreadNotebook';
......
......@@ -19,7 +19,8 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import type { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebview';
import type { MainThreadWebviewPanelsAndViews } from 'vs/workbench/api/browser/mainThreadWebviewPanelsAndViews';
import { MainThreadWebviews, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { editorGroupToViewColumn } from 'vs/workbench/api/common/shared/editor';
import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
......@@ -35,19 +36,20 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { IWorkingCopy, IWorkingCopyBackup, IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
export const enum CustomEditorModelType {
const enum CustomEditorModelType {
Custom,
Text,
}
export class MainThreadCustomEditors extends Disposable {
export class MainThreadCustomEditors extends Disposable implements extHostProtocol.MainThreadCustomEditorsShape {
private readonly _proxyCustomEditors: extHostProtocol.ExtHostCustomEditorsShape;
private readonly _editorProviders = new Map<string, IDisposable>();
constructor(
private readonly mainThreadWebviews: MainThreadWebviews,
private readonly mainThreadWebview: MainThreadWebviews,
private readonly mainThreadWebviewPanelsAndViews: MainThreadWebviewPanelsAndViews,
context: extHostProtocol.IExtHostContext,
@IWorkingCopyService workingCopyService: IWorkingCopyService,
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
......@@ -85,7 +87,15 @@ export class MainThreadCustomEditors extends Disposable {
this._editorProviders.clear();
}
public registerEditorProvider(
public $registerTextEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: extHostProtocol.CustomTextEditorCapabilities): void {
this.registerEditorProvider(CustomEditorModelType.Text, reviveWebviewExtension(extensionData), viewType, options, capabilities, true);
}
public $registerCustomEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, supportsMultipleEditorsPerDocument: boolean): void {
this.registerEditorProvider(CustomEditorModelType.Custom, reviveWebviewExtension(extensionData), viewType, options, {}, supportsMultipleEditorsPerDocument);
}
private registerEditorProvider(
modelType: CustomEditorModelType,
extension: WebviewExtensionDescription,
viewType: string,
......@@ -111,7 +121,7 @@ export class MainThreadCustomEditors extends Disposable {
const handle = webviewInput.id;
const resource = webviewInput.resource;
this.mainThreadWebviews.addWebviewInput(handle, webviewInput);
this.mainThreadWebviewPanelsAndViews.addWebviewInput(handle, webviewInput);
webviewInput.webview.options = options;
webviewInput.webview.extension = extension;
......@@ -120,7 +130,7 @@ export class MainThreadCustomEditors extends Disposable {
modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, { backupId: webviewInput.backupId }, cancellation);
} catch (error) {
onUnexpectedError(error);
webviewInput.webview.html = this.mainThreadWebviews.getWebviewResolvedFailedContent(viewType);
webviewInput.webview.html = this.mainThreadWebview.getWebviewResolvedFailedContent(viewType);
return;
}
......@@ -157,7 +167,7 @@ export class MainThreadCustomEditors extends Disposable {
await this._proxyCustomEditors.$resolveWebviewEditor(resource, handle, viewType, webviewInput.getTitle(), editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), webviewInput.webview.options, cancellation);
} catch (error) {
onUnexpectedError(error);
webviewInput.webview.html = this.mainThreadWebviews.getWebviewResolvedFailedContent(viewType);
webviewInput.webview.html = this.mainThreadWebview.getWebviewResolvedFailedContent(viewType);
modelRef.dispose();
return;
}
......@@ -200,7 +210,7 @@ export class MainThreadCustomEditors extends Disposable {
case CustomEditorModelType.Custom:
{
const model = MainThreadCustomEditorModel.create(this._instantiationService, this._proxyCustomEditors, viewType, resource, options, () => {
return Array.from(this.mainThreadWebviews.webviewInputs)
return Array.from(this.mainThreadWebviewPanelsAndViews.webviewInputs)
.filter(editor => editor instanceof CustomEditorInput && isEqual(editor.resource, resource)) as CustomEditorInput[];
}, cancellation, this._backupService);
return this._customEditorService.models.add(resource, viewType, model);
......
......@@ -4,25 +4,18 @@
*--------------------------------------------------------------------------------------------*/
import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { isWeb } from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
import { localize } from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CustomEditorModelType, MainThreadCustomEditors } from 'vs/workbench/api/browser/mainThreadCustomEditors';
import { MainThreadCustomEditors } from 'vs/workbench/api/browser/mainThreadCustomEditors';
import { MainThreadWebviews, reviveWebviewExtension, reviveWebviewOptions } from 'vs/workbench/api/browser/mainThreadWebviews';
import { MainThreadWebviewSerializers } from 'vs/workbench/api/browser/mainThreadWebviewSerializer';
import { MainThreadWebviewsViews } from 'vs/workbench/api/browser/mainThreadWebviewViews';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
import { IEditorInput } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { Webview, WebviewExtensionDescription, WebviewIcons, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewIcons } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
......@@ -82,37 +75,26 @@ class WebviewViewTypeTransformer {
}
}
@extHostNamedCustomer(extHostProtocol.MainContext.MainThreadWebviews)
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
private static readonly standardSupportedLinkSchemes = new Set([
Schemas.http,
Schemas.https,
Schemas.mailto,
Schemas.vscode,
'vscode-insider',
]);
@extHostNamedCustomer(extHostProtocol.MainContext.MainThreadWebviewService)
export class MainThreadWebviewPanelsAndViews extends Disposable implements extHostProtocol.MainThreadWebviewPanelsAndViewsShape {
public readonly webviewPanelViewType = new WebviewViewTypeTransformer('mainThreadWebview-');
private readonly _proxy: extHostProtocol.ExtHostWebviewsShape;
private readonly _webviews = new Map<string, Webview>();
private readonly _webviewInputs = new WebviewInputStore();
private readonly _editorProviders = new Map<string, IDisposable>();
private readonly _webviewFromDiffEditorHandles = new Set<string>();
private readonly _mainThreadWebviews: MainThreadWebviews;
private readonly serializers: MainThreadWebviewSerializers;
private readonly customEditors: MainThreadCustomEditors;
private readonly webviewViews: MainThreadWebviewsViews;
constructor(
context: extHostProtocol.IExtHostContext,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@IEditorService private readonly _editorService: IEditorService,
@IOpenerService private readonly _openerService: IOpenerService,
@IProductService private readonly _productService: IProductService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
......@@ -121,9 +103,16 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviews);
this.serializers = this._instantiationService.createInstance(MainThreadWebviewSerializers, this, context);
this.customEditors = this._instantiationService.createInstance(MainThreadCustomEditors, this, context);
this.webviewViews = this._instantiationService.createInstance(MainThreadWebviewsViews, this, context);
this._mainThreadWebviews = this._instantiationService.createInstance(MainThreadWebviews, context);
context.set(extHostProtocol.MainContext.MainThreadWebviews, this._mainThreadWebviews);
const webviewViews = this._instantiationService.createInstance(MainThreadWebviewsViews, this._mainThreadWebviews, context);
context.set(extHostProtocol.MainContext.MainThreadWebviewViews, webviewViews);
const customEditors = this._instantiationService.createInstance(MainThreadCustomEditors, this._mainThreadWebviews, this, context);
context.set(extHostProtocol.MainContext.MainThreadCustomEditors, customEditors);
this.serializers = this._instantiationService.createInstance(MainThreadWebviewSerializers, this._mainThreadWebviews, this, context);
this._register(_editorService.onDidActiveEditorChange(() => {
const activeInput = this._editorService.activeEditor;
......@@ -152,12 +141,13 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
public addWebviewInput(handle: extHostProtocol.WebviewPanelHandle, input: WebviewInput): void {
this._webviewInputs.add(handle, input);
this.addWebview(handle, input.webview);
}
this._mainThreadWebviews.addWebview(handle, input.webview);
public addWebview(handle: extHostProtocol.WebviewPanelHandle, webview: WebviewOverlay): void {
this._webviews.set(handle, webview);
this.hookupWebviewEventDelegate(handle, webview);
input.webview.onDispose(() => {
this._proxy.$onDidDisposeWebviewPanel(handle).finally(() => {
this._webviewInputs.delete(handle);
});
});
}
public $createWebviewPanel(
......@@ -197,25 +187,12 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
webview.setName(value);
}
public $setWebviewViewTitle(handle: extHostProtocol.WebviewPanelHandle, value: string | undefined): void {
this.webviewViews.$setWebviewViewTitle(handle, value);
}
public $setIconPath(handle: extHostProtocol.WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void {
const webview = this.getWebviewInput(handle);
webview.iconPath = reviveWebviewIcon(value);
}
public $setHtml(handle: extHostProtocol.WebviewPanelHandle, value: string): void {
const webview = this.getWebview(handle);
webview.html = value;
}
public $setOptions(handle: extHostProtocol.WebviewPanelHandle, options: modes.IWebviewOptions): void {
const webview = this.getWebview(handle);
webview.contentOptions = reviveWebviewOptions(options);
}
public $reveal(handle: extHostProtocol.WebviewPanelHandle, showOptions: extHostProtocol.WebviewPanelShowOptions): void {
const webview = this.getWebviewInput(handle);
if (webview.isDisposed()) {
......@@ -228,12 +205,6 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
}
public async $postMessage(handle: extHostProtocol.WebviewPanelHandle, message: any): Promise<boolean> {
const webview = this.getWebview(handle);
webview.postMessage(message);
return true;
}
public $registerSerializer(viewType: string): void {
this.serializers.$registerSerializer(viewType);
}
......@@ -242,51 +213,6 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
this.serializers.$unregisterSerializer(viewType);
}
public $registerWebviewViewProvider(viewType: string, options?: { retainContextWhenHidden?: boolean }): void {
this.webviewViews.$registerWebviewViewProvider(viewType, options);
}
public $unregisterWebviewViewProvider(viewType: string): void {
this.webviewViews.$unregisterWebviewViewProvider(viewType);
}
public $registerTextEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: extHostProtocol.CustomTextEditorCapabilities): void {
this.customEditors.registerEditorProvider(CustomEditorModelType.Text, reviveWebviewExtension(extensionData), viewType, options, capabilities, true);
}
public $registerCustomEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, supportsMultipleEditorsPerDocument: boolean): void {
this.customEditors.registerEditorProvider(CustomEditorModelType.Custom, reviveWebviewExtension(extensionData), viewType, options, {}, supportsMultipleEditorsPerDocument);
}
public $unregisterEditorProvider(viewType: string): void {
this.customEditors.$unregisterEditorProvider(viewType);
}
public async $onDidEdit(resourceComponents: UriComponents, viewType: string, editId: number, label: string | undefined): Promise<void> {
this.customEditors.$onDidEdit(resourceComponents, viewType, editId, label);
}
public async $onContentChange(resourceComponents: UriComponents, viewType: string): Promise<void> {
this.customEditors.$onContentChange(resourceComponents, viewType);
}
public hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, webview: WebviewOverlay) {
const disposables = new DisposableStore();
disposables.add(webview.onDidClickLink((uri) => this.onDidClickLink(handle, uri)));
disposables.add(webview.onMessage((message: any) => { this._proxy.$onMessage(handle, message); }));
disposables.add(webview.onMissingCsp((extension: ExtensionIdentifier) => this._proxy.$onMissingCsp(handle, extension.value)));
disposables.add(webview.onDispose(() => {
disposables.dispose();
this._proxy.$onDidDisposeWebviewPanel(handle).finally(() => {
this._webviews.delete(handle);
this._webviewInputs.delete(handle);
});
}));
}
private registerWebviewFromDiffEditorListeners(diffEditorInput: DiffEditorInput): void {
const primary = diffEditorInput.primary as WebviewInput;
const secondary = diffEditorInput.secondary as WebviewInput;
......@@ -348,31 +274,6 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
}
private onDidClickLink(handle: extHostProtocol.WebviewPanelHandle, link: string): void {
const webview = this.getWebviewInput(handle);
if (this.isSupportedLink(webview, URI.parse(link))) {
this._openerService.open(link, { fromUserGesture: true });
}
}
private isSupportedLink(webview: WebviewInput, link: URI): boolean {
if (MainThreadWebviews.standardSupportedLinkSchemes.has(link.scheme)) {
return true;
}
if (!isWeb && this._productService.urlProtocol === link.scheme) {
return true;
}
return !!webview.webview.contentOptions.enableCommandUris && link.scheme === Schemas.command;
}
private getWebview(handle: extHostProtocol.WebviewPanelHandle): Webview {
const webview = this._webviews.get(handle);
if (!webview) {
throw new Error(`Unknown webview handle:${handle}`);
}
return webview;
}
private getWebviewInput(handle: extHostProtocol.WebviewPanelHandle): WebviewInput {
const webview = this.tryGetWebviewInput(handle);
if (!webview) {
......@@ -384,30 +285,8 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
private tryGetWebviewInput(handle: extHostProtocol.WebviewPanelHandle): WebviewInput | undefined {
return this._webviewInputs.getInputForHandle(handle);
}
public getWebviewResolvedFailedContent(viewType: string) {
return `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none';">
</head>
<body>${localize('errorMessage', "An error occurred while loading view: {0}", escape(viewType))}</body>
</html>`;
}
}
function reviveWebviewExtension(extensionData: extHostProtocol.WebviewExtensionDescription): WebviewExtensionDescription {
return { id: extensionData.id, location: URI.revive(extensionData.location) };
}
function reviveWebviewOptions(options: modes.IWebviewOptions): WebviewInputOptions {
return {
...options,
allowScripts: options.enableScripts,
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(r => URI.revive(r)) : undefined,
};
}
function reviveWebviewIcon(
value: { light: UriComponents, dark: UriComponents; } | undefined
......
......@@ -5,7 +5,8 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import type { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebview';
import type { MainThreadWebviewPanelsAndViews } from 'vs/workbench/api/browser/mainThreadWebviewPanelsAndViews';
import { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebviews';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { editorGroupToViewColumn } from 'vs/workbench/api/common/shared/editor';
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
......@@ -22,6 +23,7 @@ export class MainThreadWebviewSerializers extends Disposable {
constructor(
private readonly mainThreadWebviews: MainThreadWebviews,
private readonly mainThreadWebviewsPanelsAndViews: MainThreadWebviewPanelsAndViews,
context: extHostProtocol.IExtHostContext,
@IExtensionService extensionService: IExtensionService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
......@@ -40,7 +42,7 @@ export class MainThreadWebviewSerializers extends Disposable {
return false;
}
const viewType = this.mainThreadWebviews.webviewPanelViewType.toExternal(webview.viewType);
const viewType = this.mainThreadWebviewsPanelsAndViews.webviewPanelViewType.toExternal(webview.viewType);
if (typeof viewType === 'string') {
extensionService.activateByEvent(`onWebviewPanel:${viewType}`);
}
......@@ -50,17 +52,18 @@ export class MainThreadWebviewSerializers extends Disposable {
}));
}
public $registerSerializer(viewType: string): void {
public $registerSerializer(viewType: string)
: void {
if (this._revivers.has(viewType)) {
throw new Error(`Reviver for ${viewType} already registered`);
}
this._revivers.set(viewType, this._webviewWorkbenchService.registerResolver({
canResolve: (webviewInput) => {
return webviewInput.viewType === this.mainThreadWebviews.webviewPanelViewType.fromExternal(viewType);
return webviewInput.viewType === this.mainThreadWebviewsPanelsAndViews.webviewPanelViewType.fromExternal(viewType);
},
resolveWebview: async (webviewInput): Promise<void> => {
const viewType = this.mainThreadWebviews.webviewPanelViewType.toExternal(webviewInput.viewType);
const viewType = this.mainThreadWebviewsPanelsAndViews.webviewPanelViewType.toExternal(webviewInput.viewType);
if (!viewType) {
webviewInput.webview.html = this.mainThreadWebviews.getWebviewResolvedFailedContent(webviewInput.viewType);
return;
......@@ -69,7 +72,7 @@ export class MainThreadWebviewSerializers extends Disposable {
const handle = webviewInput.id;
this.mainThreadWebviews.addWebviewInput(handle, webviewInput);
this.mainThreadWebviewsPanelsAndViews.addWebviewInput(handle, webviewInput);
let state = undefined;
if (webviewInput.webview.state) {
......
......@@ -6,12 +6,12 @@
import { CancellationToken } from 'vs/base/common/cancellation';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import type { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebview';
import { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebviews';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { IWebviewViewService, WebviewView } from 'vs/workbench/contrib/webviewView/browser/webviewViewService';
export class MainThreadWebviewsViews extends Disposable {
export class MainThreadWebviewsViews extends Disposable implements extHostProtocol.MainThreadWebviewViewsShape {
private readonly _proxyViews: extHostProtocol.ExtHostWebviewViewsShape;
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { isWeb } from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { IWebviewOptions } from 'vs/editor/common/modes';
import { localize } from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { Webview, WebviewExtensionDescription, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
private static readonly standardSupportedLinkSchemes = new Set([
Schemas.http,
Schemas.https,
Schemas.mailto,
Schemas.vscode,
'vscode-insider',
]);
private readonly _proxy: extHostProtocol.ExtHostWebviewsShape;
private readonly _webviews = new Map<string, Webview>();
constructor(
context: extHostProtocol.IExtHostContext,
@IOpenerService private readonly _openerService: IOpenerService,
@IProductService private readonly _productService: IProductService,
) {
super();
this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviews);
}
public addWebview(handle: extHostProtocol.WebviewPanelHandle, webview: WebviewOverlay): void {
this._webviews.set(handle, webview);
this.hookupWebviewEventDelegate(handle, webview);
}
public $setHtml(handle: extHostProtocol.WebviewPanelHandle, value: string): void {
const webview = this.getWebview(handle);
webview.html = value;
}
public $setOptions(handle: extHostProtocol.WebviewPanelHandle, options: IWebviewOptions): void {
const webview = this.getWebview(handle);
webview.contentOptions = reviveWebviewOptions(options);
}
public async $postMessage(handle: extHostProtocol.WebviewPanelHandle, message: any): Promise<boolean> {
const webview = this.getWebview(handle);
webview.postMessage(message);
return true;
}
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, webview: WebviewOverlay) {
const disposables = new DisposableStore();
disposables.add(webview.onDidClickLink((uri) => this.onDidClickLink(handle, uri)));
disposables.add(webview.onMessage((message: any) => { this._proxy.$onMessage(handle, message); }));
disposables.add(webview.onMissingCsp((extension: ExtensionIdentifier) => this._proxy.$onMissingCsp(handle, extension.value)));
disposables.add(webview.onDispose(() => {
disposables.dispose();
this._webviews.delete(handle);
}));
}
private onDidClickLink(handle: extHostProtocol.WebviewPanelHandle, link: string): void {
const webview = this.getWebview(handle);
if (this.isSupportedLink(webview, URI.parse(link))) {
this._openerService.open(link, { fromUserGesture: true });
}
}
private isSupportedLink(webview: Webview, link: URI): boolean {
if (MainThreadWebviews.standardSupportedLinkSchemes.has(link.scheme)) {
return true;
}
if (!isWeb && this._productService.urlProtocol === link.scheme) {
return true;
}
return !!webview.contentOptions.enableCommandUris && link.scheme === Schemas.command;
}
private getWebview(handle: extHostProtocol.WebviewPanelHandle): Webview {
const webview = this._webviews.get(handle);
if (!webview) {
throw new Error(`Unknown webview handle:${handle}`);
}
return webview;
}
public getWebviewResolvedFailedContent(viewType: string) {
return `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none';">
</head>
<body>${localize('errorMessage', "An error occurred while loading view: {0}", escape(viewType))}</body>
</html>`;
}
}
export function reviveWebviewExtension(extensionData: extHostProtocol.WebviewExtensionDescription): WebviewExtensionDescription {
return { id: extensionData.id, location: URI.revive(extensionData.location) };
}
export function reviveWebviewOptions(options: IWebviewOptions): WebviewInputOptions {
return {
...options,
allowScripts: options.enableScripts,
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(r => URI.revive(r)) : undefined,
};
}
......@@ -609,27 +609,32 @@ export interface CustomTextEditorCapabilities {
}
export interface MainThreadWebviewsShape extends IDisposable {
$setHtml(handle: WebviewPanelHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle, options: modes.IWebviewOptions): void;
$postMessage(handle: WebviewPanelHandle, value: any): Promise<boolean>
}
export interface MainThreadWebviewPanelsAndViewsShape extends IDisposable {
$createWebviewPanel(extension: WebviewExtensionDescription, handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: modes.IWebviewPanelOptions & modes.IWebviewOptions): void;
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle, options: modes.IWebviewOptions): void;
$postMessage(handle: WebviewPanelHandle, value: any): Promise<boolean>;
$registerSerializer(viewType: string): void;
$unregisterSerializer(viewType: string): void;
}
export interface MainThreadCustomEditorsShape extends IDisposable {
$registerTextEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: CustomTextEditorCapabilities): void;
$registerCustomEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, supportsMultipleEditorsPerDocument: boolean): void;
$unregisterEditorProvider(viewType: string): void;
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
$onContentChange(resource: UriComponents, viewType: string): void;
}
export interface MainThreadWebviewViewsShape extends IDisposable {
$registerWebviewViewProvider(viewType: string, options?: { retainContextWhenHidden?: boolean }): void;
$unregisterWebviewViewProvider(viewType: string): void;
......@@ -1715,7 +1720,10 @@ export const MainContext = {
MainThreadStorage: createMainId<MainThreadStorageShape>('MainThreadStorage'),
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'),
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'),
MainThreadWebviewService: createMainId<MainThreadWebviewPanelsAndViewsShape>('MainThreadWebviewService'),
MainThreadWebviews: createMainId<MainThreadWebviewsShape>('MainThreadWebviews'),
MainThreadWebviewViews: createMainId<MainThreadWebviewViewsShape>('MainThreadWebviewViews'),
MainThreadCustomEditors: createMainId<MainThreadCustomEditorsShape>('MainThreadCustomEditors'),
MainThreadUrls: createMainId<MainThreadUrlsShape>('MainThreadUrls'),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'),
MainThreadFileSystem: createMainId<MainThreadFileSystemShape>('MainThreadFileSystem'),
......
......@@ -154,7 +154,7 @@ class EditorProviderStore {
export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditorsShape {
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
private readonly _proxy: extHostProtocol.MainThreadCustomEditorsShape;
private readonly _editorProviders = new EditorProviderStore();
......@@ -166,7 +166,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
private readonly _extensionStoragePaths: IExtensionStoragePaths | undefined,
private readonly _extHostWebview: ExtHostWebviews,
) {
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadCustomEditors);
}
public registerCustomEditorProvider(
......
......@@ -120,7 +120,7 @@ type IconPath = URI | { light: URI, dark: URI };
class ExtHostWebviewPanel extends Disposable implements vscode.WebviewPanel {
readonly #handle: extHostProtocol.WebviewPanelHandle;
readonly #proxy: extHostProtocol.MainThreadWebviewsShape;
readonly #proxy: extHostProtocol.MainThreadWebviewPanelsAndViewsShape;
readonly #viewType: string;
readonly #webview: ExtHostWebview;
......@@ -141,7 +141,7 @@ class ExtHostWebviewPanel extends Disposable implements vscode.WebviewPanel {
constructor(
handle: extHostProtocol.WebviewPanelHandle,
proxy: extHostProtocol.MainThreadWebviewsShape,
proxy: extHostProtocol.MainThreadWebviewPanelsAndViewsShape,
viewType: string,
title: string,
viewColumn: vscode.ViewColumn | undefined,
......@@ -246,11 +246,6 @@ class ExtHostWebviewPanel extends Disposable implements vscode.WebviewPanel {
}
}
public postMessage(message: any): Promise<boolean> {
this.assertNotDisposed();
return this.#proxy.$postMessage(this.#handle, message);
}
public reveal(viewColumn?: vscode.ViewColumn, preserveFocus?: boolean): void {
this.assertNotDisposed();
this.#proxy.$reveal(this.#handle, {
......@@ -272,12 +267,12 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
return generateUuid();
}
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
private readonly _proxy: extHostProtocol.MainThreadWebviewPanelsAndViewsShape;
private readonly _webviewProxy: extHostProtocol.MainThreadWebviewsShape;
private readonly _webviews = new Map<extHostProtocol.WebviewPanelHandle, ExtHostWebview>();
private readonly _webviewPanels = new Map<extHostProtocol.WebviewPanelHandle, ExtHostWebviewPanel>();
constructor(
mainContext: extHostProtocol.IMainContext,
private readonly initData: WebviewInitData,
......@@ -285,7 +280,8 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
private readonly _logService: ILogService,
private readonly _deprecationService: IExtHostApiDeprecationService,
) {
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviewService);
this._webviewProxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
}
public createWebviewPanel(
......@@ -375,7 +371,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
}
public createNewWebview(handle: string, options: modes.IWebviewOptions & modes.IWebviewPanelOptions, extension: IExtensionDescription): ExtHostWebview {
const webview = new ExtHostWebview(handle, this._proxy, reviveOptions(options), this.initData, this.workspace, extension, this._deprecationService);
const webview = new ExtHostWebview(handle, this._webviewProxy, reviveOptions(options), this.initData, this.workspace, extension, this._deprecationService);
this._webviews.set(handle, webview);
webview._onDidDispose(() => { this._webviews.delete(handle); });
......
......@@ -13,7 +13,7 @@ import * as extHostTypes from './extHostTypes';
export class ExtHostWebviewSerializer implements extHostProtocol.ExtHostWebviewSerializerShape {
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
private readonly _proxy: extHostProtocol.MainThreadWebviewPanelsAndViewsShape;
private readonly _serializers = new Map<string, {
readonly serializer: vscode.WebviewPanelSerializer;
......@@ -24,7 +24,7 @@ export class ExtHostWebviewSerializer implements extHostProtocol.ExtHostWebviewS
mainContext: extHostProtocol.IMainContext,
private readonly _webviewService: ExtHostWebviews,
) {
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviewService);
}
public registerWebviewPanelSerializer(
......
......@@ -15,7 +15,7 @@ import * as extHostTypes from './extHostTypes';
class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
readonly #handle: extHostProtocol.WebviewPanelHandle;
readonly #proxy: extHostProtocol.MainThreadWebviewsShape;
readonly #proxy: extHostProtocol.MainThreadWebviewViewsShape;
readonly #viewType: string;
readonly #webview: ExtHostWebview;
......@@ -26,7 +26,7 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
constructor(
handle: extHostProtocol.WebviewPanelHandle,
proxy: extHostProtocol.MainThreadWebviewsShape,
proxy: extHostProtocol.MainThreadWebviewViewsShape,
viewType: string,
webview: ExtHostWebview,
isVisible: boolean,
......@@ -94,7 +94,7 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsShape {
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
private readonly _proxy: extHostProtocol.MainThreadWebviewViewsShape;
private readonly _viewProviders = new Map<string, {
readonly provider: vscode.WebviewViewProvider;
......@@ -107,7 +107,7 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
mainContext: extHostProtocol.IMainContext,
private readonly _extHostWebview: ExtHostWebviews,
) {
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviewViews);
}
public registerWebviewViewProvider(
......
......@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { NullLogService } from 'vs/platform/log/common/log';
import { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebview';
import { MainThreadWebviewPanelsAndViews } from 'vs/workbench/api/browser/mainThreadWebviewPanelsAndViews';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
......@@ -153,7 +153,7 @@ suite('ExtHostWebview', () => {
function createNoopMainThreadWebviews() {
return new class extends mock<MainThreadWebviews>() {
return new class extends mock<MainThreadWebviewPanelsAndViews>() {
$createWebviewPanel() { /* noop */ }
$registerSerializer() { /* noop */ }
$unregisterSerializer() { /* noop */ }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册