Merge branch 'urlservice'
This commit is contained in:
commit
bd81089174
|
@ -108,6 +108,11 @@ const config = {
|
|||
extensions: ["ascx", "asp", "aspx", "bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "bat", "bowerrc", "c", "cc", "clj", "cljs", "cljx", "clojure", "cmd", "coffee", "config", "cpp", "cs", "cshtml", "csproj", "css", "csx", "ctp", "cxx", "dockerfile", "dot", "dtd", "editorconfig", "edn", "eyaml", "eyml", "fs", "fsi", "fsscript", "fsx", "gemspec", "gitattributes", "gitconfig", "gitignore", "go", "h", "handlebars", "hbs", "hh", "hpp", "htm", "html", "hxx", "ini", "jade", "jav", "java", "js", "jscsrc", "jshintrc", "jshtm", "json", "jsp", "less", "lua", "m", "makefile", "markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn", "ml", "mli", "php", "phtml", "pl", "pl6", "pm", "pm6", "pod", "pp", "profile", "properties", "ps1", "psd1", "psgi", "psm1", "py", "r", "rb", "rhistory", "rprofile", "rs", "rt", "scss", "sh", "shtml", "sql", "svg", "svgz", "t", "ts", "txt", "vb", "wxi", "wxl", "wxs", "xaml", "xml", "yaml", "yml", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"],
|
||||
iconFile: 'resources/darwin/code_file.icns'
|
||||
}],
|
||||
darwinBundleURLTypes: [{
|
||||
role: 'Viewer',
|
||||
name: product.nameLong,
|
||||
urlSchemes: [product.urlProtocol]
|
||||
}],
|
||||
darwinCredits: darwinCreditsTemplate ? new Buffer(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
|
||||
linuxExecutableName: product.applicationName,
|
||||
winIcon: 'resources/win32/code.ico',
|
||||
|
|
18
src/vs/base/node/event.ts
Normal file
18
src/vs/base/node/event.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export function fromEventEmitter<T>(emitter: EventEmitter, eventName: string, map: (...args: any[]) => T = ([arg]) => arg): Event<T> {
|
||||
const fn = (...args) => result.fire(map(...args));
|
||||
const onFirstListenerAdd = () => emitter.on(eventName, fn);
|
||||
const onLastListenerRemove = () => emitter.removeListener(eventName, fn);
|
||||
const result = new Emitter<T>({ onFirstListenerAdd, onLastListenerRemove });
|
||||
|
||||
return result.event;
|
||||
};
|
108
src/vs/base/parts/ipc/common/ipc.electron.ts
Normal file
108
src/vs/base/parts/ipc/common/ipc.electron.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import Event, { mapEvent, filterEvent } from 'vs/base/common/event';
|
||||
import { fromEventEmitter } from 'vs/base/node/event';
|
||||
import { Server as IPCServer, Client as IPCClient, IServer, IClient, IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
const Hello = 'ipc:hello';
|
||||
const Goodbye = 'ipc:goodbye';
|
||||
const Message = 'ipc:message';
|
||||
|
||||
export interface Sender {
|
||||
send(channel: string, ...args: any[]): void;
|
||||
}
|
||||
|
||||
export interface IPC extends Sender, NodeJS.EventEmitter {}
|
||||
|
||||
class Protocol implements IMessagePassingProtocol {
|
||||
|
||||
private listener: IDisposable;
|
||||
|
||||
constructor(private sender: Sender, private onMessageEvent: Event<any>) {}
|
||||
|
||||
send(message: any): void {
|
||||
this.sender.send(Message, message);
|
||||
}
|
||||
|
||||
onMessage(callback: (message: any) => void): void {
|
||||
this.listener = this.onMessageEvent(callback);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.listener = dispose(this.listener);
|
||||
}
|
||||
}
|
||||
|
||||
interface IIPCEvent {
|
||||
event: any;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class Server implements IServer, IDisposable {
|
||||
|
||||
private channels: { [name: string]: IChannel } = Object.create(null);
|
||||
|
||||
constructor(private ipc: NodeJS.EventEmitter) {
|
||||
ipc.on(Hello, ({ sender }) => this.onHello(sender));
|
||||
}
|
||||
|
||||
registerChannel(channelName: string, channel: IChannel): void {
|
||||
this.channels[channelName] = channel;
|
||||
}
|
||||
|
||||
private onHello(sender: any): void {
|
||||
const senderId = sender.getId();
|
||||
const onMessage = this.createScopedEvent(Message, senderId);
|
||||
const protocol = new Protocol(sender, onMessage);
|
||||
const ipcServer = new IPCServer(protocol);
|
||||
|
||||
Object.keys(this.channels)
|
||||
.forEach(name => ipcServer.registerChannel(name, this.channels[name]));
|
||||
|
||||
const onGoodbye = this.createScopedEvent(Goodbye, senderId);
|
||||
const listener = onGoodbye(() => {
|
||||
listener.dispose();
|
||||
ipcServer.dispose();
|
||||
protocol.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private createScopedEvent(eventName: string, senderId: string) {
|
||||
const onRawMessageEvent = fromEventEmitter<IIPCEvent>(this.ipc, eventName, (event, message) => ({ event, message }));
|
||||
const onScopedRawMessageEvent = filterEvent<IIPCEvent>(onRawMessageEvent, ({ event }) => event.sender.getId() === senderId);
|
||||
return mapEvent<IIPCEvent,string>(onScopedRawMessageEvent, ({ message }) => message);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.channels = null;
|
||||
}
|
||||
}
|
||||
|
||||
export class Client implements IClient, IDisposable {
|
||||
|
||||
private protocol: Protocol;
|
||||
private ipcClient: IPCClient;
|
||||
|
||||
constructor(private ipc: IPC) {
|
||||
ipc.send(Hello);
|
||||
|
||||
const receiverEvent = fromEventEmitter<string>(ipc, Message, (_, message) => message);
|
||||
this.protocol = new Protocol(ipc, receiverEvent);
|
||||
this.ipcClient = new IPCClient(this.protocol);
|
||||
}
|
||||
|
||||
getChannel<T extends IChannel>(channelName: string): T {
|
||||
return this.ipcClient.getChannel(channelName) as T;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.ipc.send(Goodbye);
|
||||
this.ipcClient = dispose(this.ipcClient);
|
||||
this.protocol = dispose(this.protocol);
|
||||
}
|
||||
}
|
|
@ -148,15 +148,17 @@ export class Server {
|
|||
}
|
||||
}
|
||||
|
||||
export class Client implements IClient {
|
||||
export class Client implements IClient, IDisposable {
|
||||
|
||||
private state: State;
|
||||
private activeRequests: Promise[];
|
||||
private bufferedRequests: IRequest[];
|
||||
private handlers: { [id: number]: IHandler; };
|
||||
private lastRequestId: number;
|
||||
|
||||
constructor(private protocol: IMessagePassingProtocol) {
|
||||
this.state = State.Uninitialized;
|
||||
this.activeRequests = [];
|
||||
this.bufferedRequests = [];
|
||||
this.handlers = Object.create(null);
|
||||
this.lastRequestId = 0;
|
||||
|
@ -179,11 +181,17 @@ export class Client implements IClient {
|
|||
}
|
||||
};
|
||||
|
||||
if (this.state === State.Uninitialized) {
|
||||
return this.bufferRequest(request);
|
||||
}
|
||||
const activeRequest = this.state === State.Uninitialized
|
||||
? this.bufferRequest(request)
|
||||
: this.doRequest(request);
|
||||
|
||||
return this.doRequest(request);
|
||||
this.activeRequests.push(activeRequest);
|
||||
|
||||
activeRequest
|
||||
.then(null, _ => null)
|
||||
.done(() => this.activeRequests = this.activeRequests.filter(i => i !== activeRequest));
|
||||
|
||||
return activeRequest;
|
||||
}
|
||||
|
||||
private doRequest(request: IRequest): Promise {
|
||||
|
@ -274,6 +282,11 @@ export class Client implements IClient {
|
|||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.activeRequests.forEach(r => r.cancel());
|
||||
this.activeRequests = [];
|
||||
}
|
||||
}
|
||||
|
||||
export function getDelayedChannel<T extends IChannel>(promise: TPromise<IChannel>): T {
|
||||
|
@ -306,12 +319,12 @@ export function eventToCall(event: Event<any>): TPromise<any> {
|
|||
);
|
||||
}
|
||||
|
||||
export function eventFromCall<T>(channel: IChannel, name: string): Event<T> {
|
||||
export function eventFromCall<T>(channel: IChannel, name: string, arg: any = null): Event<T> {
|
||||
let promise: Promise;
|
||||
|
||||
const emitter = new Emitter<any>({
|
||||
onFirstListenerAdd: () => {
|
||||
promise = channel.call(name, null).then(null, err => null, e => emitter.fire(e));
|
||||
promise = channel.call(name, arg).then(null, err => null, e => emitter.fire(e));
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
promise.cancel();
|
||||
|
|
|
@ -16,6 +16,7 @@ import { ILifecycleService, LifecycleService } from 'vs/code/electron-main/lifec
|
|||
import { VSCodeMenu } from 'vs/code/electron-main/menus';
|
||||
import { ISettingsService, SettingsManager } from 'vs/code/electron-main/settings';
|
||||
import { IUpdateService, UpdateManager } from 'vs/code/electron-main/update-manager';
|
||||
import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/common/ipc.electron';
|
||||
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { AskpassChannel } from 'vs/workbench/parts/git/common/gitIpc';
|
||||
|
@ -31,6 +32,8 @@ import { ILogService, MainLogService } from 'vs/code/electron-main/log';
|
|||
import { IStorageService, StorageService } from 'vs/code/electron-main/storage';
|
||||
import * as cp from 'child_process';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { URLChannel } from 'vs/platform/url/common/urlIpc';
|
||||
import { URLService } from 'vs/platform/url/electron-main/urlService';
|
||||
|
||||
function quit(accessor: ServicesAccessor, error?: Error);
|
||||
function quit(accessor: ServicesAccessor, message?: string);
|
||||
|
@ -52,7 +55,7 @@ function quit(accessor: ServicesAccessor, arg?: any) {
|
|||
process.exit(exitCode); // in main, process.exit === app.exit
|
||||
}
|
||||
|
||||
function main(accessor: ServicesAccessor, ipcServer: Server, userEnv: IProcessEnvironment): void {
|
||||
function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProcessEnvironment): void {
|
||||
const instantiationService = accessor.get(IInstantiationService);
|
||||
const logService = accessor.get(ILogService);
|
||||
const envService = accessor.get(IEnvironmentService);
|
||||
|
@ -93,14 +96,22 @@ function main(accessor: ServicesAccessor, ipcServer: Server, userEnv: IProcessEn
|
|||
// noop
|
||||
}
|
||||
|
||||
// Register IPC services
|
||||
// Register Main IPC services
|
||||
const launchService = instantiationService.createInstance(LaunchService);
|
||||
const launchChannel = new LaunchChannel(launchService);
|
||||
ipcServer.registerChannel('launch', launchChannel);
|
||||
mainIpcServer.registerChannel('launch', launchChannel);
|
||||
|
||||
const askpassService = new GitAskpassService();
|
||||
const askpassChannel = new AskpassChannel(askpassService);
|
||||
ipcServer.registerChannel('askpass', askpassChannel);
|
||||
mainIpcServer.registerChannel('askpass', askpassChannel);
|
||||
|
||||
// Create Electron IPC Server
|
||||
const electronIpcServer = new ElectronIPCServer(ipc);
|
||||
|
||||
// Register Electron IPC services
|
||||
const urlService = instantiationService.createInstance(URLService);
|
||||
const urlChannel = instantiationService.createInstance(URLChannel, urlService);
|
||||
electronIpcServer.registerChannel('url', urlChannel);
|
||||
|
||||
// Spawn shared process
|
||||
const sharedProcess = spawnSharedProcess({
|
||||
|
@ -120,9 +131,9 @@ function main(accessor: ServicesAccessor, ipcServer: Server, userEnv: IProcessEn
|
|||
global.programStart = envService.cliArgs.programStart;
|
||||
|
||||
function dispose() {
|
||||
if (ipcServer) {
|
||||
ipcServer.dispose();
|
||||
ipcServer = null;
|
||||
if (mainIpcServer) {
|
||||
mainIpcServer.dispose();
|
||||
mainIpcServer = null;
|
||||
}
|
||||
|
||||
sharedProcess.dispose();
|
||||
|
@ -372,6 +383,6 @@ getEnvironment().then(env => {
|
|||
|
||||
return instantiationService.invokeFunction(a => a.get(IEnvironmentService).createPaths())
|
||||
.then(() => instantiationService.invokeFunction(setupIPC))
|
||||
.then(ipcServer => instantiationService.invokeFunction(main, ipcServer, env));
|
||||
.then(mainIpcServer => instantiationService.invokeFunction(main, mainIpcServer, env));
|
||||
})
|
||||
.done(null, err => instantiationService.invokeFunction(quit, err));
|
||||
.done(null, err => instantiationService.invokeFunction(quit, err));
|
||||
|
|
|
@ -13,6 +13,7 @@ export interface IProductConfiguration {
|
|||
win32AppUserModelId: string;
|
||||
win32MutexName: string;
|
||||
darwinBundleIdentifier: string;
|
||||
urlProtocol: string;
|
||||
dataFolderName: string;
|
||||
downloadUrl: string;
|
||||
updateUrl?: string;
|
||||
|
|
17
src/vs/platform/url/common/url.ts
Normal file
17
src/vs/platform/url/common/url.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Event from 'vs/base/common/event';
|
||||
import {createDecorator} from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const ID = 'urlService';
|
||||
export const IURLService = createDecorator<IURLService>(ID);
|
||||
|
||||
export interface IURLService {
|
||||
_serviceBrand: any;
|
||||
onOpenURL: Event<string>;
|
||||
}
|
54
src/vs/platform/url/common/urlIpc.ts
Normal file
54
src/vs/platform/url/common/urlIpc.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IURLService } from './url';
|
||||
import Event, { filterEvent } from 'vs/base/common/event';
|
||||
import { IWindowsService } from 'vs/code/electron-main/windows';
|
||||
|
||||
export interface IURLChannel extends IChannel {
|
||||
call(command: 'event:onOpenURL'): TPromise<void>;
|
||||
call(command: string, arg: any): TPromise<any>;
|
||||
}
|
||||
|
||||
export class URLChannel implements IURLChannel {
|
||||
|
||||
constructor(
|
||||
private service: IURLService,
|
||||
@IWindowsService private windowsService: IWindowsService
|
||||
) { }
|
||||
|
||||
call(command: string, arg: any): TPromise<any> {
|
||||
switch (command) {
|
||||
case 'event:onOpenURL': return eventToCall(filterEvent(this.service.onOpenURL, () => this.isWindowFocused(arg)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We only want the focused window to get pinged with the onOpenUrl event.
|
||||
* The idea here is to filter the onOpenUrl event with the knowledge of which
|
||||
* was the last window to be focused. When first listening to the event,
|
||||
* each client sends its window ID via the arguments to `call(...)`.
|
||||
* When the event fires, the server has enough knowledge to filter the event
|
||||
* and fire it only to the focused window.
|
||||
*/
|
||||
private isWindowFocused(windowID: number): boolean {
|
||||
const window = this.windowsService.getFocusedWindow() || this.windowsService.getLastActiveWindow();
|
||||
return window ? window.id === windowID : false;
|
||||
}
|
||||
}
|
||||
|
||||
export class URLChannelClient implements IURLService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(private channel: IChannel, private windowID: number) { }
|
||||
|
||||
private _onOpenURL = eventFromCall<string>(this.channel, 'event:onOpenURL', this.windowID);
|
||||
get onOpenURL(): Event<string> { return this._onOpenURL; }
|
||||
}
|
30
src/vs/platform/url/electron-main/urlService.ts
Normal file
30
src/vs/platform/url/electron-main/urlService.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Event, {mapEvent} from 'vs/base/common/event';
|
||||
import {fromEventEmitter} from 'vs/base/node/event';
|
||||
import {IURLService} from 'vs/platform/url/common/url';
|
||||
import product from 'vs/platform/product';
|
||||
import {app} from 'electron';
|
||||
|
||||
export class URLService implements IURLService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
onOpenURL: Event<string>;
|
||||
|
||||
constructor() {
|
||||
const rawOnOpenUrl = fromEventEmitter(app, 'open-url', (event: Electron.Event, url: string) => ({ event, url }));
|
||||
|
||||
this.onOpenURL = mapEvent(rawOnOpenUrl, ({ event, url }) => {
|
||||
event.preventDefault();
|
||||
return url;
|
||||
});
|
||||
|
||||
app.setAsDefaultProtocolClient(product.urlProtocol);
|
||||
}
|
||||
}
|
|
@ -70,9 +70,13 @@ import {CrashReporter} from 'vs/workbench/electron-browser/crashReporter';
|
|||
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
|
||||
import {ThemeService} from 'vs/workbench/services/themes/electron-browser/themeService';
|
||||
import {getDelayedChannel} from 'vs/base/parts/ipc/common/ipc';
|
||||
import {connect} from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import {connect as connectNet} from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import {Client as ElectronIPCClient} from 'vs/base/parts/ipc/common/ipc.electron';
|
||||
import {ipcRenderer} from 'electron';
|
||||
import {IExtensionManagementChannel, ExtensionManagementChannelClient} from 'vs/platform/extensionManagement/common/extensionManagementIpc';
|
||||
import {IExtensionManagementService} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import {URLChannelClient} from 'vs/platform/url/common/urlIpc';
|
||||
import {IURLService} from 'vs/platform/url/common/url';
|
||||
import {ReloadWindowAction} from 'vs/workbench/electron-browser/actions';
|
||||
|
||||
// self registering services
|
||||
|
@ -202,7 +206,9 @@ export class WorkbenchShell {
|
|||
}
|
||||
|
||||
private initServiceCollection(): [InstantiationService, ServiceCollection] {
|
||||
const sharedProcess = connect(process.env['VSCODE_SHARED_IPC_HOOK']);
|
||||
const disposables = new Disposables();
|
||||
|
||||
const sharedProcess = connectNet(process.env['VSCODE_SHARED_IPC_HOOK']);
|
||||
sharedProcess.done(service => {
|
||||
service.onClose(() => {
|
||||
this.messageService.show(Severity.Error, {
|
||||
|
@ -212,13 +218,15 @@ export class WorkbenchShell {
|
|||
});
|
||||
}, errors.onUnexpectedError);
|
||||
|
||||
const mainProcessClient = new ElectronIPCClient(ipcRenderer);
|
||||
disposables.add(mainProcessClient);
|
||||
|
||||
const serviceCollection = new ServiceCollection();
|
||||
serviceCollection.set(IEventService, this.eventService);
|
||||
serviceCollection.set(IWorkspaceContextService, this.contextService);
|
||||
serviceCollection.set(IConfigurationService, this.configurationService);
|
||||
|
||||
const instantiationService = new InstantiationService(serviceCollection, true);
|
||||
const disposables = new Disposables();
|
||||
|
||||
this.windowService = instantiationService.createInstance(WindowService);
|
||||
serviceCollection.set(IWindowService, this.windowService);
|
||||
|
@ -311,9 +319,13 @@ export class WorkbenchShell {
|
|||
serviceCollection.set(ICodeEditorService, codeEditorService);
|
||||
|
||||
const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
|
||||
const extensionManagementChannelClient = instantiationService.createInstance(ExtensionManagementChannelClient, extensionManagementChannel);
|
||||
const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
|
||||
serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);
|
||||
|
||||
const urlChannel = mainProcessClient.getChannel('url');
|
||||
const urlChannelClient = new URLChannelClient(urlChannel, this.windowService.getWindowId());
|
||||
serviceCollection.set(IURLService, urlChannelClient);
|
||||
|
||||
return [instantiationService, serviceCollection];
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common
|
|||
import { IActivityService, ProgressBadge, NumberBadge } from 'vs/workbench/services/activity/common/activityService';
|
||||
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
|
||||
import { ipcRenderer as ipc } from 'electron';
|
||||
import { IURLService } from 'vs/platform/url/common/url';
|
||||
|
||||
interface IInstallExtensionsRequest {
|
||||
extensionsToInstall: string[];
|
||||
|
@ -31,7 +32,8 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution {
|
|||
@IMessageService private messageService: IMessageService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@IExtensionTipsService extenstionTips: IExtensionTipsService, // this is to eagerly start the service
|
||||
@IExtensionGalleryService galleryService: IExtensionGalleryService
|
||||
@IExtensionGalleryService galleryService: IExtensionGalleryService,
|
||||
@IURLService urlService: IURLService
|
||||
) {
|
||||
this.registerListeners();
|
||||
|
||||
|
@ -40,6 +42,9 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution {
|
|||
if (options.extensionsToInstall && options.extensionsToInstall.length) {
|
||||
this.install(options.extensionsToInstall).done(null, onUnexpectedError);
|
||||
}
|
||||
|
||||
urlService.onOpenURL(url => console.log(url));
|
||||
|
||||
//actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(InstallExtensionAction, InstallExtensionAction.ID, InstallExtensionAction.LABEL), 'Extensions: Install Extension', ExtensionsLabel);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue