Hook up shared process sorta

This commit is contained in:
Asher
2019-01-18 18:04:24 -06:00
committed by Kyle Carberry
parent d827015b40
commit 811260cc80
15 changed files with 198 additions and 246 deletions

View File

@@ -1,10 +1,12 @@
import "./fill/require";
import "./fill/storageDatabase";
import "./fill/windowsService";
import * as paths from "./fill/paths";
import "./fill/dom";
import "./vscode.scss";
import { fork } from "child_process";
import { createConnection } from "net";
import { Client as IDEClient, IURI, IURIFactory } from "@coder/ide";
import { logger } from "@coder/logger";
import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu";
import { LogLevel } from "vs/platform/log/common/log";
@@ -12,36 +14,42 @@ import { toLocalISOString } from "vs/base/common/date";
// import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
import { URI } from "vs/base/common/uri";
import { Protocol, ISharedProcessInitData } from "./protocol";
import * as paths from "./fill/paths";
import "./firefox";
import { Protocol } from "vs/base/parts/ipc/node/ipc.net";
export class Client extends IDEClient {
private readonly sharedProcessLogger = logger.named("shr proc");
private readonly windowId = parseInt(toLocalISOString(new Date()).replace(/[-:.TZ]/g, ""), 10);
private readonly version = "hello"; // TODO: pull from package.json probably
private readonly bootstrapForkLocation = "/bootstrap"; // TODO: location.
public readonly protocolPromise: Promise<Protocol>;
private protoResolve: ((protocol: Protocol) => void) | undefined;
public protoResolve: ((protocol: Protocol) => void) | undefined;
public constructor() {
super();
process.env.VSCODE_LOGS = "/tmp/vscode-online/logs"; // TODO: use tmpdir or get log directory from init data.
this.protocolPromise = new Promise((resolve): void => {
this.protoResolve = resolve;
});
}
protected initialize(): Promise<void> {
this.task("Start shared process", 5, async () => {
const protocol = await this.forkSharedProcess();
this.protoResolve!(protocol);
this.task("Connect to shared process", 5, async () => {
await new Promise((resolve, reject): void => {
const listener = this.onSharedProcessActive((data) => {
listener.dispose();
const socket = createConnection(data.socketPath, resolve);
socket.once("error", () => {
reject();
});
this.protoResolve!(new Protocol(socket));
});
});
}).catch(() => undefined);
registerContextMenuListener();
return this.task("Start workbench", 1000, async (initData) => {
paths.paths.appData = initData.dataDirectory;
paths.paths.defaultUserData = initData.dataDirectory;
const { startup } = require("./startup");
await startup({
machineId: "1",
@@ -57,6 +65,33 @@ export class Client extends IDEClient {
folderUri: URI.file(initData.dataDirectory),
});
// TODO: Set notification service for retrying.
// this.retry.setNotificationService({
// prompt: (severity, message, buttons, onCancel) => {
// const handle = getNotificationService().prompt(severity, message, buttons, onCancel);
// return {
// close: () => handle.close(),
// updateMessage: (message) => handle.updateMessage(message),
// updateButtons: (buttons) => handle.updateActions({
// primary: buttons.map((button) => ({
// id: undefined,
// label: button.label,
// tooltip: undefined,
// class: undefined,
// enabled: true,
// checked: false,
// radio: false,
// dispose: () => undefined,
// run: () => {
// button.run();
// return Promise.resolve();
// },
// })),
// }),
// };
// }
// });
// TODO: Set up clipboard context.
// const workbench = workbenchShell.workbench;
// const contextKeys = workbench.workbenchParams.serviceCollection.get(IContextKeyService) as IContextKeyService;
@@ -69,50 +104,6 @@ export class Client extends IDEClient {
}, this.initData);
}
public async forkSharedProcess(): Promise<Protocol> {
const childProcess = fork(this.bootstrapForkLocation, ["--shared"], {
env: {
"VSCODE_ALLOW_IO": "true",
"AMD_ENTRYPOINT": "vs/code/electron-browser/sharedProcess/sharedProcessClient",
},
});
childProcess.stderr.on("data", (data) => {
this.sharedProcessLogger.error("stderr: " + data);
});
const protocol = Protocol.fromProcess(childProcess);
await new Promise((resolve, reject): void => {
protocol.onClose(() => {
reject(new Error("unable to establish connection to shared process"));
});
const listener = protocol.onMessage((message) => {
const messageStr = message.toString();
this.sharedProcessLogger.debug(messageStr);
switch (messageStr) {
case "handshake:hello":
protocol.send(Buffer.from(JSON.stringify({
// Using the version so if we get a new mount, it spins up a new
// shared process.
socketPath: `/tmp/vscode-online/shared-${this.version}.sock`,
serviceUrl: "", // TODO
logsDir: process.env.VSCODE_LOGS,
windowId: this.windowId,
logLevel: LogLevel.Info,
} as ISharedProcessInitData)));
break;
case "handshake:ready":
listener.dispose();
resolve();
break;
}
});
});
return protocol;
}
protected createUriFactory(): IURIFactory {
return {
// TODO: not sure why this is an error.
@@ -126,8 +117,3 @@ export class Client extends IDEClient {
}
export const client = new Client();
client.initData.then((initData) => {
paths.appData = initData.dataDirectory;
paths.defaultUserData = initData.dataDirectory;
});