Webview Api Prototype (#42690)

* Webview api

* Cleaning up markdown webview

* Hooking up dispose

* Fix some merge errors

* Use custom context key to show markdown title bar contributions

* Add basic on focus and on blur events

* Fixing find widget in webview

* Hookup _isDisposed

* Use new extension resource scheme to load markdown extension resources

* Documenting keep alive
This commit is contained in:
Matt Bierner
2018-02-14 18:52:26 -08:00
committed by GitHub
parent dbcf30ddbc
commit 3412eab2ec
26 changed files with 889 additions and 196 deletions

View File

@@ -57,6 +57,7 @@ import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionA
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { OverviewRulerLane } from 'vs/editor/common/model';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
@@ -116,6 +117,7 @@ export function createApiFactory(
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol));
// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
@@ -396,6 +398,9 @@ export function createApiFactory(
}),
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
}),
createWebview: proposedApiFunction(extension, (name: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
return extHostWebviews.createWebview(name, column, options);
})
};

View File

@@ -345,6 +345,21 @@ export interface MainThreadTelemetryShape extends IDisposable {
$publicLog(eventName: string, data?: any): void;
}
export interface MainThreadWebviewShape extends IDisposable {
$createWebview(handle: number): void;
$disposeWebview(handle: number): void;
$show(handle: number, column: EditorPosition): void;
$setTitle(handle: number, value: string): void;
$setHtml(handle: number, value: string): void;
$setOptions(handle: number, value: vscode.WebviewOptions): void;
$sendMessage(handle: number, value: any): Thenable<boolean>;
}
export interface ExtHostWebviewsShape {
$onMessage(handle: number, message: any): void;
$onBecameActive(handle: number): void;
$onBecameInactive(handle: number): void;
}
export interface MainThreadWorkspaceShape extends IDisposable {
$startSearch(includePattern: string, includeFolder: string, excludePatternOrDisregardExcludes: string | false, maxResults: number, requestId: number): Thenable<UriComponents[]>;
$cancelSearch(requestId: number): Thenable<boolean>;
@@ -796,6 +811,7 @@ export const MainContext = {
MainThreadStorage: createMainId<MainThreadStorageShape>('MainThreadStorage'),
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'),
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'),
MainThreadWebview: createMainId<MainThreadWebviewShape>('MainThreadWebview'),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'),
MainThreadFileSystem: createMainId<MainThreadFileSystemShape>('MainThreadFileSystem'),
MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'),
@@ -828,4 +844,5 @@ export const ExtHostContext = {
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews')
};

View File

@@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { MainContext, MainThreadWebviewShape, IMainContext, ExtHostWebviewsShape } from './extHost.protocol';
import * as vscode from 'vscode';
import { Emitter } from 'vs/base/common/event';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
class ExtHostWebview implements vscode.Webview {
private _title: string;
private _html: string;
private _options: vscode.WebviewOptions;
private _isDisposed: boolean = false;
public readonly onMessageEmitter = new Emitter<any>();
public readonly onMessage = this.onMessageEmitter.event;
public readonly onBecameActiveEmitter = new Emitter<void>();
public readonly onBecameActive = this.onBecameActiveEmitter.event;
public readonly onBecameInactiveEmitter = new Emitter<void>();
public readonly onBecameInactive = this.onBecameInactiveEmitter.event;
constructor(
private readonly _proxy: MainThreadWebviewShape,
private readonly _handle: number,
) { }
public dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this._proxy.$disposeWebview(this._handle);
}
get title(): string {
return this._title;
}
set title(value: string) {
if (this._title !== value) {
this._title = value;
this._proxy.$setTitle(this._handle, value);
}
}
get html(): string {
return this._html;
}
set html(value: string) {
if (this._html !== value) {
this._html = value;
this._proxy.$setHtml(this._handle, value);
}
}
get options(): vscode.WebviewOptions {
return this._options;
}
set options(value: vscode.WebviewOptions) {
this._proxy.$setOptions(this._handle, value);
}
public postMessage(message: any): Thenable<any> {
return this._proxy.$sendMessage(this._handle, message);
}
}
export class ExtHostWebviews implements ExtHostWebviewsShape {
private static _handlePool = 0;
private readonly _proxy: MainThreadWebviewShape;
private readonly _webviews = new Map<number, ExtHostWebview>();
constructor(
mainContext: IMainContext
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadWebview);
}
createWebview(
title: string,
column: vscode.ViewColumn,
options: vscode.WebviewOptions
): vscode.Webview {
const handle = ExtHostWebviews._handlePool++;
this._proxy.$createWebview(handle);
const webview = new ExtHostWebview(this._proxy, handle);
this._webviews.set(handle, webview);
webview.title = title;
webview.options = options;
this._proxy.$show(handle, typeConverters.fromViewColumn(column));
return webview;
}
$onMessage(handle: number, message: any): void {
const webview = this._webviews.get(handle);
webview.onMessageEmitter.fire(message);
}
$onBecameActive(handle: number): void {
const webview = this._webviews.get(handle);
webview.onBecameActiveEmitter.fire();
}
$onBecameInactive(handle: number): void {
const webview = this._webviews.get(handle);
webview.onBecameInactiveEmitter.fire();
}
}