Prepare Code for integration with code-server 1. We already have the arguments so allow passing them in. There is also a slight change in a few directories to preserve the directory structure we have been using and to not override passed-in arguments. 2. Modify the terminal environment to filter out code-server environment variables. 3. Add the code-server version to the help dialog. 4. Add ready events for use in an iframe. 5. Add our icons. 6. Use our own manifest. Index: code-server/lib/vscode/src/vs/server/node/server.main.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/server.main.ts +++ code-server/lib/vscode/src/vs/server/node/server.main.ts @@ -12,7 +12,7 @@ import { createServer as doCreateServer, import { parseArgs, ErrorReporter } from 'vs/platform/environment/node/argv'; import { join, dirname } from 'vs/base/common/path'; import { performance } from 'perf_hooks'; -import { serverOptions } from 'vs/server/node/serverEnvironmentService'; +import { serverOptions, ServerParsedArgs } from 'vs/server/node/serverEnvironmentService'; import product from 'vs/platform/product/common/product'; import * as perf from 'vs/base/common/performance'; @@ -34,38 +34,43 @@ const errorReporter: ErrorReporter = { } }; -const args = parseArgs(process.argv.slice(2), serverOptions, errorReporter); +function parse(): ServerParsedArgs { + return parseArgs(process.argv.slice(2), serverOptions, errorReporter); +} -const REMOTE_DATA_FOLDER = args['server-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote'); -const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data'); -const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User'); -const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage'); -const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History'); -const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine'); -args['user-data-dir'] = USER_DATA_PATH; -const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath); -const BUILTIN_EXTENSIONS_FOLDER_PATH = join(APP_ROOT, 'extensions'); -args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH; -args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions'); - -[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => { - try { - if (!fs.existsSync(f)) { - fs.mkdirSync(f, { mode: 0o700 }); - } - } catch (err) { console.error(err); } -}); +function createDirs(args: ServerParsedArgs): string { + const REMOTE_DATA_FOLDER = args['server-data-dir'] || args['user-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote'); + const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data'); + const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User'); + const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage'); + const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History'); + const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine'); + args['user-data-dir'] = USER_DATA_PATH; + const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath); + const BUILTIN_EXTENSIONS_FOLDER_PATH = args['builtin-extensions-dir'] || join(APP_ROOT, 'extensions'); + args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH; + args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions'); + + [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => { + try { + if (!fs.existsSync(f)) { + fs.mkdirSync(f, { mode: 0o700 }); + } + } catch (err) { console.error(err); } + }); + return REMOTE_DATA_FOLDER; +} /** * invoked by server-main.js */ -export function spawnCli() { - runCli(args, REMOTE_DATA_FOLDER, serverOptions); +export function spawnCli(args = parse()): Promise { + return runCli(args, createDirs(args), serverOptions); } /** * invoked by server-main.js */ -export function createServer(address: string | net.AddressInfo | null): Promise { - return doCreateServer(address, args, REMOTE_DATA_FOLDER); +export function createServer(address: string | net.AddressInfo | null, args = parse()): Promise { + return doCreateServer(address, args, createDirs(args)); } Index: code-server/lib/vscode/src/vs/base/common/processes.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/processes.ts +++ code-server/lib/vscode/src/vs/base/common/processes.ts @@ -111,6 +111,8 @@ export function sanitizeProcessEnvironme /^VSCODE_(?!(PORTABLE|SHELL_LOGIN|ENV_REPLACE|ENV_APPEND|ENV_PREPEND)).+$/, /^SNAP(|_.*)$/, /^GDK_PIXBUF_.+$/, + /^CODE_SERVER_.+$/, + /^CS_.+$/, ]; const envKeys = Object.keys(env); envKeys Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts +++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts @@ -77,8 +77,11 @@ export class BrowserDialogHandler extend async about(): Promise { const detailString = (useAgo: boolean): string => { - return localize('aboutDetail', - "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}", + return localize('aboutCodeServerDetail', + "code-server: {0}", + this.productService.codeServerVersion ? `v${this.productService.codeServerVersion}` : 'Unknown' + ) + '\n' + localize('aboutDetail', + "Code: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}", this.productService.version || 'Unknown', this.productService.commit || 'Unknown', this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown', Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts =================================================================== --- /dev/null +++ code-server/lib/vscode/src/vs/workbench/browser/client.ts @@ -0,0 +1,46 @@ +import { Disposable } from 'vs/base/common/lifecycle'; + +export class CodeServerClient extends Disposable { + constructor ( + ) { + super(); + } + + async startup(): Promise { + // Emit ready events + const event = new CustomEvent('ide-ready'); + window.dispatchEvent(event); + + if (parent) { + // Tell the parent loading has completed. + parent.postMessage({ event: 'loaded' }, '*'); + + // Proxy or stop proxing events as requested by the parent. + const listeners = new Map void>(); + + window.addEventListener('message', parentEvent => { + const eventName = parentEvent.data.bind || parentEvent.data.unbind; + if (eventName) { + const oldListener = listeners.get(eventName); + if (oldListener) { + document.removeEventListener(eventName, oldListener); + } + } + + if (parentEvent.data.bind && parentEvent.data.prop) { + const listener = (event: Event) => { + parent?.postMessage( + { + event: parentEvent.data.event, + [parentEvent.data.prop]: event[parentEvent.data.prop as keyof Event], + }, + window.location.origin, + ); + }; + listeners.set(parentEvent.data.bind, listener); + document.addEventListener(parentEvent.data.bind, listener); + } + }); + } + } +} Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts @@ -64,6 +64,7 @@ import { IOpenerService } from 'vs/platf import { mixin, safeStringify } from 'vs/base/common/objects'; import { IndexedDB } from 'vs/base/browser/indexedDB'; import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; +import { CodeServerClient } from 'vs/workbench/browser/client'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel'; @@ -131,6 +132,9 @@ export class BrowserMain extends Disposa // Startup const instantiationService = workbench.startup(); + const codeServerClient = this._register(instantiationService.createInstance(CodeServerClient)); + await codeServerClient.startup(); + // Window this._register(instantiationService.createInstance(BrowserWindow)); Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts @@ -55,6 +55,8 @@ export type ExtensionVirtualWorkspaceSup }; export interface IProductConfiguration { + readonly codeServerVersion?: string + readonly version: string; readonly date?: string; readonly quality?: string; Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html =================================================================== --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html @@ -11,7 +11,8 @@ - + + @@ -26,9 +27,9 @@ - - - + + + Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html =================================================================== --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html @@ -11,7 +11,8 @@ - + + @@ -23,8 +24,9 @@ - - + + + Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts @@ -307,6 +307,7 @@ export class WebClientServer { } : undefined; const productConfiguration = { + codeServerVersion: this._productService.codeServerVersion, embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? { ...this._productService.extensionsGallery,