Skip to content

Commit

Permalink
Use openWithSystemApp to open uri on vscode.env.openExternal(#13676)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhuebner committed Jun 25, 2024
1 parent 1f08797 commit 40adb22
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 12 deletions.
4 changes: 3 additions & 1 deletion packages/core/src/browser/http-open-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export interface HttpOpenHandlerOptions {
@injectable()
export class HttpOpenHandler implements OpenHandler {

static readonly PRIORITY: number = 500;

readonly id = 'http';

@inject(WindowService)
Expand All @@ -36,7 +38,7 @@ export class HttpOpenHandler implements OpenHandler {
protected readonly externalUriService: ExternalUriService;

canHandle(uri: URI, options?: HttpOpenHandlerOptions): number {
return ((options && options.openExternal) || uri.scheme.startsWith('http') || uri.scheme.startsWith('mailto')) ? 500 : 0;
return ((options && options.openExternal) || uri.scheme.startsWith('http') || uri.scheme.startsWith('mailto')) ? HttpOpenHandler.PRIORITY : 0;
}

async open(uri: URI): Promise<undefined> {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/electron-browser/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ const api: TheiaCoreAPI = {
showItemInFolder: fsPath => {
ipcRenderer.send(CHANNEL_SHOW_ITEM_IN_FOLDER, fsPath);
},
openWithSystemApp: fsPath => {
ipcRenderer.send(CHANNEL_OPEN_WITH_SYSTEM_APP, fsPath);
openWithSystemApp: location => {
ipcRenderer.send(CHANNEL_OPEN_WITH_SYSTEM_APP, location);
},
attachSecurityToken: (endpoint: string) => ipcRenderer.invoke(CHANNEL_ATTACH_SECURITY_TOKEN, endpoint),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@
// *****************************************************************************

import { ContainerModule } from 'inversify';
import { WindowService } from '../../browser/window/window-service';
import { ElectronWindowService } from './electron-window-service';
import { FrontendApplicationContribution } from '../../browser/frontend-application-contribution';
import { ElectronClipboardService } from '../electron-clipboard-service';
import { OpenHandler } from '../../browser';
import { ClipboardService } from '../../browser/clipboard-service';
import { FrontendApplicationContribution } from '../../browser/frontend-application-contribution';
import { FrontendApplicationStateService } from '../../browser/frontend-application-state';
import { SecondaryWindowService } from '../../browser/window/secondary-window-service';
import { WindowService } from '../../browser/window/window-service';
import { ElectronMainWindowService, electronMainWindowServicePath } from '../../electron-common/electron-main-window-service';
import { ElectronClipboardService } from '../electron-clipboard-service';
import { ElectronIpcConnectionProvider } from '../messaging/electron-ipc-connection-source';
import { bindWindowPreferences } from './electron-window-preferences';
import { FrontendApplicationStateService } from '../../browser/frontend-application-state';
import { ElectronFrontendApplicationStateService } from './electron-frontend-application-state';
import { ElectronSecondaryWindowService } from './electron-secondary-window-service';
import { SecondaryWindowService } from '../../browser/window/secondary-window-service';
import { bindWindowPreferences } from './electron-window-preferences';
import { ElectronWindowService } from './electron-window-service';
import { ExternalAppOpenHandler } from './external-app-open-handler';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ElectronMainWindowService).toDynamicValue(context =>
Expand All @@ -38,4 +40,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ClipboardService).to(ElectronClipboardService).inSingletonScope();
rebind(FrontendApplicationStateService).to(ElectronFrontendApplicationStateService).inSingletonScope();
bind(SecondaryWindowService).to(ElectronSecondaryWindowService).inSingletonScope();
bind(ExternalAppOpenHandler).toSelf().inSingletonScope();
bind(OpenHandler).toService(ExternalAppOpenHandler);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// *****************************************************************************
// Copyright (C) 2024 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { injectable } from 'inversify';
import { OpenHandler } from '../../browser/opener-service';
import URI from '../../common/uri';
import { HttpOpenHandler } from '../../browser/http-open-handler';

export interface ExternalAppOpenHandlerOptions {
openExternalApp?: boolean
}

@injectable()
export class ExternalAppOpenHandler implements OpenHandler {

static readonly PRIORITY: number = HttpOpenHandler.PRIORITY + 100;
readonly id = 'external-app';

canHandle(uri: URI, options?: ExternalAppOpenHandlerOptions): number {
return (options && options.openExternalApp) ? ExternalAppOpenHandler.PRIORITY : -1;
}

async open(uri: URI): Promise<undefined> {
// For files 'file:' scheme, system accepts only the path.
// For other protocols e.g. 'vscode:' we use the full URI to propagate target app information.
window.electronTheiaCore.openWithSystemApp(uri.scheme === 'file' ? uri.path.fsPath() : uri.toString(true));
return undefined;
}
}
6 changes: 5 additions & 1 deletion packages/core/src/electron-common/electron-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ export interface TheiaCoreAPI {
focusWindow(name?: string): void;

showItemInFolder(fsPath: string): void;
openWithSystemApp(fsPath: string): void;

/**
* @param location The location to open with the system app. This can be a file path or a URL.
*/
openWithSystemApp(location: string): void;

getTitleBarStyleAtStartup(): Promise<string>;
setTitleBarStyle(style: string): void;
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/main/browser/window-state-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class WindowStateMain implements WindowMain, Disposable {
const uri = URI.revive(uriComponent);
const url = new CoreURI(encodeURI(uri.toString(true)));
try {
await open(this.openerService, url);
await open(this.openerService, url, { openExternalApp: true });
return true;
} catch (e) {
return false;
Expand Down

0 comments on commit 40adb22

Please sign in to comment.