diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index ac970624ec8..74cd460f5e3 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow } from 'electron'; +import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow, dialog } from 'electron'; import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; @@ -80,6 +80,7 @@ import { coalesce } from 'vs/base/common/arrays'; import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { StorageKeysSyncRegistryChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -605,6 +606,11 @@ export class CodeApplication extends Disposable { return undefined; } })).filter(pendingUriToHandle => { + // if URI should be blocked, filter it out + if (this.shouldBlockURI(pendingUriToHandle)) { + return false; + } + // filter out any protocol link that wants to open as window so that // we open the right set of windows on startup and not restore the // previous workspace too. @@ -623,6 +629,10 @@ export class CodeApplication extends Disposable { const environmentService = this.environmentService; urlService.registerHandler({ async handleURL(uri: URI): Promise { + // if URI should be blocked, behave as if it's handled + if (app.shouldBlockURI(uri)) { + return true; + } // Check for URIs to open in window const windowOpenableFromProtocolLink = app.getWindowOpenableFromProtocolLink(uri); @@ -727,6 +737,29 @@ export class CodeApplication extends Disposable { }); } + private shouldBlockURI(uri: URI): boolean { + if (uri.authority === Schemas.file && isWindows) { + const res = dialog.showMessageBoxSync({ + title: product.nameLong, + type: 'question', + buttons: [ + mnemonicButtonLabel(localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Yes")), + mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")), + ], + cancelId: 1, + message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath), product.nameShort), + detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"), + noLink: true + }); + + if (res === 1) { + return true; + } + } + + return false; + } + private getWindowOpenableFromProtocolLink(uri: URI): IWindowOpenable | undefined { if (!uri.path) { return undefined;