mirror of
https://github.com/Microsoft/vscode
synced 2024-09-18 01:58:27 +00:00
Improve env variable handling around extension host connection type (#152466)
This commit is contained in:
parent
0f05ed4758
commit
47652af0b6
|
@ -22,6 +22,7 @@ import { logRemoteEntry } from 'vs/workbench/services/extensions/common/remoteCo
|
||||||
import { removeDangerousEnvVariables } from 'vs/base/common/processes';
|
import { removeDangerousEnvVariables } from 'vs/base/common/processes';
|
||||||
import { IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService';
|
import { IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService';
|
||||||
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { IPCExtHostConnection, writeExtHostConnection, SocketExtHostConnection } from 'vs/workbench/services/extensions/common/extensionHostEnv';
|
||||||
|
|
||||||
export async function buildUserEnvironment(startParamsEnv: { [key: string]: string | null } = {}, withUserShellEnvironment: boolean, language: string, isDebug: boolean, environmentService: IServerEnvironmentService, logService: ILogService): Promise<IProcessEnvironment> {
|
export async function buildUserEnvironment(startParamsEnv: { [key: string]: string | null } = {}, withUserShellEnvironment: boolean, language: string, isDebug: boolean, environmentService: IServerEnvironmentService, logService: ILogService): Promise<IProcessEnvironment> {
|
||||||
const nlsConfig = await getNLSConfiguration(language, environmentService.userDataPath);
|
const nlsConfig = await getNLSConfiguration(language, environmentService.userDataPath);
|
||||||
|
@ -244,11 +245,11 @@ export class ExtensionHostConnection {
|
||||||
let extHostNamedPipeServer: net.Server | null;
|
let extHostNamedPipeServer: net.Server | null;
|
||||||
|
|
||||||
if (this._canSendSocket) {
|
if (this._canSendSocket) {
|
||||||
env['VSCODE_EXTHOST_WILL_SEND_SOCKET'] = 'true';
|
writeExtHostConnection(new SocketExtHostConnection(), env);
|
||||||
extHostNamedPipeServer = null;
|
extHostNamedPipeServer = null;
|
||||||
} else {
|
} else {
|
||||||
const { namedPipeServer, pipeName } = await this._listenOnPipe();
|
const { namedPipeServer, pipeName } = await this._listenOnPipe();
|
||||||
env['VSCODE_IPC_HOOK_EXTHOST'] = pipeName;
|
writeExtHostConnection(new IPCExtHostConnection(pipeName), env);
|
||||||
extHostNamedPipeServer = namedPipeServer;
|
extHostNamedPipeServer = namedPipeServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { ProcessTimeRunOnceScheduler } from 'vs/base/common/async';
|
||||||
import { boolean } from 'vs/editor/common/config/editorOptions';
|
import { boolean } from 'vs/editor/common/config/editorOptions';
|
||||||
import { createURITransformer } from 'vs/workbench/api/node/uriTransformer';
|
import { createURITransformer } from 'vs/workbench/api/node/uriTransformer';
|
||||||
import { MessagePortMain } from 'electron';
|
import { MessagePortMain } from 'electron';
|
||||||
|
import { ExtHostConnectionType, readExtHostConnection } from 'vs/workbench/services/extensions/common/extensionHostEnv';
|
||||||
|
|
||||||
import 'vs/workbench/api/common/extHost.common.services';
|
import 'vs/workbench/api/common/extHost.common.services';
|
||||||
import 'vs/workbench/api/node/extHost.node.services';
|
import 'vs/workbench/api/node/extHost.node.services';
|
||||||
|
@ -110,7 +111,9 @@ let onTerminate = function (reason: string) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||||
if (process.env.VSCODE_WILL_SEND_MESSAGE_PORT) {
|
const extHostConnection = readExtHostConnection(process.env);
|
||||||
|
|
||||||
|
if (extHostConnection.type === ExtHostConnectionType.MessagePort) {
|
||||||
|
|
||||||
return new Promise<IMessagePassingProtocol>((resolve, reject) => {
|
return new Promise<IMessagePassingProtocol>((resolve, reject) => {
|
||||||
|
|
||||||
|
@ -139,7 +142,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (process.env.VSCODE_EXTHOST_WILL_SEND_SOCKET) {
|
} else if (extHostConnection.type === ExtHostConnectionType.Socket) {
|
||||||
|
|
||||||
return new Promise<PersistentProtocol>((resolve, reject) => {
|
return new Promise<PersistentProtocol>((resolve, reject) => {
|
||||||
|
|
||||||
|
@ -208,7 +211,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const pipeName = process.env.VSCODE_IPC_HOOK_EXTHOST!;
|
const pipeName = extHostConnection.pipeName;
|
||||||
|
|
||||||
return new Promise<PersistentProtocol>((resolve, reject) => {
|
return new Promise<PersistentProtocol>((resolve, reject) => {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||||
|
|
||||||
|
export const enum ExtHostConnectionType {
|
||||||
|
IPC = 1,
|
||||||
|
Socket = 2,
|
||||||
|
MessagePort = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extension host will connect via named pipe / domain socket to its renderer.
|
||||||
|
*/
|
||||||
|
export class IPCExtHostConnection {
|
||||||
|
public static ENV_KEY = 'VSCODE_EXTHOST_IPC_HOOK';
|
||||||
|
|
||||||
|
public readonly type = ExtHostConnectionType.IPC;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly pipeName: string
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public serialize(env: IProcessEnvironment): void {
|
||||||
|
env[IPCExtHostConnection.ENV_KEY] = this.pipeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extension host will receive via nodejs IPC the socket to its renderer.
|
||||||
|
*/
|
||||||
|
export class SocketExtHostConnection {
|
||||||
|
public static ENV_KEY = 'VSCODE_EXTHOST_WILL_SEND_SOCKET';
|
||||||
|
|
||||||
|
public readonly type = ExtHostConnectionType.Socket;
|
||||||
|
|
||||||
|
public serialize(env: IProcessEnvironment): void {
|
||||||
|
env[SocketExtHostConnection.ENV_KEY] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extension host will receive via nodejs IPC the MessagePort to its renderer.
|
||||||
|
*/
|
||||||
|
export class MessagePortExtHostConnection {
|
||||||
|
public static ENV_KEY = 'VSCODE_WILL_SEND_MESSAGE_PORT';
|
||||||
|
|
||||||
|
public readonly type = ExtHostConnectionType.MessagePort;
|
||||||
|
|
||||||
|
public serialize(env: IProcessEnvironment): void {
|
||||||
|
env[MessagePortExtHostConnection.ENV_KEY] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExtHostConnection = IPCExtHostConnection | SocketExtHostConnection | MessagePortExtHostConnection;
|
||||||
|
|
||||||
|
function clean(env: IProcessEnvironment): void {
|
||||||
|
delete env[IPCExtHostConnection.ENV_KEY];
|
||||||
|
delete env[SocketExtHostConnection.ENV_KEY];
|
||||||
|
delete env[MessagePortExtHostConnection.ENV_KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write `connection` into `env` and clean up `env`.
|
||||||
|
*/
|
||||||
|
export function writeExtHostConnection(connection: ExtHostConnection, env: IProcessEnvironment): void {
|
||||||
|
// Avoid having two different keys that might introduce amiguity or problems.
|
||||||
|
clean(env);
|
||||||
|
connection.serialize(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read `connection` from `env` and clean up `env`.
|
||||||
|
*/
|
||||||
|
export function readExtHostConnection(env: IProcessEnvironment): ExtHostConnection {
|
||||||
|
if (env[IPCExtHostConnection.ENV_KEY]) {
|
||||||
|
return cleanAndReturn(env, new IPCExtHostConnection(env[IPCExtHostConnection.ENV_KEY]!));
|
||||||
|
}
|
||||||
|
if (env[SocketExtHostConnection.ENV_KEY]) {
|
||||||
|
return cleanAndReturn(env, new SocketExtHostConnection());
|
||||||
|
}
|
||||||
|
if (env[MessagePortExtHostConnection.ENV_KEY]) {
|
||||||
|
return cleanAndReturn(env, new MessagePortExtHostConnection());
|
||||||
|
}
|
||||||
|
throw new Error(`No connection information defined in environment!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanAndReturn(env: IProcessEnvironment, result: ExtHostConnection): ExtHostConnection {
|
||||||
|
clean(env);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net';
|
||||||
import { createRandomIPCHandle, NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
import { createRandomIPCHandle, NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||||
import { IExtensionHostProcessOptions } from 'vs/platform/extensions/common/extensionHostStarter';
|
import { IExtensionHostProcessOptions } from 'vs/platform/extensions/common/extensionHostStarter';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
|
import { IPCExtHostConnection, writeExtHostConnection } from 'vs/workbench/services/extensions/common/extensionHostEnv';
|
||||||
import { createMessageOfType, MessageType } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
import { createMessageOfType, MessageType } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||||
import { ExtensionHostProcess, ExtHostMessagePortCommunication, IExtHostCommunication, SandboxLocalProcessExtensionHost } from 'vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost';
|
import { ExtensionHostProcess, ExtHostMessagePortCommunication, IExtHostCommunication, SandboxLocalProcessExtensionHost } from 'vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost';
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ class ExtHostNamedPipeCommunication extends Disposable implements IExtHostCommun
|
||||||
establishProtocol(prepared: INamedPipePreparedData, extensionHostProcess: ExtensionHostProcess, opts: IExtensionHostProcessOptions): Promise<IMessagePassingProtocol> {
|
establishProtocol(prepared: INamedPipePreparedData, extensionHostProcess: ExtensionHostProcess, opts: IExtensionHostProcessOptions): Promise<IMessagePassingProtocol> {
|
||||||
const { namedPipeServer, pipeName } = prepared;
|
const { namedPipeServer, pipeName } = prepared;
|
||||||
|
|
||||||
opts.env['VSCODE_IPC_HOOK_EXTHOST'] = pipeName;
|
writeExtHostConnection(new IPCExtHostConnection(pipeName), opts.env);
|
||||||
|
|
||||||
return new Promise<PersistentProtocol>((resolve, reject) => {
|
return new Promise<PersistentProtocol>((resolve, reject) => {
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/use
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { acquirePort } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp';
|
import { acquirePort } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { MessagePortExtHostConnection, writeExtHostConnection } from 'vs/workbench/services/extensions/common/extensionHostEnv';
|
||||||
|
|
||||||
export interface ILocalProcessExtensionHostInitData {
|
export interface ILocalProcessExtensionHostInitData {
|
||||||
readonly autoStart: boolean;
|
readonly autoStart: boolean;
|
||||||
|
@ -620,7 +621,7 @@ export class ExtHostMessagePortCommunication extends Disposable implements IExtH
|
||||||
|
|
||||||
establishProtocol(prepared: void, extensionHostProcess: ExtensionHostProcess, opts: IExtensionHostProcessOptions): Promise<IMessagePassingProtocol> {
|
establishProtocol(prepared: void, extensionHostProcess: ExtensionHostProcess, opts: IExtensionHostProcessOptions): Promise<IMessagePassingProtocol> {
|
||||||
|
|
||||||
opts.env['VSCODE_WILL_SEND_MESSAGE_PORT'] = 'true';
|
writeExtHostConnection(new MessagePortExtHostConnection(), opts.env);
|
||||||
|
|
||||||
// Get ready to acquire the message port from the shared process worker
|
// Get ready to acquire the message port from the shared process worker
|
||||||
const portPromise = acquirePort(undefined /* we trigger the request via service call! */, opts.responseChannel, opts.responseNonce);
|
const portPromise = acquirePort(undefined /* we trigger the request via service call! */, opts.responseChannel, opts.responseNonce);
|
||||||
|
|
Loading…
Reference in a new issue