Skip to content

Commit 3b26dc1

Browse files
committed
Connect message port from window to pty host
1 parent 7993982 commit 3b26dc1

File tree

6 files changed

+66
-3
lines changed

6 files changed

+66
-3
lines changed

src/vs/platform/terminal/common/terminal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ export enum TerminalIpcChannels {
207207
* Communicates between the shared process and the pty host process.
208208
*/
209209
PtyHost = 'ptyHost',
210+
211+
PtyHostWindow = 'ptyHostWindow',
210212
/**
211213
* Deals with logging from the pty host process.
212214
*/

src/vs/platform/terminal/electron-main/electronPtyHostStarter.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { IReconnectConstants } from 'vs/platform/terminal/common/terminal';
1212
import { IPtyHostConnection, IPtyHostStarter } from 'vs/platform/terminal/node/ptyHost';
1313
import { UtilityProcess } from 'vs/platform/utilityProcess/electron-main/utilityProcess';
1414
import { Client as MessagePortClient } from 'vs/base/parts/ipc/electron-main/ipc.mp';
15+
import { MessageChannelMain, MessagePortMain } from 'electron';
16+
import { assertIsDefined } from 'vs/base/common/types';
1517

1618
export class ElectronPtyHostStarter implements IPtyHostStarter {
1719

@@ -51,6 +53,8 @@ export class ElectronPtyHostStarter implements IPtyHostStarter {
5153

5254
return {
5355
client,
56+
port,
57+
connect: () => assertIsDefined(this.utilityProcess).connect(),
5458
dispose: client.dispose,
5559
onDidProcessExit: this.utilityProcess.onExit
5660
};

src/vs/platform/terminal/node/ptyHost.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { IChannelClient } from 'vs/base/parts/ipc/common/ipc';
99

1010
export interface IPtyHostConnection extends IDisposable {
1111
readonly client: IChannelClient;
12+
// TODO: Type
13+
readonly port?: any;
14+
connect?(): any;
1215
readonly onDidProcessExit: Event<{ code: number; signal: string }>;
1316
}
1417

src/vs/platform/terminal/node/ptyHostMain.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import { HeartbeatService } from 'vs/platform/terminal/node/heartbeatService';
2121
import { PtyService } from 'vs/platform/terminal/node/ptyService';
2222
import { isUtilityProcess } from 'vs/base/parts/sandbox/node/electronTypes';
2323

24+
const _isUtilityProcess = isUtilityProcess(process);
25+
2426
let server: ChildProcessServer<string> | UtilityProcessServer;
25-
if (isUtilityProcess(process)) {
27+
if (_isUtilityProcess) {
2628
server = new UtilityProcessServer();
2729
} else {
2830
server = new ChildProcessServer(TerminalIpcChannels.PtyHost);
@@ -53,7 +55,11 @@ delete process.env.VSCODE_RECONNECT_SHORT_GRACE_TIME;
5355
delete process.env.VSCODE_RECONNECT_SCROLLBACK;
5456

5557
const ptyService = new PtyService(lastPtyId, logService, productService, reconnectConstants);
56-
server.registerChannel(TerminalIpcChannels.PtyHost, ProxyChannel.fromService(ptyService));
58+
const ptyServiceChannel = ProxyChannel.fromService(ptyService);
59+
server.registerChannel(TerminalIpcChannels.PtyHost, ptyServiceChannel);
60+
if (_isUtilityProcess) {
61+
server.registerChannel(TerminalIpcChannels.PtyHostWindow, ptyServiceChannel);
62+
}
5763

5864
process.once('exit', () => {
5965
logService.dispose();

src/vs/platform/terminal/node/ptyHostService.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { IpcMainEvent, MessagePortMain } from 'electron';
67
import { Emitter, Event } from 'vs/base/common/event';
78
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
89
import { IProcessEnvironment, OperatingSystem, isWindows } from 'vs/base/common/platform';
910
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
11+
import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain';
1012
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1113
import { ILogService, ILoggerService } from 'vs/platform/log/common/log';
1214
import { RemoteLoggerChannelClient } from 'vs/platform/log/common/logIpc';
@@ -94,6 +96,11 @@ export class PtyHostService extends Disposable implements IPtyService {
9496
this._resolveVariablesRequestStore = this._register(new RequestStore(undefined, this._logService));
9597
this._resolveVariablesRequestStore.onCreateRequest(this._onPtyHostRequestResolveVariables.fire, this._onPtyHostRequestResolveVariables);
9698

99+
validatedIpcMain.on('vscode:createPtyHostMessageChannel', (e, nonce) => this._onWindowConnection(e, nonce));
100+
101+
// TODO: Start on demand on first window connection (see SharedProcess.onWindowConnection
102+
// TODO: Make direct message port connection to each window when requested
103+
97104
this._startPtyHost().then(value => {
98105
this._connection = value[0];
99106
this._proxy = value[1];
@@ -107,6 +114,22 @@ export class PtyHostService extends Disposable implements IPtyService {
107114
});
108115
}
109116

117+
private _onWindowConnection(e: IpcMainEvent, nonce: string) {
118+
const port = this._connection.connect!() as MessagePortMain;
119+
120+
121+
// Check back if the requesting window meanwhile closed
122+
// Since shared process is delayed on startup there is
123+
// a chance that the window close before the shared process
124+
// was ready for a connection.
125+
126+
if (e.sender.isDestroyed()) {
127+
return port.close();
128+
}
129+
130+
e.sender.postMessage('vscode:createPtyHostMessageChannelResult', nonce, [port]);
131+
}
132+
110133
private get _ignoreProcessNames(): string[] {
111134
return this._configurationService.getValue<string[]>(TerminalSettingId.IgnoreProcessNames);
112135
}

src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log';
1414
import { INotificationService } from 'vs/platform/notification/common/notification';
1515
import { Registry } from 'vs/platform/registry/common/platform';
1616
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
17-
import { ILocalPtyService, IProcessPropertyMap, IShellLaunchConfig, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal';
17+
import { ILocalPtyService, IProcessPropertyMap, IPtyService, IShellLaunchConfig, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalIpcChannels, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal';
1818
import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
1919
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
2020
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
@@ -30,6 +30,10 @@ import { IProductService } from 'vs/platform/product/common/productService';
3030
import { IEnvironmentVariableService } from 'vs/workbench/contrib/terminal/common/environmentVariable';
3131
import { BaseTerminalBackend } from 'vs/workbench/contrib/terminal/browser/baseTerminalBackend';
3232
import { getWorkspaceForTerminal } from 'vs/workbench/services/configurationResolver/common/terminalResolver';
33+
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
34+
import { Client as MessagePortClient } from 'vs/base/parts/ipc/common/ipc.mp';
35+
import { acquirePort } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp';
36+
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
3337

3438
export class LocalTerminalBackendContribution implements IWorkbenchContribution {
3539
constructor(
@@ -66,9 +70,30 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
6670
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
6771
@INotificationService notificationService: INotificationService,
6872
@IHistoryService historyService: IHistoryService,
73+
@INativeWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService
6974
) {
7075
super(_localPtyService, logService, notificationService, historyService, _configurationResolverService, workspaceContextService);
7176

77+
78+
79+
80+
(async () => {
81+
// mark('code/willConnectSharedProcess');
82+
// this.logService.trace('Renderer->SharedProcess#connect: before acquirePort');
83+
const port = await acquirePort('vscode:createPtyHostMessageChannel', 'vscode:createPtyHostMessageChannelResult');
84+
// mark('code/didConnectSharedProcess');
85+
// this.logService.trace('Renderer->SharedProcess#connect: connection established');
86+
87+
const client = new MessagePortClient(port, `window:${environmentService.window.id}`);
88+
const proxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHostWindow));
89+
90+
logService.info('latency: ', proxy.getLatency(0));
91+
proxy.onProcessData(e => {
92+
logService.info('message port process data: ' + e.event);
93+
});
94+
})();
95+
96+
7297
// Attach process listeners
7398
this._localPtyService.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event));
7499
this._localPtyService.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.property));

0 commit comments

Comments
 (0)