Skip to content

WebviewContentProvider API investigation #45994

@mjbvz

Description

@mjbvz

From #43713

Problem
The currently proposed webview API is a push model (extensions call createWebview to create and push a webview to vscode). This model prevents us from implementing restoration of webviews when vscode is reloaded. It also does not feel consistent with the other APIs

Proposal
Based on a discussion with @jrieken and @kieferrm, move webview to more of a pull model similar to the TreeDataProviderProposal (vscode asks an extension to create a webview). This would also be very similar to the existing TextDocumentContentProvider api.

Here's a mock up:

	/**
	 * A webview is an editor with html content, like an iframe.
	 */
	export interface Webview {
		/**
		 * Unique identifer of the webview.
		 */
		readonly uri: Uri;

		/**
		 * Content settings for the webview.
		 */
		options: WebviewOptions;

		/**
		 * Title of the webview shown in UI.
		 */
		title: string;

		/**
		 * Contents of the webview.
		 *
		 * Should be a complete html document.
		 */
		html: string;

		/**
		 * The column in which the webview is showing.
		 */
		readonly viewColumn?: ViewColumn;

		/**
		 * Fired when the webview content posts a message.
		 */
		readonly onDidReceiveMessage: Event<any>;

		/**
		 * Fired when the webview is disposed.
		 */
		readonly onDidDispose: Event<void>;

		/**
		 * Event fired when webview's state changes
		 */
		readonly onDidChangeViewState: Event<{ isActive: boolean, viewColumn: ViewColumn }>;

		/**
		 * Post a message to the webview content.
		 *
		 * Messages are only develivered if the webview is visible.
		 *
		 * @param message Body of the message.
		 */
		postMessage(message: any): Thenable<boolean>;

		/**
		 * Shows the webview in a given column.
		 *
		 * A webview may only show in a single column at a time. If it is already showing, this
		 * command moves it to a new column.
		 */
		show(viewColumn: ViewColumn): void;

		/**
		 * Dispose of the the webview.
		 *
		 * This closes the webview if it showing and disposes of the resources owned by the webview.
		 * Webview are also disposed when the user closes the webview editor. Both cases fire `onDispose`
		 * event. Trying to use the webview after it has been disposed throws an exception.
		 */
		dispose(): any;
	}

	/**
	 * Provides webview editors based on uri.
	 *
	 * Webview Content providers are [registered](#workspace.registerWebviewContentProvider)
	 * for a [uri-scheme](#Uri.scheme). When a uri with that scheme is to
	 * be [loaded](#workspace.openTextDocument) the content provider is
	 * asked.
	 */
	export interface WebviewContentProvider {

		/**
		 * Initialize a new webview.
		 *
		 * @param uri Identifier of webview resource.
		 * @param webview Webview to initialize.
		 * @param token Cancellation token.
		 *
		 * @returns Did initilization succeed?
		 */
		initializeWebview(uri: Uri, webview: Webview, token: CancellationToken): ProviderResult<boolean>;
	}

	namespace workspace {
		/**
		 * Registers a new WebviewContentProvider for a given resource scheme.
		 *
		 * When a document of scheme is opened, the provider is asked to initialize the webview's content.
		 */
		export function registerWebviewContentProvider(scheme: string, provider: WebviewContentProvider): Disposable;
	}

The markdown extension for example would register a provider for the markdown-preview: scheme. API usage:

Create a new markdown preview

  • Markdown extension calls vscode.open('markdown-preview:preview1')
  • This invokes markdown's content provider

Restoring a markdown preview

  • Document with 'markdown-preview:preview1' uri is open
  • VS Code is reloaded.
  • VS Code restores the 'markdown-preview:preview1' document. This inits any extensions that activate on markdown-preview: and then invokes markdown's content provider

Close a markdown preview
Either:

  • User action
  • Extension calls .dispose() on the webview
  • Or command closes the document for ``'markdown-preview:preview1'` resource

/cc @sandy081

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions