mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 17:48:56 +01:00
Make the external opener a two phase process
This changes makes a few changes to the openers: - Move the opener prompting from the extension host into the main thread - Make the external opener process two phases: get openers and then open. This would let us skip the trusted domain validation for extension handled links if we want to in the future - Add lifecycle to commands used by the uri opener For #109277
This commit is contained in:
@@ -9,9 +9,9 @@ import { toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostUriOpenersShape, IMainContext, MainContext, MainThreadUriOpenersShape } from './extHost.protocol';
|
||||
import { Cache } from './cache';
|
||||
import { ChainedCacheId, ExtHostUriOpenersShape, IMainContext, MainContext, MainThreadUriOpenersShape } from './extHost.protocol';
|
||||
|
||||
export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
|
||||
|
||||
@@ -19,18 +19,16 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
|
||||
|
||||
private readonly _proxy: MainThreadUriOpenersShape;
|
||||
private readonly _commands: ExtHostCommands;
|
||||
private readonly _quickOpen: ExtHostQuickOpen;
|
||||
|
||||
private readonly _cache = new Cache<vscode.Command>('CodeAction');
|
||||
private readonly _openers = new Map<number, { schemes: ReadonlySet<string>, opener: vscode.ExternalUriOpener }>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
commands: ExtHostCommands,
|
||||
quickOpen: ExtHostQuickOpen,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadUriOpeners);
|
||||
this._commands = commands;
|
||||
this._quickOpen = quickOpen;
|
||||
}
|
||||
|
||||
registerUriOpener(
|
||||
@@ -49,7 +47,7 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
|
||||
});
|
||||
}
|
||||
|
||||
async $openUri(uriComponents: UriComponents, ctx: { originalUri: UriComponents }, token: CancellationToken): Promise<boolean> {
|
||||
async $getOpenersForUri(uriComponents: UriComponents, token: CancellationToken): Promise<{ cacheId: number, openers: Array<{ id: number, title: string }> }> {
|
||||
const uri = URI.revive(uriComponents);
|
||||
|
||||
const promises = Array.from(this._openers.values()).map(async ({ schemes, opener }): Promise<vscode.Command | undefined> => {
|
||||
@@ -58,9 +56,7 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await opener.openExternalUri(uri, {
|
||||
originalUri: URI.revive(ctx.originalUri),
|
||||
}, token);
|
||||
const result = await opener.openExternalUri(uri, {}, token);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
@@ -71,30 +67,24 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const results = coalesce(await Promise.all(promises));
|
||||
const commands = coalesce(await Promise.all(promises));
|
||||
const cacheId = this._cache.add(commands);
|
||||
return {
|
||||
cacheId,
|
||||
openers: commands.map((command, i) => ({ title: command.title, id: i })),
|
||||
};
|
||||
}
|
||||
|
||||
if (results.length === 0) {
|
||||
return false;
|
||||
} else if (results.length === 1) {
|
||||
const [command] = results;
|
||||
await this._commands.executeCommand(command.command, ...(command.arguments ?? []));
|
||||
return true;
|
||||
} else {
|
||||
type PickItem = vscode.QuickPickItem & { index: number };
|
||||
const items = results.map((command, i): PickItem => {
|
||||
return {
|
||||
label: command.title,
|
||||
index: i
|
||||
};
|
||||
});
|
||||
const picked = await this._quickOpen.showQuickPick(items, false, {});
|
||||
if (picked) {
|
||||
const command = results[(picked as PickItem).index];
|
||||
await this._commands.executeCommand(command.command, ...(command.arguments ?? []));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
async $openUri(id: ChainedCacheId, uri: UriComponents): Promise<void> {
|
||||
const command = this._cache.get(id[0], id[1]);
|
||||
if (!command) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._commands.executeCommand(command.command, URI.revive(uri), ...(command.arguments || []));
|
||||
}
|
||||
|
||||
$releaseOpener(cacheId: number): void {
|
||||
this._cache.delete(cacheId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user