Skip to content

Commit 666396d

Browse files
authored
Avoid extensionService.getExtension and use ActivationKind.Immediate to allow that URI handling works while resolving (microsoft#184310)
Avoid `extensionService.getExtension` and use `ActivationKind.Immediate` to allow that URI handling works while resolving (fixes microsoft#182217)
1 parent d42cf24 commit 666396d

File tree

5 files changed

+39
-24
lines changed

5 files changed

+39
-24
lines changed

src/vs/workbench/api/browser/mainThreadUrls.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@
55

66
import { ExtHostContext, MainContext, MainThreadUrlsShape, ExtHostUrlsShape } from 'vs/workbench/api/common/extHost.protocol';
77
import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers';
8-
import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url';
8+
import { IURLService, IOpenURLOptions } from 'vs/platform/url/common/url';
99
import { URI, UriComponents } from 'vs/base/common/uri';
1010
import { IDisposable } from 'vs/base/common/lifecycle';
11-
import { IExtensionUrlHandler } from 'vs/workbench/services/extensions/browser/extensionUrlHandler';
11+
import { IExtensionContributedURLHandler, IExtensionUrlHandler } from 'vs/workbench/services/extensions/browser/extensionUrlHandler';
1212
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
1313

14-
class ExtensionUrlHandler implements IURLHandler {
14+
class ExtensionUrlHandler implements IExtensionContributedURLHandler {
1515

1616
constructor(
1717
private readonly proxy: ExtHostUrlsShape,
1818
private readonly handle: number,
19-
readonly extensionId: ExtensionIdentifier
19+
readonly extensionId: ExtensionIdentifier,
20+
readonly extensionDisplayName: string
2021
) { }
2122

2223
handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
@@ -42,8 +43,8 @@ export class MainThreadUrls implements MainThreadUrlsShape {
4243
this.proxy = context.getProxy(ExtHostContext.ExtHostUrls);
4344
}
4445

45-
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void> {
46-
const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId);
46+
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier, extensionDisplayName: string): Promise<void> {
47+
const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId, extensionDisplayName);
4748
const disposable = this.urlService.registerHandler(handler);
4849

4950
this.handlers.set(handle, { extensionId, disposable });

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
788788
return extHostDecorations.registerFileDecorationProvider(provider, extension);
789789
},
790790
registerUriHandler(handler: vscode.UriHandler) {
791-
return extHostUrls.registerUriHandler(extension.identifier, handler);
791+
return extHostUrls.registerUriHandler(extension, handler);
792792
},
793793
createQuickPick<T extends vscode.QuickPickItem>(): vscode.QuickPick<T> {
794794
return extHostQuickOpen.createQuickPick(extension);

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ export interface ExtHostInteractiveEditorShape {
11301130
}
11311131

11321132
export interface MainThreadUrlsShape extends IDisposable {
1133-
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void>;
1133+
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier, extensionDisplayName: string): Promise<void>;
11341134
$unregisterUriHandler(handle: number): Promise<void>;
11351135
$createAppUri(uri: UriComponents): Promise<UriComponents>;
11361136
}

src/vs/workbench/api/common/extHostUrls.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from
88
import { URI, UriComponents } from 'vs/base/common/uri';
99
import { toDisposable } from 'vs/base/common/lifecycle';
1010
import { onUnexpectedError } from 'vs/base/common/errors';
11-
import { ExtensionIdentifier, ExtensionIdentifierSet } from 'vs/platform/extensions/common/extensions';
11+
import { ExtensionIdentifierSet, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
1212

1313
export class ExtHostUrls implements ExtHostUrlsShape {
1414

@@ -24,15 +24,16 @@ export class ExtHostUrls implements ExtHostUrlsShape {
2424
this._proxy = mainContext.getProxy(MainContext.MainThreadUrls);
2525
}
2626

27-
registerUriHandler(extensionId: ExtensionIdentifier, handler: vscode.UriHandler): vscode.Disposable {
27+
registerUriHandler(extension: IExtensionDescription, handler: vscode.UriHandler): vscode.Disposable {
28+
const extensionId = extension.identifier;
2829
if (this.handles.has(extensionId)) {
2930
throw new Error(`Protocol handler already registered for extension ${extensionId}`);
3031
}
3132

3233
const handle = ExtHostUrls.HandlePool++;
3334
this.handles.add(extensionId);
3435
this.handlers.set(handle, handler);
35-
this._proxy.$registerUriHandler(handle, extensionId);
36+
this._proxy.$registerUriHandler(handle, extensionId, extension.displayName || extension.name);
3637

3738
return toDisposable(() => {
3839
this.handles.delete(extensionId);

src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
1616
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
1717
import { IURLHandler, IURLService, IOpenURLOptions } from 'vs/platform/url/common/url';
1818
import { IHostService } from 'vs/workbench/services/host/browser/host';
19-
import { IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
19+
import { ActivationKind, IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
2020
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
2121
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
2222
import { Registry } from 'vs/platform/registry/common/platform';
@@ -70,9 +70,13 @@ class UserTrustedExtensionIdStorage {
7070

7171
export const IExtensionUrlHandler = createDecorator<IExtensionUrlHandler>('extensionUrlHandler');
7272

73+
export interface IExtensionContributedURLHandler extends IURLHandler {
74+
extensionDisplayName: string;
75+
}
76+
7377
export interface IExtensionUrlHandler {
7478
readonly _serviceBrand: undefined;
75-
registerExtensionHandler(extensionId: ExtensionIdentifier, handler: IURLHandler): void;
79+
registerExtensionHandler(extensionId: ExtensionIdentifier, handler: IExtensionContributedURLHandler): void;
7680
unregisterExtensionHandler(extensionId: ExtensionIdentifier): void;
7781
}
7882

@@ -99,7 +103,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
99103

100104
readonly _serviceBrand: undefined;
101105

102-
private extensionHandlers = new Map<string, IURLHandler>();
106+
private extensionHandlers = new Map<string, IExtensionContributedURLHandler>();
103107
private uriBuffer = new Map<string, { timestamp: number; uri: URI }[]>();
104108
private userTrustedExtensionsStorage: UserTrustedExtensionIdStorage;
105109
private disposable: IDisposable;
@@ -145,12 +149,20 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
145149
const extensionId = uri.authority;
146150
this.telemetryService.publicLog2<ExtensionUrlHandlerEvent, ExtensionUrlHandlerClassification>('uri_invoked/start', { extensionId });
147151

148-
const wasHandlerAvailable = this.extensionHandlers.has(ExtensionIdentifier.toKey(extensionId));
149-
const extension = await this.extensionService.getExtension(extensionId);
152+
const initialHandler = this.extensionHandlers.get(ExtensionIdentifier.toKey(extensionId));
153+
let extensionDisplayName: string;
150154

151-
if (!extension) {
152-
await this.handleUnhandledURL(uri, { id: extensionId }, options);
153-
return true;
155+
if (!initialHandler) {
156+
// The extension is not yet activated, so let's check if it is installed and enabled
157+
const extension = await this.extensionService.getExtension(extensionId);
158+
if (!extension) {
159+
await this.handleUnhandledURL(uri, { id: extensionId }, options);
160+
return true;
161+
} else {
162+
extensionDisplayName = extension.displayName || extension.name;
163+
}
164+
} else {
165+
extensionDisplayName = initialHandler.extensionDisplayName;
154166
}
155167

156168
const trusted = options?.trusted
@@ -169,7 +181,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
169181
checkbox: {
170182
label: localize('rememberConfirmUrl', "Don't ask again for this extension."),
171183
},
172-
detail: `${extension.displayName || extension.name} (${extensionId}) wants to open a URI:\n\n${uriString}`,
184+
detail: `${extensionDisplayName} (${extensionId}) wants to open a URI:\n\n${uriString}`,
173185
primaryButton: localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Open")
174186
});
175187

@@ -186,7 +198,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
186198
const handler = this.extensionHandlers.get(ExtensionIdentifier.toKey(extensionId));
187199

188200
if (handler) {
189-
if (!wasHandlerAvailable) {
201+
if (!initialHandler) {
190202
// forward it directly
191203
return await this.handleURLByExtension(extensionId, handler, uri, options);
192204
}
@@ -206,12 +218,13 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
206218

207219
uris.push({ timestamp, uri });
208220

209-
// activate the extension
210-
await this.extensionService.activateByEvent(`onUri:${ExtensionIdentifier.toKey(extensionId)}`);
221+
// activate the extension using ActivationKind.Immediate because URI handling might be part
222+
// of resolving authorities (via authentication extensions)
223+
await this.extensionService.activateByEvent(`onUri:${ExtensionIdentifier.toKey(extensionId)}`, ActivationKind.Immediate);
211224
return true;
212225
}
213226

214-
registerExtensionHandler(extensionId: ExtensionIdentifier, handler: IURLHandler): void {
227+
registerExtensionHandler(extensionId: ExtensionIdentifier, handler: IExtensionContributedURLHandler): void {
215228
this.extensionHandlers.set(ExtensionIdentifier.toKey(extensionId), handler);
216229

217230
const uris = this.uriBuffer.get(ExtensionIdentifier.toKey(extensionId)) || [];

0 commit comments

Comments
 (0)