提交 d5026ed3 编写于 作者: B Benjamin Pasero

fix #79453

上级 df0dd2ed
......@@ -19,10 +19,11 @@ import { localize } from 'vs/nls';
import { IProductService } from 'vs/platform/product/common/product';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import Severity from 'vs/base/common/severity';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class OpenerService implements IOpenerService {
_serviceBrand: any;
_serviceBrand!: ServiceIdentifier<any>;
private readonly _opener = new LinkedList<IOpener>();
......@@ -41,7 +42,7 @@ export class OpenerService implements IOpenerService {
return { dispose: remove };
}
async open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean> {
async open(resource: URI, options?: { openToSide?: boolean, openExternal?: boolean }): Promise<boolean> {
// no scheme ?!?
if (!resource.scheme) {
return Promise.resolve(false);
......@@ -57,13 +58,13 @@ export class OpenerService implements IOpenerService {
return this._doOpen(resource, options);
}
private _doOpen(resource: URI, options?: { openToSide?: boolean }): Promise<boolean> {
private _doOpen(resource: URI, options?: { openToSide?: boolean, openExternal?: boolean }): Promise<boolean> {
const { scheme, authority, path, query, fragment } = resource;
if (equalsIgnoreCase(scheme, Schemas.mailto)) {
if (equalsIgnoreCase(scheme, Schemas.mailto) || (options && options.openExternal)) {
// open default mail application
return this.openExternal(resource);
return this._doOpenExternal(resource);
}
if (equalsIgnoreCase(scheme, Schemas.http) || equalsIgnoreCase(scheme, Schemas.https)) {
......@@ -78,7 +79,7 @@ export class OpenerService implements IOpenerService {
const domainToOpen = `${scheme}://${authority}`;
if (isDomainTrusted(domainToOpen, trustedDomains)) {
return this.openExternal(resource);
return this._doOpenExternal(resource);
} else {
return this._dialogService.show(
Severity.Info,
......@@ -97,11 +98,11 @@ export class OpenerService implements IOpenerService {
cancelId: 1
}).then((choice) => {
if (choice === 0) {
return this.openExternal(resource);
return this._doOpenExternal(resource);
} else if (choice === 2) {
return this._commandService.executeCommand('workbench.action.configureTrustedDomains', domainToOpen).then((pickedDomains: string[]) => {
if (pickedDomains.indexOf(domainToOpen) !== -1) {
return this.openExternal(resource);
return this._doOpenExternal(resource);
}
return Promise.resolve(false);
});
......@@ -152,7 +153,7 @@ export class OpenerService implements IOpenerService {
}
}
openExternal(resource: URI): Promise<boolean> {
private _doOpenExternal(resource: URI): Promise<boolean> {
dom.windowOpenNoOpener(encodeURI(resource.toString(true)));
return Promise.resolve(true);
......
......@@ -11,6 +11,7 @@ export const IOpenerService = createDecorator<IOpenerService>('openerService');
export interface IOpener {
open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean>;
open(resource: URI, options?: { openExternal?: boolean }): Promise<boolean>;
}
export interface IOpenerService {
......@@ -29,18 +30,11 @@ export interface IOpenerService {
* @return A promise that resolves when the opening is done.
*/
open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean>;
/**
* Opens a URL externally.
*
* @param url A resource to open externally.
*/
openExternal(resource: URI): Promise<boolean>;
open(resource: URI, options?: { openExternal?: boolean }): Promise<boolean>;
}
export const NullOpenerService: IOpenerService = Object.freeze({
_serviceBrand: undefined,
registerOpener() { return { dispose() { } }; },
open() { return Promise.resolve(false); },
openExternal() { return Promise.resolve(false); }
});
......@@ -27,12 +27,16 @@ export class RelayURLService extends URLService implements IURLHandler {
openerService.registerOpener(this);
}
async open(uri: URI): Promise<boolean> {
if (uri.scheme !== product.urlProtocol) {
async open(resource: URI, options?: { openToSide?: boolean, openExternal?: boolean }): Promise<boolean> {
if (options && options.openExternal) {
return false;
}
return await this.urlService.open(uri);
if (resource.scheme !== product.urlProtocol) {
return false;
}
return await this.urlService.open(resource);
}
handleURL(uri: URI): Promise<boolean> {
......
......@@ -59,7 +59,7 @@ export class MainThreadWindow implements MainThreadWindowShape {
}
}
return this.openerService.openExternal(uri);
return this.openerService.open(uri, { openExternal: true });
}
private getOrCreateTunnel(remotePort: number): Promise<RemoteTunnel> | undefined {
......
......@@ -38,7 +38,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor {
BinaryFileEditor.ID,
{
openInternal: (input, options) => this.openInternal(input, options),
openExternal: resource => this.openerService.openExternal(resource)
openExternal: resource => this.openerService.open(resource, { openExternal: true })
},
telemetryService,
themeService,
......
......@@ -54,6 +54,8 @@ import { IPreferencesService } from '../services/preferences/common/preferences'
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IMenubarService, IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/node/menubar';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { Schemas } from 'vs/base/common/network';
const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), undefined, true, () => Promise.resolve(document.execCommand('undo'))),
......@@ -101,7 +103,8 @@ export class ElectronWindow extends Disposable {
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@ITextFileService private readonly textFileService: ITextFileService,
@IInstantiationService private readonly instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IOpenerService private readonly openerService: IOpenerService
) {
super();
......@@ -312,13 +315,8 @@ export class ElectronWindow extends Disposable {
this._register(this.instantiationService.createInstance(NativeMenubarControl));
}
// Handle window.open() calls
const $this = this;
window.open = function (url: string, target: string, features: string, replace: boolean): Window | null {
$this.windowsService.openExternal(url);
return null;
};
// Handle open calls
this.setupOpenHandlers();
// Emit event when vscode is ready
this.lifecycleService.when(LifecyclePhase.Ready).then(() => ipc.send('vscode:workbenchReady', this.windowService.windowId));
......@@ -356,6 +354,35 @@ export class ElectronWindow extends Disposable {
}
}
private setupOpenHandlers(): void {
// Handle window.open() calls
const $this = this;
window.open = function (url: string, target: string, features: string, replace: boolean): Window | null {
$this.windowsService.openExternal(url);
return null;
};
// Handle external open calls
this.openerService.registerOpener({
async open(resource: URI, options?: { openToSide?: boolean; openExternal?: boolean; } | undefined): Promise<boolean> {
if (!options || !options.openExternal) {
return false; // only override behaviour for external open()
}
const success = await $this.windowsService.openExternal(encodeURI(resource.toString(true)));
if (!success && resource.scheme === Schemas.file) {
await $this.windowsService.showItemInFolder(resource);
return true;
}
return success;
}
});
}
private updateTouchbarMenu(): void {
if (!isMacintosh) {
return; // macOS only
......@@ -741,4 +768,4 @@ class NativeMenubarControl extends MenubarControl {
return undefined;
}
}
\ No newline at end of file
}
......@@ -79,7 +79,7 @@ export class WorkspaceWatcher extends Disposable {
localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."),
[{
label: localize('installNet', "Download .NET Framework 4.5"),
run: () => this.openerService.openExternal(URI.parse('https://go.microsoft.com/fwlink/?LinkId=786533'))
run: () => this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?LinkId=786533'))
}],
{
sticky: true,
......@@ -95,7 +95,7 @@ export class WorkspaceWatcher extends Disposable {
localize('enospcError', "Unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue."),
[{
label: localize('learnMore', "Instructions"),
run: () => this.openerService.openExternal(URI.parse('https://go.microsoft.com/fwlink/?linkid=867693'))
run: () => this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=867693'))
}],
{
sticky: true,
......
......@@ -93,7 +93,7 @@ export class IntegrityServiceImpl implements IIntegrityService {
[
{
label: nls.localize('integrity.moreInformation', "More Information"),
run: () => this.openerService.openExternal(URI.parse(product.checksumFailMoreInfoUrl))
run: () => this.openerService.open(URI.parse(product.checksumFailMoreInfoUrl))
},
{
label: nls.localize('integrity.dontShowAgain', "Don't Show Again"),
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { OpenerService as BaseOpenerService } from 'vs/editor/browser/services/openerService';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IProductService } from 'vs/platform/product/common/product';
import { IStorageService } from 'vs/platform/storage/common/storage';
export class OpenerService extends BaseOpenerService {
_serviceBrand!: ServiceIdentifier<any>;
constructor(
@ICodeEditorService codeEditorService: ICodeEditorService,
@ICommandService commandService: ICommandService,
@IWindowsService private readonly windowsService: IWindowsService,
@IStorageService readonly storageService: IStorageService,
@IDialogService readonly dialogService: IDialogService,
@IProductService readonly productService: IProductService
) {
super(codeEditorService, commandService, storageService, dialogService, productService);
}
async openExternal(resource: URI): Promise<boolean> {
const success = this.windowsService.openExternal(encodeURI(resource.toString(true)));
if (!success && resource.scheme === Schemas.file) {
await this.windowsService.showItemInFolder(resource);
return true;
}
return success;
}
}
registerSingleton(IOpenerService, OpenerService, true);
......@@ -96,6 +96,8 @@ import { IMenuService } from 'vs/platform/actions/common/actions';
import { MenuService } from 'vs/platform/actions/common/menuService';
import { IDownloadService } from 'vs/platform/download/common/download';
import { DownloadService } from 'vs/platform/download/common/downloadService';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
registerSingleton(IContextViewService, ContextViewService, true);
......@@ -108,6 +110,7 @@ registerSingleton(IModelService, ModelServiceImpl, true);
registerSingleton(ITextResourceConfigurationService, TextResourceConfigurationService);
registerSingleton(IMenuService, MenuService, true);
registerSingleton(IDownloadService, DownloadService, true);
registerSingleton(IOpenerService, OpenerService, true);
//#endregion
......
......@@ -48,7 +48,6 @@ import 'vs/workbench/services/extensionManagement/node/extensionManagementServic
import 'vs/workbench/services/accessibility/node/accessibilityService';
import 'vs/workbench/services/remote/node/tunnelService';
import 'vs/workbench/services/backup/node/backupFileService';
import 'vs/workbench/services/opener/electron-browser/openerService';
import 'vs/workbench/services/credentials/node/credentialsService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
......
......@@ -56,8 +56,6 @@ import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuS
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { BackupFileService } from 'vs/workbench/services/backup/common/backupFileService';
import { ExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
registerSingleton(IRequestService, RequestService, true);
registerSingleton(IExtensionManagementService, ExtensionManagementService);
......@@ -67,7 +65,6 @@ registerSingleton(IClipboardService, BrowserClipboardService, true);
registerSingleton(IAccessibilityService, BrowserAccessibilityService, true);
registerSingleton(ILifecycleService, BrowserLifecycleService);
registerSingleton(IContextMenuService, ContextMenuService);
registerSingleton(IOpenerService, OpenerService, true);
//#endregion
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册