Skip to content

Commit 2ab6546

Browse files
committed
debt - make url service contribute to opener service, microsoft#70319
1 parent 85afabd commit 2ab6546

4 files changed

Lines changed: 41 additions & 14 deletions

File tree

src/vs/editor/browser/services/openerService.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,48 @@ import * as resources from 'vs/base/common/resources';
1010
import { URI } from 'vs/base/common/uri';
1111
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
1212
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
13-
import { IOpenerService } from 'vs/platform/opener/common/opener';
13+
import { IOpenerService, IOpener } from 'vs/platform/opener/common/opener';
1414
import { equalsIgnoreCase } from 'vs/base/common/strings';
15+
import { IDisposable } from 'vs/base/common/lifecycle';
16+
import { LinkedList } from 'vs/base/common/linkedList';
1517

1618
export class OpenerService implements IOpenerService {
1719

1820
_serviceBrand: any;
1921

22+
private readonly _opener = new LinkedList<IOpener>();
23+
2024
constructor(
2125
@ICodeEditorService private readonly _editorService: ICodeEditorService,
2226
@ICommandService private readonly _commandService: ICommandService,
2327
) {
2428
//
2529
}
2630

27-
open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean> {
28-
29-
const { scheme, path, query, fragment } = resource;
31+
registerOpener(opener: IOpener): IDisposable {
32+
const remove = this._opener.push(opener);
33+
return { dispose: remove };
34+
}
3035

31-
if (!scheme) {
32-
// no scheme ?!?
36+
async open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean> {
37+
// no scheme ?!?
38+
if (!resource.scheme) {
3339
return Promise.resolve(false);
3440
}
41+
// check with contributed openers
42+
for (const opener of this._opener.toArray()) {
43+
const handled = await opener.open(resource, options);
44+
if (handled) {
45+
return true;
46+
}
47+
}
48+
// use default openers
49+
return this._doOpen(resource, options);
50+
}
51+
52+
private _doOpen(resource: URI, options?: { openToSide?: boolean }): Promise<boolean> {
53+
54+
const { scheme, path, query, fragment } = resource;
3555

3656
if (equalsIgnoreCase(scheme, Schemas.http) || equalsIgnoreCase(scheme, Schemas.https) || equalsIgnoreCase(scheme, Schemas.mailto)) {
3757
// open http or default mail application

src/vs/platform/opener/common/opener.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
55

66
import { URI } from 'vs/base/common/uri';
77
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
8+
import { IDisposable } from 'vs/base/common/lifecycle';
89

910
export const IOpenerService = createDecorator<IOpenerService>('openerService');
1011

12+
13+
export interface IOpener {
14+
open(resource: URI, options?: { openToSide?: boolean }): Promise<boolean>;
15+
}
16+
1117
export interface IOpenerService {
1218

1319
_serviceBrand: any;
1420

21+
registerOpener(opener: IOpener): IDisposable;
22+
1523
/**
1624
* Opens a resource, like a webadress, a document uri, or executes command.
1725
*
@@ -23,5 +31,6 @@ export interface IOpenerService {
2331

2432
export const NullOpenerService: IOpenerService = Object.freeze({
2533
_serviceBrand: undefined,
34+
registerOpener() { return { dispose() { } }; },
2635
open() { return Promise.resolve(false); }
2736
});

src/vs/platform/url/electron-browser/urlService.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,21 @@ import { URI } from 'vs/base/common/uri';
88
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
99
import { URLServiceChannelClient, URLHandlerChannel } from 'vs/platform/url/node/urlIpc';
1010
import { URLService } from 'vs/platform/url/common/urlService';
11+
import { IOpenerService } from 'vs/platform/opener/common/opener';
1112

1213
export class RelayURLService extends URLService implements IURLHandler {
1314
private urlService: IURLService;
1415

15-
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
16+
constructor(
17+
@IMainProcessService mainProcessService: IMainProcessService,
18+
@IOpenerService openerService: IOpenerService
19+
) {
1620
super();
1721

1822
this.urlService = new URLServiceChannelClient(mainProcessService.getChannel('url'));
1923

2024
mainProcessService.registerChannel('urlHandler', new URLHandlerChannel(this));
25+
openerService.registerOpener(this);
2126
}
2227

2328
open(uri: URI): Promise<boolean> {

src/vs/workbench/api/electron-browser/mainThreadEditors.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContex
2424
import { EditorViewColumn, editorGroupToViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
2525
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
2626
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
27-
import { IURLService } from 'vs/platform/url/common/url';
28-
import product from 'vs/platform/product/node/product';
2927

3028
export class MainThreadTextEditors implements MainThreadTextEditorsShape {
3129

@@ -270,7 +268,6 @@ CommandsRegistry.registerCommand('_workbench.open', function (accessor: Services
270268
const editorService = accessor.get(IEditorService);
271269
const editorGroupService = accessor.get(IEditorGroupsService);
272270
const openerService = accessor.get(IOpenerService);
273-
const urlService = accessor.get(IURLService);
274271

275272
const [resource, options, position, label] = args;
276273

@@ -282,12 +279,8 @@ CommandsRegistry.registerCommand('_workbench.open', function (accessor: Services
282279
if (resource && resource.scheme === 'command') {
283280
// do not allow to execute commands from here
284281
return Promise.resolve(undefined);
285-
}
286282

287-
if (resource && (resource.scheme === product.urlProtocol || /^vscode/.test(resource.scheme))) {
288-
return urlService.open(resource).then(_ => undefined);
289283
}
290-
291284
// finally, delegate to opener service
292285
return openerService.open(resource).then(_ => undefined);
293286
});

0 commit comments

Comments
 (0)