diff --git a/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts b/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts index 54cfc70e05aa73bba22e7c760fa68291211255dd..5c6ab39a215421d93d5b0c98047cf53b3a96dabc 100644 --- a/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts +++ b/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts @@ -9,6 +9,8 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { localize } from 'vs/nls'; const FIVE_MINUTES = 5 * 60 * 1000; const THIRTY_SECONDS = 30 * 1000; @@ -17,9 +19,9 @@ function isExtensionId(value: string): boolean { return /^[a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*$/i.test(value); } -export const IInactiveExtensionUrlHandler = createDecorator('inactiveExtensionUrlHandler'); +export const IExtensionUrlHandler = createDecorator('inactiveExtensionUrlHandler'); -export interface IInactiveExtensionUrlHandler { +export interface IExtensionUrlHandler { readonly _serviceBrand: any; registerExtensionHandler(extensionId: string, handler: IURLHandler): void; unregisterExtensionHandler(extensionId: string): void; @@ -31,8 +33,10 @@ export interface IInactiveExtensionUrlHandler { * activates the extension and re-opens the URL once the extension registers * a URL handler. If the extension never registers a URL handler, the urls * will eventually be garbage collected. + * + * It also makes sure the user confirms opening URLs directed towards extensions. */ -export class InactiveExtensionUrlHandler implements IInactiveExtensionUrlHandler, IURLHandler { +export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { readonly _serviceBrand: any; @@ -42,7 +46,8 @@ export class InactiveExtensionUrlHandler implements IInactiveExtensionUrlHandler constructor( @IURLService urlService: IURLService, - @IExtensionService private extensionService: IExtensionService + @IExtensionService private extensionService: IExtensionService, + @IDialogService private dialogService: IDialogService ) { const interval = setInterval(() => this.garbageCollect(), THIRTY_SECONDS); @@ -52,13 +57,22 @@ export class InactiveExtensionUrlHandler implements IInactiveExtensionUrlHandler ]); } - handleURL(uri: URI): TPromise { + async handleURL(uri: URI): TPromise { if (!isExtensionId(uri.authority)) { - return TPromise.as(false); + return false; } const extensionId = uri.authority; + const result = await this.dialogService.confirm({ + message: localize('confirmUrl', "Do you want to let the {0} extension open the following URL?", extensionId), + detail: uri.toString() + }); + + if (!result.confirmed) { + return true; + } + // let the ExtensionUrlHandler instance handle this if (this.extensionIds.has(extensionId)) { return TPromise.as(false); @@ -76,8 +90,9 @@ export class InactiveExtensionUrlHandler implements IInactiveExtensionUrlHandler uris.push({ timestamp, uri }); // activate the extension - return this.extensionService.activateByEvent(`onUri:${extensionId}`) - .then(() => true); + await this.extensionService.activateByEvent(`onUri:${extensionId}`); + + return true; } registerExtensionHandler(extensionId: string, handler: IURLHandler): void { diff --git a/src/vs/workbench/api/electron-browser/mainThreadUrls.ts b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts index c9fc7ab862b599fd86217a7214a67f179c63ac9f..7ba2ed813b131fd40a23b8abe057b6f4551ad96b 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadUrls.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import URI from 'vs/base/common/uri'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IInactiveExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; +import { IExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; class ExtensionUrlHandler implements IURLHandler { @@ -37,7 +37,7 @@ export class MainThreadUrls implements MainThreadUrlsShape { constructor( context: IExtHostContext, @IURLService private urlService: IURLService, - @IInactiveExtensionUrlHandler private inactiveExtensionUrlHandler: IInactiveExtensionUrlHandler + @IExtensionUrlHandler private inactiveExtensionUrlHandler: IExtensionUrlHandler ) { this.proxy = context.getProxy(ExtHostContext.ExtHostUrls); } diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 4ea24f29b426e172c6a53b256c4078202786f191..d196ddd2ca5fd3b94d9012c4df1b8dde96c9a38d 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -110,7 +110,7 @@ import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService'; -import { IInactiveExtensionUrlHandler, InactiveExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; +import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); export const InZenModeContext = new RawContextKey('inZenMode', false); @@ -618,7 +618,7 @@ export class Workbench implements IPartService { serviceCollection.set(ISCMService, new SyncDescriptor(SCMService)); // Inactive extension URL handler - serviceCollection.set(IInactiveExtensionUrlHandler, new SyncDescriptor(InactiveExtensionUrlHandler)); + serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler)); // Text Model Resolver Service serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));