urls - first cut better windowId=_blank support

This commit is contained in:
Benjamin Pasero 2023-01-15 11:49:13 +01:00
parent dafad403e9
commit be0197d61d
No known key found for this signature in database
GPG Key ID: E6380CC4C8219E65
2 changed files with 55 additions and 20 deletions

View File

@ -576,7 +576,7 @@ export class CodeApplication extends Disposable {
// Check for initial URLs to handle from protocol url
// invocations that happened right on startup
const initialProtocolUrls = this.resolveProtocolUrls();
const initialProtocolUrls = this.resolveInitialProtocolUrls();
// Create a URL handler to open file URIs in the active window
// or open new windows. The URL handler will be invoked from
@ -606,18 +606,18 @@ export class CodeApplication extends Disposable {
return initialProtocolUrls;
}
private resolveProtocolUrls(): IInitialProtocolUrls {
private resolveInitialProtocolUrls(): IInitialProtocolUrls {
// Windows/Linux: protocol handler invokes CLI with --open-url
const protocolUrlsFromCommandLine = this.environmentMainService.args['open-url'] ? this.environmentMainService.args._urls || [] : [];
if (protocolUrlsFromCommandLine.length) {
this.logService.trace('app#resolveProtocolUrls() protocol urls from command line:', protocolUrlsFromCommandLine);
this.logService.trace('app#resolveInitialProtocolUrls() protocol urls from command line:', protocolUrlsFromCommandLine);
}
// macOS: open-url events that were received before the app is ready
const protocolUrlsFromEvent = ((<any>global).getOpenUrls() || []) as string[];
if (protocolUrlsFromEvent.length) {
this.logService.trace(`app#resolveProtocolUrls() protocol urls from macOS 'open-url' event:`, protocolUrlsFromEvent);
this.logService.trace(`app#resolveInitialProtocolUrls() protocol urls from macOS 'open-url' event:`, protocolUrlsFromEvent);
}
// Go over all protocol urls and split window openables
@ -626,6 +626,7 @@ export class CodeApplication extends Disposable {
// Filter out blocked urls or invalid ones.
const openables: IWindowOpenable[] = [];
const emptyWindows: IProtocolUrl[] = [];
const urls = [
...protocolUrlsFromCommandLine,
...protocolUrlsFromEvent
@ -633,40 +634,49 @@ export class CodeApplication extends Disposable {
try {
return { uri: URI.parse(url), originalUrl: url };
} catch {
this.logService.trace('app#resolveProtocolUrls() protocol url failed to parse:', url);
this.logService.trace('app#resolveInitialProtocolUrls() protocol url failed to parse:', url);
return undefined;
}
}).filter((obj): obj is IProtocolUrl => {
if (!obj) {
return false;
return false; // invalid
}
// If URI should be blocked, filter it out
if (this.shouldBlockURI(obj.uri)) {
this.logService.trace('app#resolveProtocolUrls() protocol url was blocked:', obj.uri.toString(true));
this.logService.trace('app#resolveInitialProtocolUrls() protocol url was blocked:', obj.uri.toString(true));
return false;
return false; // blocked
}
// Filter out any protocol url that wants to open as window so that
// we open the right set of windows on startup and not restore the
// previous workspace too.
const windowOpenable = this.getWindowOpenableFromProtocolUrl(obj.uri);
if (windowOpenable) {
this.logService.trace('app#resolveProtocolUrls() protocol url will be handled as window to open:', obj.uri.toString(true), windowOpenable);
this.logService.trace('app#resolveInitialProtocolUrls() protocol url will be handled as window to open:', obj.uri.toString(true), windowOpenable);
openables.push(windowOpenable);
return false;
return false; // handled as window to open
}
this.logService.trace('app#resolveProtocolUrls() protocol url will be passed to active window for handling:', obj.uri.toString(true));
const params = new URLSearchParams(obj.uri.query);
if (params.get('windowId') === '_blank') {
this.logService.trace(`app#resolveInitialProtocolUrls() found 'windowId=_blank' as parameter, protocol url will be handled as empty window to open:`, obj.uri.toString(true));
return true;
params.delete('windowId');
obj.originalUrl = obj.uri.toString(true);
obj.uri = obj.uri.with({ query: params.toString() });
emptyWindows.push(obj);
return true; // still needs to be handled within empty window
}
this.logService.trace('app#resolveInitialProtocolUrls() protocol url will be passed to active window for handling:', obj.uri.toString(true));
return true; // handled within active window
});
return { urls, openables };
return { urls, openables, emptyWindows };
}
private shouldBlockURI(uri: URI): boolean {
@ -904,7 +914,6 @@ export class CodeApplication extends Disposable {
// Webview Manager
services.set(IWebviewManagerService, new SyncDescriptor(WebviewMainService));
// Menubar
services.set(IMenubarMainService, new SyncDescriptor(MenubarMainService));
@ -1085,6 +1094,7 @@ export class CodeApplication extends Disposable {
private async openFirstWindow(accessor: ServicesAccessor, initialProtocolUrls: IInitialProtocolUrls): Promise<ICodeWindow[]> {
const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService);
const context = isLaunchedFromCli(process.env) ? OpenContext.CLI : OpenContext.DESKTOP;
const args = this.environmentMainService.args;
@ -1100,6 +1110,17 @@ export class CodeApplication extends Disposable {
});
}
// If we have empty windows from protocol URLs, open one directly
if (initialProtocolUrls.emptyWindows.length > 0) {
return windowsMainService.open({
context,
cli: args,
forceNewWindow: true,
forceEmpty: true,
gotoLineMode: true
});
}
const macOpenFiles: string[] = (<any>global).macOpenFiles;
const hasCliArgs = args._.length;
const hasFolderURIs = !!args['folder-uri'];

View File

@ -26,13 +26,27 @@ export interface IInitialProtocolUrls {
/**
* Initial protocol URLs to handle that are not
* already converted to `IWindowOpenable` instances.
* already converted to `IWindowOpenable` or empty
* window instances.
*
* These URLs will be handled by the URL service
* in the active window (i.e. forwarded to extensions).
*/
readonly urls: IProtocolUrl[];
/**
* Initial protocol URLs that result in direct
* `IWindowOpenable` instances.
* `IWindowOpenable` instances. These are not
* handled within the URL service but directly
* result in a window to open (currently only
* `file` and `vscode-remote` URLs).
*/
readonly openables: IWindowOpenable[];
/**
* Initial protocol URLs that result require
* a new window to be handled within (having
* a `windowId` property of `blank`).
*/
readonly emptyWindows: IProtocolUrl[];
}