mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 02:28:34 +01:00
Start CLIServer with extension host
This commit is contained in:
@@ -65,6 +65,7 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/n
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -113,7 +114,7 @@ export function createApiFactory(
|
||||
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures));
|
||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService, extHostCommands));
|
||||
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService));
|
||||
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService, extHostCommands));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
@@ -124,6 +125,10 @@ export function createApiFactory(
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(initData.logsLocation, rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
if (initData.remoteAuthority) {
|
||||
const cliServer = new CLIServer(extHostCommands);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
}
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => (<any>ExtHostContext)[key]);
|
||||
|
||||
101
src/vs/workbench/api/node/extHostCLIServer.ts
Normal file
101
src/vs/workbench/api/node/extHostCLIServer.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { IURIToOpen, URIType } from 'vs/platform/windows/common/windows';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
|
||||
export class CLIServer {
|
||||
|
||||
private _server: http.Server;
|
||||
private _ipcHandlePath: string | undefined;
|
||||
|
||||
constructor(private _commands: ExtHostCommands) {
|
||||
this._server = http.createServer((req, res) => this.onRequest(req, res));
|
||||
this.setup().catch(err => {
|
||||
console.error(err);
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
public get ipcHandlePath() {
|
||||
return this._ipcHandlePath;
|
||||
}
|
||||
|
||||
private async setup(): Promise<string> {
|
||||
this._ipcHandlePath = generateRandomPipeName();
|
||||
|
||||
try {
|
||||
this._server.listen(this.ipcHandlePath);
|
||||
this._server.on('error', err => console.error(err));
|
||||
} catch (err) {
|
||||
console.error('Could not start open from terminal server.');
|
||||
}
|
||||
|
||||
return this.ipcHandlePath;
|
||||
}
|
||||
private collectURIToOpen(strs: string[], typeHint: URIType, result: IURIToOpen[]): void {
|
||||
if (Array.isArray(strs)) {
|
||||
for (const s of strs) {
|
||||
try {
|
||||
result.push({ uri: URI.parse(s), typeHint });
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
|
||||
const chunks: string[] = [];
|
||||
req.setEncoding('utf8');
|
||||
req.on('data', (d: string) => chunks.push(d));
|
||||
req.on('end', () => {
|
||||
const data = JSON.parse(chunks.join(''));
|
||||
switch (data.type) {
|
||||
case 'open':
|
||||
this.open(data, res);
|
||||
break;
|
||||
default:
|
||||
res.writeHead(404);
|
||||
res.write(`Unkown message type: ${data.type}`, err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
res.end();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private open(data: any, res: http.ServerResponse) {
|
||||
let { fileURIs, folderURIs, forceNewWindow, diffMode, addMode, forceReuseWindow } = data;
|
||||
if (folderURIs && folderURIs.length || fileURIs && fileURIs.length) {
|
||||
const urisToOpen: IURIToOpen[] = [];
|
||||
this.collectURIToOpen(folderURIs, 'folder', urisToOpen);
|
||||
this.collectURIToOpen(fileURIs, 'file', urisToOpen);
|
||||
if (!forceReuseWindow && urisToOpen.some(o => o.typeHint === 'folder' || (o.typeHint === 'file' && hasWorkspaceFileExtension(o.uri.path)))) {
|
||||
forceNewWindow = true;
|
||||
}
|
||||
this._commands.executeCommand('_files.windowOpen', { urisToOpen, forceNewWindow, diffMode, addMode, forceReuseWindow });
|
||||
}
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._server.close();
|
||||
|
||||
if (this._ipcHandlePath && process.platform !== 'win32' && fs.existsSync(this._ipcHandlePath)) {
|
||||
fs.unlinkSync(this._ipcHandlePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { EXT_HOST_CREATION_DELAY } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { sanitizeProcessEnvironment } from 'vs/base/node/processes';
|
||||
import { IURIToOpen, URIType } from 'vs/platform/windows/common/windows';
|
||||
|
||||
const RENDERER_NO_PROCESS_ID = -1;
|
||||
|
||||
@@ -270,7 +265,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
private _terminalProcesses: { [id: number]: TerminalProcess } = {};
|
||||
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
|
||||
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||
private _cliServer: CLIServer | undefined;
|
||||
|
||||
public get activeTerminal(): ExtHostTerminal { return this._activeTerminal; }
|
||||
public get terminals(): ExtHostTerminal[] { return this._terminals; }
|
||||
@@ -288,7 +282,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
mainContext: IMainContext,
|
||||
private _extHostConfiguration: ExtHostConfiguration,
|
||||
private _logService: ILogService,
|
||||
private _commands: ExtHostCommands
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
|
||||
}
|
||||
@@ -453,17 +446,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
|
||||
// Sanitize the environment, removing any undesirable VS Code and Electron environment
|
||||
// variables
|
||||
sanitizeProcessEnvironment(env);
|
||||
sanitizeProcessEnvironment(env, 'VSCODE_IPC_HOOK_CLI');
|
||||
|
||||
// Continue env initialization, merging in the env from the launch
|
||||
// config and adding keys that are needed to create the process
|
||||
terminalEnvironment.addTerminalEnvironmentKeys(env, platform.locale, terminalConfig.get('setLocaleVariables'));
|
||||
|
||||
if (!this._cliServer) {
|
||||
this._cliServer = new CLIServer(this._commands);
|
||||
}
|
||||
env['VSCODE_IPC_HOOK_CLI'] = this._cliServer.ipcHandlePath;
|
||||
|
||||
// Fork the process and listen for messages
|
||||
this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env);
|
||||
const p = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, terminalConfig.get('windowsEnableConpty'));
|
||||
@@ -512,11 +500,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
// Send exit event to main side
|
||||
this._proxy.$sendProcessExit(id, exitCode);
|
||||
|
||||
if (this._cliServer && !Object.keys(this._terminalProcesses).length) {
|
||||
this._cliServer.dispose();
|
||||
this._cliServer = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private _getTerminalByIdEventually(id: number, retries: number = 5): Promise<ExtHostTerminal> {
|
||||
@@ -588,74 +571,3 @@ class ApiRequest {
|
||||
this._callback.apply(proxy, [id].concat(this._args));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CLIServer {
|
||||
|
||||
private _server: http.Server;
|
||||
private _ipcHandlePath: string | undefined;
|
||||
|
||||
constructor(private _commands: ExtHostCommands) {
|
||||
this._server = http.createServer((req, res) => this.onRequest(req, res));
|
||||
this.setup().catch(err => {
|
||||
console.error(err);
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
public get ipcHandlePath() {
|
||||
return this._ipcHandlePath;
|
||||
}
|
||||
|
||||
private async setup(): Promise<string> {
|
||||
this._ipcHandlePath = generateRandomPipeName();
|
||||
|
||||
try {
|
||||
this._server.listen(this.ipcHandlePath);
|
||||
this._server.on('error', err => console.error(err));
|
||||
} catch (err) {
|
||||
console.error('Could not start open from terminal server.');
|
||||
}
|
||||
|
||||
return this.ipcHandlePath;
|
||||
}
|
||||
private collectURIToOpen(strs: string[], typeHint: URIType, result: IURIToOpen[]): void {
|
||||
if (Array.isArray(strs)) {
|
||||
for (const s of strs) {
|
||||
try {
|
||||
result.push({ uri: URI.parse(s), typeHint });
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
|
||||
const chunks: string[] = [];
|
||||
req.setEncoding('utf8');
|
||||
req.on('data', (d: string) => chunks.push(d));
|
||||
req.on('end', () => {
|
||||
let { fileURIs, folderURIs, forceNewWindow, diffMode, addMode, forceReuseWindow } = JSON.parse(chunks.join(''));
|
||||
if (folderURIs && folderURIs.length || fileURIs && fileURIs.length) {
|
||||
if (folderURIs && folderURIs.length && !forceReuseWindow) {
|
||||
forceNewWindow = true;
|
||||
}
|
||||
const urisToOpen: IURIToOpen[] = [];
|
||||
this.collectURIToOpen(folderURIs, 'folder', urisToOpen);
|
||||
this.collectURIToOpen(fileURIs, 'file', urisToOpen);
|
||||
this._commands.executeCommand('_files.windowOpen', { urisToOpen, forceNewWindow, diffMode, addMode, forceReuseWindow });
|
||||
}
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._server.close();
|
||||
|
||||
if (this._ipcHandlePath && process.platform !== 'win32' && fs.existsSync(this._ipcHandlePath)) {
|
||||
fs.unlinkSync(this._ipcHandlePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user