diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index 3e6ce1e6ddac065080bb041d0a9dfdfb67e58212..989da8796445737654f7febbc5803c27d6e9d60f 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -212,29 +212,21 @@ export class SharedProcess extends Disposable implements ISharedProcess { return connectMessagePort(window); } - toggle(): void { - if (!this.window || this.window.isVisible()) { - this.hide(); - } else { - this.show(); - } - } - - show(): void { - if (!this.window) { - return; // possibly too early before created - } + async toggle(): Promise { - this.window.show(); - this.window.webContents.openDevTools(); - } + // wait for window to be created + await this.whenIpcReady; - hide(): void { if (!this.window) { - return; // possibly too early before created + return; // possibly disposed already } - this.window.webContents.closeDevTools(); - this.window.hide(); + if (this.window.isVisible()) { + this.window.webContents.closeDevTools(); + this.window.hide(); + } else { + this.window.show(); + this.window.webContents.openDevTools(); + } } } diff --git a/src/vs/platform/ipc/electron-browser/sharedProcessService.ts b/src/vs/platform/ipc/electron-browser/sharedProcessService.ts index 3cfe94145dff9dbf522546fa5f03aa06f62cbaf9..60299f96efb83711215e72357ac99d5391eb782a 100644 --- a/src/vs/platform/ipc/electron-browser/sharedProcessService.ts +++ b/src/vs/platform/ipc/electron-browser/sharedProcessService.ts @@ -4,7 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; +import { Event } from 'vs/base/common/event'; +import { IpcRendererEvent } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { Client as MessagePortClient } from 'vs/base/parts/ipc/common/ipc.mp'; +import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; +import { generateUuid } from 'vs/base/common/uuid'; +import { ILogService } from 'vs/platform/log/common/log'; +import { Disposable } from 'vs/base/common/lifecycle'; export const ISharedProcessService = createDecorator('sharedProcessService'); @@ -15,3 +23,46 @@ export interface ISharedProcessService { getChannel(channelName: string): IChannel; registerChannel(channelName: string, channel: IServerChannel): void; } + +export class SharedProcessService extends Disposable implements ISharedProcessService { + + declare readonly _serviceBrand: undefined; + + private readonly withSharedProcessConnection: Promise; + + constructor( + @INativeHostService private readonly nativeHostService: INativeHostService, + @ILogService private readonly logService: ILogService + ) { + super(); + + this.withSharedProcessConnection = this.connect(); + } + + private async connect(): Promise { + this.logService.trace('Renderer->SharedProcess#connect'); + + // Ask to create message channel inside the window + // and send over a UUID to correlate the response + const nonce = generateUuid(); + ipcRenderer.send('vscode:createSharedProcessMessageChannel', nonce); + + // Wait until the main side has returned the `MessagePort` + // We need to filter by the `nonce` to ensure we listen + // to the right response. + const onMessageChannelResult = Event.fromNodeEventEmitter<{ nonce: string, port: MessagePort }>(ipcRenderer, 'vscode:createSharedProcessMessageChannelResult', (e: IpcRendererEvent, nonce: string) => ({ nonce, port: e.ports[0] })); + const { port } = await Event.toPromise(Event.once(Event.filter(onMessageChannelResult, e => e.nonce === nonce))); + + this.logService.trace('Renderer->SharedProcess#connect: connection established'); + + return this._register(new MessagePortClient(port, `window:${this.nativeHostService.windowId}`)); + } + + getChannel(channelName: string): IChannel { + return getDelayedChannel(this.withSharedProcessConnection.then(connection => connection.getChannel(channelName))); + } + + registerChannel(channelName: string, channel: IServerChannel): void { + this.withSharedProcessConnection.then(connection => connection.registerChannel(channelName, channel)); + } +} diff --git a/src/vs/platform/sharedProcess/node/sharedProcess.ts b/src/vs/platform/sharedProcess/node/sharedProcess.ts index f68bc60cb5f4c43055db466a42b6d6be4754d0fc..8a0ea62d76bf235b6791fa9c2756ac026594375d 100644 --- a/src/vs/platform/sharedProcess/node/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/node/sharedProcess.ts @@ -12,7 +12,7 @@ export interface ISharedProcess { * Toggles the visibility of the otherwise hidden * shared process window. */ - toggle(): void; + toggle(): Promise; } export interface ISharedProcessConfiguration { diff --git a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts b/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts deleted file mode 100644 index 924ca70d083c271e1fdbf00114f206ac007a6cca..0000000000000000000000000000000000000000 --- a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; -import { IpcRendererEvent } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes'; -import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; -import { Client as MessagePortClient } from 'vs/base/parts/ipc/common/ipc.mp'; -import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; -import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; -import { generateUuid } from 'vs/base/common/uuid'; -import { ILogService } from 'vs/platform/log/common/log'; -import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { Disposable } from 'vs/base/common/lifecycle'; - -export class SharedProcessService extends Disposable implements ISharedProcessService { - - declare readonly _serviceBrand: undefined; - - private readonly withSharedProcessConnection: Promise; - - constructor( - @INativeHostService private readonly nativeHostService: INativeHostService, - @ILogService private readonly logService: ILogService, - @ILifecycleService private readonly lifecycleService: ILifecycleService - ) { - super(); - - this.withSharedProcessConnection = this.connect(); - - this.registerListeners(); - } - - private registerListeners(): void { - - // Lifecycle - this.lifecycleService.onWillShutdown(() => this.dispose()); - } - - private async connect(): Promise { - this.logService.trace('Workbench->SharedProcess#connect'); - - // Ask to create message channel inside the window - // and send over a UUID to correlate the response - const nonce = generateUuid(); - ipcRenderer.send('vscode:createSharedProcessMessageChannel', nonce); - - // Wait until the main side has returned the `MessagePort` - // We need to filter by the `nonce` to ensure we listen - // to the right response. - const onMessageChannelResult = Event.fromNodeEventEmitter<{ nonce: string, port: MessagePort }>(ipcRenderer, 'vscode:createSharedProcessMessageChannelResult', (e: IpcRendererEvent, nonce: string) => ({ nonce, port: e.ports[0] })); - const { port } = await Event.toPromise(Event.once(Event.filter(onMessageChannelResult, e => e.nonce === nonce))); - - this.logService.trace('Workbench->SharedProcess#connect: connection established'); - - return this._register(new MessagePortClient(port, `window:${this.nativeHostService.windowId}`)); - } - - getChannel(channelName: string): IChannel { - return getDelayedChannel(this.withSharedProcessConnection.then(connection => connection.getChannel(channelName))); - } - - registerChannel(channelName: string, channel: IServerChannel): void { - this.withSharedProcessConnection.then(connection => connection.registerChannel(channelName, channel)); - } -} - -registerSingleton(ISharedProcessService, SharedProcessService, true); diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index 2daa6c23831a3f5bec1eaa147d02c9e7de7c6183..abb042ce897509fd04b7111ba9e4b726344febfc 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -71,7 +71,6 @@ import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncService' import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncAccountService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncStoreManagementService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataAutoSyncService'; -import 'vs/workbench/services/sharedProcess/electron-browser/sharedProcessService'; import 'vs/workbench/services/localizations/electron-browser/localizationsService'; import 'vs/workbench/services/diagnostics/electron-browser/diagnosticsService'; @@ -90,8 +89,10 @@ import 'vs/workbench/services/diagnostics/electron-browser/diagnosticsService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { TunnelService } from 'vs/workbench/services/remote/electron-browser/tunnelServiceImpl'; +import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; registerSingleton(ITunnelService, TunnelService); +registerSingleton(ISharedProcessService, SharedProcessService, true); //#endregion