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.d.ts b/src/vs/vscode.d.ts index 7e66b3f3a7c79..27a09386ff78a 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5732,6 +5732,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 @@ -6203,6 +6218,29 @@ 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. A uri must respect + * the following rules: + * + * - 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 `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. + * + * * *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; + /** * Registers a webview panel serializer. * diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index a04b43ec4243d..819ddb33c41b3 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -638,22 +638,6 @@ declare module 'vscode' { //#endregion - //#region URLs - - export interface ProtocolHandler { - handleUri(uri: Uri): void; - } - - export namespace window { - - /** - * Registers a protocol handler capable of handling system-wide URIs. - */ - export function registerProtocolHandler(handler: ProtocolHandler): Disposable; - } - - //#endregion - //#region Joh -> exclusive document filters export interface DocumentFilter { 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 9911e27bbe8a2..eea4190baedd5 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( registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => { return extHostDecorations.registerDecorationProvider(provider, extension.id); }), - registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => { - return extHostUrls.registerProtocolHandler(extension.id, handler); - }), + registerUriHandler(handler: vscode.UriHandler) { + return extHostUrls.registerUriHandler(extension.id, handler); + }, get quickInputBackButton() { return proposedApiFunction(extension, (): vscode.QuickInputButton => { return extHostQuickOpen.backButton; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index e78edaceeea6e..c65fd9cf161d1 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -453,8 +453,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..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 { @@ -15,7 +17,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 +25,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 +33,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); }); } @@ -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