From 92693a1b268a37e1f4446115a171810715d5640d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 15:13:03 +0200 Subject: [PATCH 1/8] API: UriHandler, rename and docs --- extensions/git/src/protocolHandler.ts | 6 ++-- src/vs/vscode.proposed.d.ts | 32 +++++++++++++++++-- .../api/electron-browser/mainThreadUrls.ts | 4 +-- src/vs/workbench/api/node/extHost.api.impl.ts | 4 +-- src/vs/workbench/api/node/extHost.protocol.ts | 4 +-- src/vs/workbench/api/node/extHostUrls.ts | 8 ++--- 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/extensions/git/src/protocolHandler.ts b/extensions/git/src/protocolHandler.ts index b84d6620068f1..422ca3df73970 100644 --- a/extensions/git/src/protocolHandler.ts +++ b/extensions/git/src/protocolHandler.ts @@ -5,16 +5,16 @@ 'use strict'; -import { ProtocolHandler, Uri, window, Disposable, commands } from 'vscode'; +import { UriHandler, Uri, window, Disposable, commands } from 'vscode'; import { dispose } from './util'; import * as querystring from 'querystring'; -export class GitProtocolHandler implements ProtocolHandler { +export class GitProtocolHandler implements UriHandler { private disposables: Disposable[] = []; constructor() { - this.disposables.push(window.registerProtocolHandler(this)); + this.disposables.push(window.registerUriHandler(this)); } handleUri(uri: Uri): void { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 99ece63c7de87..997cfb6570c74 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -497,16 +497,42 @@ declare module 'vscode' { //#region URLs - export interface ProtocolHandler { + /** + * A Uri handler is responsible for handling system-wide [Uris](#Uri). + * + * @see [window.registerUriHandler](#window.registerUriHandler). + */ + export interface UriHandler { + + /** + * Handle the provided system-wide [Uri](#Uri). + * + * @see [window.registerUriHandler](#window.registerUriHandler). + */ handleUri(uri: Uri): void; } export namespace window { /** - * Registers a protocol handler capable of handling system-wide URIs. + * Registers a [Uri handler](#UriHandler) capable of handling system-wide [Uris](#Uri). + * A Uri handler is scoped to the extension it is contributed from: it will only + * be able to handle Uris which are directed to the extension itself. + * + * For example, if the `vscode.git` extension registers a Uri handler, it will only + * be allowed to handle Uris with the prefix `{scheme}://vscode.git`, in which `{scheme}` + * is either `vscode` or `vscode-insiders`. All the following Uris are examples: + * + * - `vscode://vscode.git` + * - `vscode://vscode.git/` + * - `vscode-insiders://vscode.git/status` + * - `vscode-insiders://vscode.git/clone?url=foobar` + * + * An extension can only register a single Uri handler in its entire activation lifetime. + * + * @param handler The Uri handler to register for this extension. */ - export function registerProtocolHandler(handler: ProtocolHandler): Disposable; + export function registerUriHandler(handler: UriHandler): Disposable; } //#endregion diff --git a/src/vs/workbench/api/electron-browser/mainThreadUrls.ts b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts index 7ba2ed813b131..f85ebfdea2749 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadUrls.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts @@ -42,7 +42,7 @@ export class MainThreadUrls implements MainThreadUrlsShape { this.proxy = context.getProxy(ExtHostContext.ExtHostUrls); } - $registerProtocolHandler(handle: number, extensionId: string): TPromise { + $registerUriHandler(handle: number, extensionId: string): TPromise { const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId); const disposable = this.urlService.registerHandler(handler); @@ -52,7 +52,7 @@ export class MainThreadUrls implements MainThreadUrlsShape { return TPromise.as(null); } - $unregisterProtocolHandler(handle: number): TPromise { + $unregisterUriHandler(handle: number): TPromise { const tuple = this.handlers.get(handle); if (!tuple) { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 609db622a2b71..2b434b1fd0365 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -452,8 +452,8 @@ export function createApiFactory( registerWebviewPanelSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewPanelSerializer) => { return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer); }), - registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => { - return extHostUrls.registerProtocolHandler(extension.id, handler); + registerUriHandler: proposedApiFunction(extension, (handler: vscode.UriHandler) => { + return extHostUrls.registerUriHandler(extension.id, handler); }), get quickInputBackButton() { return proposedApiFunction(extension, (): vscode.QuickInputButton => { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 6aab73ca6f725..20996b207a63f 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -462,8 +462,8 @@ export interface ExtHostWebviewsShape { } export interface MainThreadUrlsShape extends IDisposable { - $registerProtocolHandler(handle: number, extensionId: string): TPromise; - $unregisterProtocolHandler(handle: number): TPromise; + $registerUriHandler(handle: number, extensionId: string): TPromise; + $unregisterUriHandler(handle: number): TPromise; } export interface ExtHostUrlsShape { diff --git a/src/vs/workbench/api/node/extHostUrls.ts b/src/vs/workbench/api/node/extHostUrls.ts index 534dfb4f02a30..fd02738bdae92 100644 --- a/src/vs/workbench/api/node/extHostUrls.ts +++ b/src/vs/workbench/api/node/extHostUrls.ts @@ -15,7 +15,7 @@ export class ExtHostUrls implements ExtHostUrlsShape { private readonly _proxy: MainThreadUrlsShape; private handles = new Set(); - private handlers = new Map(); + private handlers = new Map(); constructor( mainContext: IMainContext @@ -23,7 +23,7 @@ export class ExtHostUrls implements ExtHostUrlsShape { this._proxy = mainContext.getProxy(MainContext.MainThreadUrls); } - registerProtocolHandler(extensionId: string, handler: vscode.ProtocolHandler): vscode.Disposable { + registerUriHandler(extensionId: string, handler: vscode.UriHandler): vscode.Disposable { if (this.handles.has(extensionId)) { throw new Error(`Protocol handler already registered for extension ${extensionId}`); } @@ -31,12 +31,12 @@ export class ExtHostUrls implements ExtHostUrlsShape { const handle = ExtHostUrls.HandlePool++; this.handles.add(extensionId); this.handlers.set(handle, handler); - this._proxy.$registerProtocolHandler(handle, extensionId); + this._proxy.$registerUriHandler(handle, extensionId); return toDisposable(() => { this.handles.delete(extensionId); this.handlers.delete(handle); - this._proxy.$unregisterProtocolHandler(handle); + this._proxy.$unregisterUriHandler(handle); }); } From c7050d6c016587e9e50d3e1124bb2acad16b4fc6 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 15:35:16 +0200 Subject: [PATCH 2/8] uri handler can return promise, we'll log any errors --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/node/extHostUrls.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 997cfb6570c74..4f56858bceb5e 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -509,7 +509,7 @@ declare module 'vscode' { * * @see [window.registerUriHandler](#window.registerUriHandler). */ - handleUri(uri: Uri): void; + handleUri(uri: Uri): ProviderResult; } export namespace window { diff --git a/src/vs/workbench/api/node/extHostUrls.ts b/src/vs/workbench/api/node/extHostUrls.ts index fd02738bdae92..06f5b72ca62ae 100644 --- a/src/vs/workbench/api/node/extHostUrls.ts +++ b/src/vs/workbench/api/node/extHostUrls.ts @@ -8,6 +8,8 @@ import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from import URI, { UriComponents } from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { toDisposable } from 'vs/base/common/lifecycle'; +import { asWinJsPromise } from 'vs/base/common/async'; +import { onUnexpectedError } from 'vs/base/common/errors'; export class ExtHostUrls implements ExtHostUrlsShape { @@ -47,7 +49,9 @@ export class ExtHostUrls implements ExtHostUrlsShape { return TPromise.as(null); } - handler.handleUri(URI.revive(uri)); + asWinJsPromise(_ => handler.handleUri(URI.revive(uri))) + .done(null, onUnexpectedError); + return TPromise.as(null); } } \ No newline at end of file From 87fa41ee006e75f6325729149a313f90bd6e61c5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 15:37:46 +0200 Subject: [PATCH 3/8] improve Url handler docs --- src/vs/vscode.proposed.d.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 4f56858bceb5e..0d387afcade69 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -516,8 +516,10 @@ declare module 'vscode' { /** * Registers a [Uri handler](#UriHandler) capable of handling system-wide [Uris](#Uri). - * A Uri handler is scoped to the extension it is contributed from: it will only - * be able to handle Uris which are directed to the extension itself. + * In case there are multiple windows open, the topmost window will handle the Uri. + * A Uri handler is scoped to the extension it is contributed from; it will only + * be able to handle Uris which are directed to the extension itself. The Uri format + * is predetermined by the extension's identifier. * * For example, if the `vscode.git` extension registers a Uri handler, it will only * be allowed to handle Uris with the prefix `{scheme}://vscode.git`, in which `{scheme}` @@ -526,7 +528,7 @@ declare module 'vscode' { * - `vscode://vscode.git` * - `vscode://vscode.git/` * - `vscode-insiders://vscode.git/status` - * - `vscode-insiders://vscode.git/clone?url=foobar` + * - `vscode-insiders://vscode.git/clone?when=now` * * An extension can only register a single Uri handler in its entire activation lifetime. * From 0e8d72797107ece0d12267c423ba8c3f26b93235 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 16:09:43 +0200 Subject: [PATCH 4/8] promote uri handler api to stable --- src/vs/vscode.d.ts | 37 ++++++++++++++++ src/vs/vscode.proposed.d.ts | 44 ------------------- src/vs/workbench/api/node/extHost.api.impl.ts | 4 +- 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 71329e06fea26..826cdea511817 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5686,6 +5686,21 @@ declare module 'vscode' { readonly focused: boolean; } + /** + * A Uri handler is responsible for handling system-wide [Uris](#Uri). + * + * @see [window.registerUriHandler](#window.registerUriHandler). + */ + export interface UriHandler { + + /** + * Handle the provided system-wide [Uri](#Uri). + * + * @see [window.registerUriHandler](#window.registerUriHandler). + */ + handleUri(uri: Uri): ProviderResult; + } + /** * Namespace for dealing with the current window of the editor. That is visible * and active editors, as well as, UI elements to show messages, selections, and @@ -6145,6 +6160,28 @@ declare module 'vscode' { * @returns a [TreeView](#TreeView). */ export function createTreeView(viewId: string, options: { treeDataProvider: TreeDataProvider }): TreeView; + + /** + * Registers a [Uri handler](#UriHandler) capable of handling system-wide [Uris](#Uri). + * In case there are multiple windows open, the topmost window will handle the Uri. + * A Uri handler is scoped to the extension it is contributed from; it will only + * be able to handle Uris which are directed to the extension itself. The Uri format + * is predetermined by the extension's identifier. + * + * For example, if the `vscode.git` extension registers a Uri handler, it will only + * be allowed to handle Uris with the prefix `{scheme}://vscode.git`, in which `{scheme}` + * is either `vscode` or `vscode-insiders`. All the following Uris are examples: + * + * - `vscode://vscode.git` + * - `vscode://vscode.git/` + * - `vscode-insiders://vscode.git/status` + * - `vscode-insiders://vscode.git/clone?when=now` + * + * An extension can only register a single Uri handler in its entire activation lifetime. + * + * @param handler The Uri handler to register for this extension. + */ + export function registerUriHandler(handler: UriHandler): Disposable; } /** diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 0d387afcade69..10dea16487e61 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -495,50 +495,6 @@ declare module 'vscode' { //#endregion - //#region URLs - - /** - * A Uri handler is responsible for handling system-wide [Uris](#Uri). - * - * @see [window.registerUriHandler](#window.registerUriHandler). - */ - export interface UriHandler { - - /** - * Handle the provided system-wide [Uri](#Uri). - * - * @see [window.registerUriHandler](#window.registerUriHandler). - */ - handleUri(uri: Uri): ProviderResult; - } - - export namespace window { - - /** - * Registers a [Uri handler](#UriHandler) capable of handling system-wide [Uris](#Uri). - * In case there are multiple windows open, the topmost window will handle the Uri. - * A Uri handler is scoped to the extension it is contributed from; it will only - * be able to handle Uris which are directed to the extension itself. The Uri format - * is predetermined by the extension's identifier. - * - * For example, if the `vscode.git` extension registers a Uri handler, it will only - * be allowed to handle Uris with the prefix `{scheme}://vscode.git`, in which `{scheme}` - * is either `vscode` or `vscode-insiders`. All the following Uris are examples: - * - * - `vscode://vscode.git` - * - `vscode://vscode.git/` - * - `vscode-insiders://vscode.git/status` - * - `vscode-insiders://vscode.git/clone?when=now` - * - * An extension can only register a single Uri handler in its entire activation lifetime. - * - * @param handler The Uri handler to register for this extension. - */ - export function registerUriHandler(handler: UriHandler): Disposable; - } - - //#endregion - //#region Joh -> exclusive document filters export interface DocumentFilter { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 2b434b1fd0365..a13e4ea75f065 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -452,9 +452,9 @@ export function createApiFactory( registerWebviewPanelSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewPanelSerializer) => { return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer); }), - registerUriHandler: proposedApiFunction(extension, (handler: vscode.UriHandler) => { + registerUriHandler(handler: vscode.UriHandler) { return extHostUrls.registerUriHandler(extension.id, handler); - }), + }, get quickInputBackButton() { return proposedApiFunction(extension, (): vscode.QuickInputButton => { return extHostQuickOpen.backButton; From 99ae54c030a5cec05436fa8158377b18072618c0 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 16:16:38 +0200 Subject: [PATCH 5/8] document onUri activation event --- src/vs/vscode.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 826cdea511817..8268b0b120453 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6179,6 +6179,9 @@ declare module 'vscode' { * * An extension can only register a single Uri handler in its entire activation lifetime. * + * * *Note:* There is an activation event `onUri` that fires when a Uri directed for + * the current extension is about to be handled. + * * @param handler The Uri handler to register for this extension. */ export function registerUriHandler(handler: UriHandler): Disposable; From 74df04928f030e796b3662e2e77e3319c427dad7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 25 Jun 2018 17:06:35 +0200 Subject: [PATCH 6/8] uri handler api: improve docs --- src/vs/vscode.d.ts | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 8268b0b120453..fb96d7b0d88d4 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5687,14 +5687,14 @@ declare module 'vscode' { } /** - * A Uri handler is responsible for handling system-wide [Uris](#Uri). + * A uri handler is responsible for handling system-wide [uris](#Uri). * * @see [window.registerUriHandler](#window.registerUriHandler). */ export interface UriHandler { /** - * Handle the provided system-wide [Uri](#Uri). + * Handle the provided system-wide [uri](#Uri). * * @see [window.registerUriHandler](#window.registerUriHandler). */ @@ -6162,27 +6162,31 @@ declare module 'vscode' { export function createTreeView(viewId: string, options: { treeDataProvider: TreeDataProvider }): TreeView; /** - * Registers a [Uri handler](#UriHandler) capable of handling system-wide [Uris](#Uri). - * In case there are multiple windows open, the topmost window will handle the Uri. - * A Uri handler is scoped to the extension it is contributed from; it will only - * be able to handle Uris which are directed to the extension itself. The Uri format - * is predetermined by the extension's identifier. + * Registers a [uri handler](#UriHandler) capable of handling system-wide [uris](#Uri). + * In case there are multiple windows open, the topmost window will handle the uri. + * A uri handler is scoped to the extension it is contributed from; it will only + * be able to handle uris which are directed to the extension itself. A uri must respect + * the following rules: * - * For example, if the `vscode.git` extension registers a Uri handler, it will only - * be allowed to handle Uris with the prefix `{scheme}://vscode.git`, in which `{scheme}` - * is either `vscode` or `vscode-insiders`. All the following Uris are examples: + * - The uri-scheme must be the product name (eg. `vscode`); + * - The uri-authority must be the extension id (eg. `vscode-git`); + * - The uri-path, -query and -fragment parts are arbitrary. + * + * For example, if the `vscode.git` extension registers a uri handler, it will only + * be allowed to handle uris with the prefix `{product}://vscode.git`. All the following + * uris are examples: * * - `vscode://vscode.git` * - `vscode://vscode.git/` - * - `vscode-insiders://vscode.git/status` - * - `vscode-insiders://vscode.git/clone?when=now` + * - `vscode://vscode.git/status` + * - `vscode://vscode.git/clone?when=now` * - * An extension can only register a single Uri handler in its entire activation lifetime. + * An extension can only register a single uri handler in its entire activation lifetime. * - * * *Note:* There is an activation event `onUri` that fires when a Uri directed for + * * *Note:* There is an activation event `onUri` that fires when a uri directed for * the current extension is about to be handled. * - * @param handler The Uri handler to register for this extension. + * @param handler The uri handler to register for this extension. */ export function registerUriHandler(handler: UriHandler): Disposable; } From 875eab9b7b3babd63db8eec09f9424e2473195d0 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 6 Jul 2018 12:43:22 +0200 Subject: [PATCH 7/8] update docs --- src/vs/vscode.d.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index fb96d7b0d88d4..dc0b0fbc616bf 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6168,18 +6168,12 @@ declare module 'vscode' { * be able to handle uris which are directed to the extension itself. A uri must respect * the following rules: * - * - The uri-scheme must be the product name (eg. `vscode`); - * - The uri-authority must be the extension id (eg. `vscode-git`); + * - The uri-scheme must be the product name; + * - The uri-authority must be the extension id (eg. `my.extension`); * - The uri-path, -query and -fragment parts are arbitrary. * - * For example, if the `vscode.git` extension registers a uri handler, it will only - * be allowed to handle uris with the prefix `{product}://vscode.git`. All the following - * uris are examples: - * - * - `vscode://vscode.git` - * - `vscode://vscode.git/` - * - `vscode://vscode.git/status` - * - `vscode://vscode.git/clone?when=now` + * For example, if the `my.extension` extension registers a uri handler, it will only + * be allowed to handle uris with the prefix `product-name://my.extension`. * * An extension can only register a single uri handler in its entire activation lifetime. * From 97aa61c04952d3781dcbac5fbc473265b503ef24 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 6 Jul 2018 14:35:11 +0200 Subject: [PATCH 8/8] whitespace --- src/vs/vscode.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index a2b480f95c652..27a09386ff78a 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6244,10 +6244,10 @@ declare module 'vscode' { /** * Registers a webview panel serializer. * - * Extensions that support reviving should have an`"onWebviewPanel:viewType"` activation event and - * make sure that[registerWebviewPanelSerializer](#registerWebviewPanelSerializer) is called during activation. + * Extensions that support reviving should have an `"onWebviewPanel:viewType"` activation event and + * make sure that [registerWebviewPanelSerializer](#registerWebviewPanelSerializer) is called during activation. * - * Only a single serializer may be registered at a time for a given`viewType`. + * Only a single serializer may be registered at a time for a given `viewType`. * * @param viewType Type of the webview panel that can be serialized. * @param serializer Webview serializer.