wip: url service
This commit is contained in:
parent
dccf029ef6
commit
fe33ef722a
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Server as IPCServer, Client as IPCClient, IServer, IClient, IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
|
@ -12,24 +11,26 @@ const Hello = 'ipc:hello';
|
|||
const Goodbye = 'ipc:goodbye';
|
||||
const Message = 'ipc:message';
|
||||
|
||||
export interface IPC extends NodeJS.EventEmitter {
|
||||
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 ipc: IPC) {}
|
||||
constructor(private sender: Sender, private receiver: NodeJS.EventEmitter) {}
|
||||
|
||||
send(message: any): void {
|
||||
this.ipc.send(Message, message);
|
||||
this.sender.send(Message, message);
|
||||
}
|
||||
|
||||
onMessage(callback: (message: any) => void): void {
|
||||
const cb = (_, m) => callback(m);
|
||||
this.ipc.on(Message, cb);
|
||||
this.listener = toDisposable(() => this.ipc.removeListener(Message, cb));
|
||||
this.receiver.on(Message, cb);
|
||||
this.listener = toDisposable(() => this.receiver.removeListener(Message, cb));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
@ -41,11 +42,11 @@ export class Server implements IServer, IDisposable {
|
|||
|
||||
private channels: { [name: string]: IChannel };
|
||||
|
||||
constructor(ipc: IPC) {
|
||||
constructor(ipc: NodeJS.EventEmitter) {
|
||||
this.channels = Object.create(null);
|
||||
|
||||
ipc.on(Hello, ({ sender }) => {
|
||||
const protocol = new Protocol(sender);
|
||||
const protocol = new Protocol(sender, ipc);
|
||||
const ipcServer = new IPCServer(protocol);
|
||||
|
||||
Object.keys(this.channels)
|
||||
|
@ -55,8 +56,6 @@ export class Server implements IServer, IDisposable {
|
|||
ipcServer.dispose();
|
||||
protocol.dispose();
|
||||
});
|
||||
|
||||
sender.send(Hello);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -75,7 +74,8 @@ export class Client implements IClient, IDisposable {
|
|||
private ipcClient: IPCClient;
|
||||
|
||||
constructor(private ipc: IPC) {
|
||||
this.protocol = new Protocol(ipc);
|
||||
ipc.send(Hello);
|
||||
this.protocol = new Protocol(ipc, ipc);
|
||||
this.ipcClient = new IPCClient(this.protocol);
|
||||
}
|
||||
|
||||
|
@ -87,16 +87,4 @@ export class Client implements IClient, IDisposable {
|
|||
this.ipc.send(Goodbye);
|
||||
this.protocol = dispose(this.protocol);
|
||||
}
|
||||
}
|
||||
|
||||
export function connect(ipc: IPC): TPromise<Client> {
|
||||
return new TPromise<Client>((c, e) => {
|
||||
ipc.once(Hello, () => {
|
||||
ipc.removeListener('error', e);
|
||||
c(new Client(ipc));
|
||||
});
|
||||
|
||||
ipc.once('error', e);
|
||||
ipc.send(Hello);
|
||||
});
|
||||
}
|
|
@ -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 = new URLChannel(urlService);
|
||||
electronIpcServer.registerChannel('url', urlChannel);
|
||||
|
||||
// Used by sub processes to communicate back to the main instance
|
||||
process.env['VSCODE_PID'] = '' + process.pid;
|
||||
|
@ -125,9 +136,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();
|
||||
|
@ -144,12 +155,6 @@ function main(accessor: ServicesAccessor, ipcServer: Server, userEnv: IProcessEn
|
|||
dispose();
|
||||
});
|
||||
|
||||
app.setAsDefaultProtocolClient('vscode');
|
||||
|
||||
app.on('open-url', url => {
|
||||
console.log(url);
|
||||
});
|
||||
|
||||
// Dispose on vscode:exit
|
||||
ipc.on('vscode:exit', (event, code: number) => {
|
||||
logService.log('IPC#vscode:exit', code);
|
||||
|
@ -356,6 +361,6 @@ getUserEnvironment()
|
|||
|
||||
return instantiationService.invokeFunction(a => a.get(IEnvironmentService).createPaths())
|
||||
.then(() => instantiationService.invokeFunction(setupIPC))
|
||||
.then(ipcServer => instantiationService.invokeFunction(main, ipcServer, userEnv));
|
||||
.then(mainIpcServer => instantiationService.invokeFunction(main, mainIpcServer, userEnv));
|
||||
})
|
||||
.done(null, err => instantiationService.invokeFunction(quit, err));
|
|
@ -12,5 +12,6 @@ export const ID = 'urlService';
|
|||
export const IURLService = createDecorator<IURLService>(ID);
|
||||
|
||||
export interface IURLService {
|
||||
onOpenUrl: Event<string>;
|
||||
_serviceBrand: any;
|
||||
onOpenURL: Event<string>;
|
||||
}
|
||||
|
|
|
@ -3,4 +3,35 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
'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 from 'vs/base/common/event';
|
||||
|
||||
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) { }
|
||||
|
||||
call(command: string, arg: any): TPromise<any> {
|
||||
switch (command) {
|
||||
case 'event:onOpenURL': return eventToCall(this.service.onOpenURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class URLChannelClient implements IURLService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(private channel: IChannel) { }
|
||||
|
||||
private _onOpenURL = eventFromCall<string>(this.channel, 'event:onOpenURL');
|
||||
get onOpenURL(): Event<string> { return this._onOpenURL; }
|
||||
}
|
36
src/vs/platform/url/electron-main/urlService.ts
Normal file
36
src/vs/platform/url/electron-main/urlService.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 {IDisposable, dispose, toDisposable} from 'vs/base/common/lifecycle';
|
||||
import {IURLService} from 'vs/platform/url/common/url';
|
||||
import {app} from 'electron';
|
||||
|
||||
export class URLService implements IURLService, IDisposable {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private _onOpenURL = new Emitter<string>();
|
||||
onOpenURL: Event<string> = this._onOpenURL.event;
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor() {
|
||||
const handler = (e: Electron.Event, url: string) => {
|
||||
e.preventDefault();
|
||||
this._onOpenURL.fire(url);
|
||||
};
|
||||
|
||||
app.on('open-url', handler);
|
||||
this.disposables.push(toDisposable(() => app.removeListener('open-url', handler)));
|
||||
|
||||
// app.setAsDefaultProtocolClient('vscode');
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 {IURLService} from 'vs/platform/url/common/url';
|
||||
|
||||
export class URLService implements IURLService {
|
||||
|
||||
private _onOpenUrl = new Emitter<string>();
|
||||
onOpenUrl: Event<string> = this._onOpenUrl.event;
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
|
@ -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,7 @@ export class WorkbenchShell {
|
|||
}
|
||||
|
||||
private initServiceCollection(): [InstantiationService, ServiceCollection] {
|
||||
const sharedProcess = connect(process.env['VSCODE_SHARED_IPC_HOOK']);
|
||||
const sharedProcess = connectNet(process.env['VSCODE_SHARED_IPC_HOOK']);
|
||||
sharedProcess.done(service => {
|
||||
service.onClose(() => {
|
||||
this.messageService.show(Severity.Error, {
|
||||
|
@ -212,6 +216,8 @@ export class WorkbenchShell {
|
|||
});
|
||||
}, errors.onUnexpectedError);
|
||||
|
||||
const mainProcessClient = new ElectronIPCClient(ipcRenderer);
|
||||
|
||||
const serviceCollection = new ServiceCollection();
|
||||
serviceCollection.set(IEventService, this.eventService);
|
||||
serviceCollection.set(IWorkspaceContextService, this.contextService);
|
||||
|
@ -314,6 +320,10 @@ export class WorkbenchShell {
|
|||
const extensionManagementChannelClient = instantiationService.createInstance(ExtensionManagementChannelClient, extensionManagementChannel);
|
||||
serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);
|
||||
|
||||
const urlChannel = mainProcessClient.getChannel('url');
|
||||
const urlChannelClient = instantiationService.createInstance(URLChannelClient, urlChannel);
|
||||
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