refactor: change goHome test to helpAbout

This commit is contained in:
Joe Previte 2021-03-16 12:49:49 -07:00
parent 0c2708302d
commit bcdca86539
No known key found for this signature in database
GPG Key ID: 2C91590C6B742C24
3 changed files with 304 additions and 279 deletions

View File

@ -9,133 +9,124 @@ export interface Options {
} }
export interface InitMessage { export interface InitMessage {
type: 'init'; type: "init"
id: string; id: string
options: VscodeOptions; options: VscodeOptions
} }
export type Query = { [key: string]: string | string[] | undefined | Query | Query[] }; export type Query = { [key: string]: string | string[] | undefined | Query | Query[] }
export interface SocketMessage { export interface SocketMessage {
type: 'socket'; type: "socket"
query: Query; query: Query
permessageDeflate: boolean; permessageDeflate: boolean
} }
export interface CliMessage { export interface CliMessage {
type: 'cli'; type: "cli"
args: Args; args: Args
} }
export interface OpenCommandPipeArgs { export interface OpenCommandPipeArgs {
type: 'open'; type: "open"
fileURIs?: string[]; fileURIs?: string[]
folderURIs: string[]; folderURIs: string[]
forceNewWindow?: boolean; forceNewWindow?: boolean
diffMode?: boolean; diffMode?: boolean
addMode?: boolean; addMode?: boolean
gotoLineMode?: boolean; gotoLineMode?: boolean
forceReuseWindow?: boolean; forceReuseWindow?: boolean
waitMarkerFilePath?: string; waitMarkerFilePath?: string
} }
export type CodeServerMessage = InitMessage | SocketMessage | CliMessage; export type CodeServerMessage = InitMessage | SocketMessage | CliMessage
export interface ReadyMessage { export interface ReadyMessage {
type: 'ready'; type: "ready"
} }
export interface OptionsMessage { export interface OptionsMessage {
id: string; id: string
type: 'options'; type: "options"
options: WorkbenchOptions; options: WorkbenchOptions
} }
export type VscodeMessage = ReadyMessage | OptionsMessage; export type VscodeMessage = ReadyMessage | OptionsMessage
export interface StartPath { export interface StartPath {
url: string; url: string
workspace: boolean; workspace: boolean
} }
export interface Args { export interface Args {
'user-data-dir'?: string; "user-data-dir"?: string
'enable-proposed-api'?: string[]; "enable-proposed-api"?: string[]
'extensions-dir'?: string; "extensions-dir"?: string
'builtin-extensions-dir'?: string; "builtin-extensions-dir"?: string
'extra-extensions-dir'?: string[]; "extra-extensions-dir"?: string[]
'extra-builtin-extensions-dir'?: string[]; "extra-builtin-extensions-dir"?: string[]
'ignore-last-opened'?: boolean; "ignore-last-opened"?: boolean
locale?: string locale?: string
log?: string; log?: string
verbose?: boolean; verbose?: boolean
home?: string;
_: string[]; _: string[]
} }
export interface VscodeOptions { export interface VscodeOptions {
readonly args: Args; readonly args: Args
readonly remoteAuthority: string; readonly remoteAuthority: string
readonly startPath?: StartPath; readonly startPath?: StartPath
} }
export interface VscodeOptionsMessage extends VscodeOptions { export interface VscodeOptionsMessage extends VscodeOptions {
readonly id: string; readonly id: string
} }
export interface UriComponents { export interface UriComponents {
readonly scheme: string; readonly scheme: string
readonly authority: string; readonly authority: string
readonly path: string; readonly path: string
readonly query: string; readonly query: string
readonly fragment: string; readonly fragment: string
} }
export interface NLSConfiguration { export interface NLSConfiguration {
locale: string; locale: string
availableLanguages: { availableLanguages: {
[key: string]: string; [key: string]: string
}; }
pseudo?: boolean; pseudo?: boolean
_languagePackSupport?: boolean; _languagePackSupport?: boolean
} }
export interface WorkbenchOptions { export interface WorkbenchOptions {
readonly workbenchWebConfiguration: { readonly workbenchWebConfiguration: {
readonly remoteAuthority?: string; readonly remoteAuthority?: string
readonly folderUri?: UriComponents; readonly folderUri?: UriComponents
readonly workspaceUri?: UriComponents; readonly workspaceUri?: UriComponents
readonly logLevel?: number; readonly logLevel?: number
readonly workspaceProvider?: { readonly workspaceProvider?: {
payload: [ payload: [["userDataPath", string], ["enableProposedApi", string]]
['userDataPath', string], }
['enableProposedApi', string], }
]; readonly remoteUserDataUri: UriComponents
};
readonly homeIndicator?: {
href: string,
icon: string,
title: string,
},
};
readonly remoteUserDataUri: UriComponents;
readonly productConfiguration: { readonly productConfiguration: {
codeServerVersion?: string; codeServerVersion?: string
readonly extensionsGallery?: { readonly extensionsGallery?: {
readonly serviceUrl: string; readonly serviceUrl: string
readonly itemUrl: string; readonly itemUrl: string
readonly controlUrl: string; readonly controlUrl: string
readonly recommendationsUrl: string; readonly recommendationsUrl: string
}; }
}; }
readonly nlsConfiguration: NLSConfiguration; readonly nlsConfiguration: NLSConfiguration
readonly commit: string; readonly commit: string
} }
export interface WorkbenchOptionsMessage { export interface WorkbenchOptionsMessage {
id: string; id: string
} }

View File

@ -1,100 +1,108 @@
import { field } from '@coder/logger'; import { field } from "@coder/logger"
import { release } from 'os'; import { release } from "os"
import * as fs from 'fs'; import * as fs from "fs"
import * as net from 'net'; import * as net from "net"
import * as path from 'path'; import * as path from "path"
import { Emitter } from 'vs/base/common/event'; import { Emitter } from "vs/base/common/event"
import { Schemas } from 'vs/base/common/network'; import { Schemas } from "vs/base/common/network"
import { URI } from 'vs/base/common/uri'; import { URI } from "vs/base/common/uri"
import { getMachineId } from 'vs/base/node/id'; import { getMachineId } from "vs/base/node/id"
import { ClientConnectionEvent, IPCServer, IServerChannel, ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { ClientConnectionEvent, IPCServer, IServerChannel, ProxyChannel } from "vs/base/parts/ipc/common/ipc"
import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; import { LogsDataCleaner } from "vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner"
import { main } from 'vs/code/node/cliProcessMain'; import { main } from "vs/code/node/cliProcessMain"
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from "vs/platform/configuration/common/configuration"
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService'; import { ConfigurationService } from "vs/platform/configuration/common/configurationService"
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; import { ExtensionHostDebugBroadcastChannel } from "vs/platform/debug/common/extensionHostDebugIpc"
import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { NativeParsedArgs } from "vs/platform/environment/common/argv"
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService, INativeEnvironmentService } from "vs/platform/environment/common/environment"
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; import { NativeEnvironmentService } from "vs/platform/environment/node/environmentService"
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; import { ExtensionGalleryService } from "vs/platform/extensionManagement/common/extensionGalleryService"
import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import {
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc'; IExtensionGalleryService,
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; IExtensionManagementService,
import { IFileService } from 'vs/platform/files/common/files'; } from "vs/platform/extensionManagement/common/extensionManagement"
import { FileService } from 'vs/platform/files/common/fileService'; import { ExtensionManagementChannel } from "vs/platform/extensionManagement/common/extensionManagementIpc"
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { ExtensionManagementService } from "vs/platform/extensionManagement/node/extensionManagementService"
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IFileService } from "vs/platform/files/common/files"
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { FileService } from "vs/platform/files/common/fileService"
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider"
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { SyncDescriptor } from "vs/platform/instantiation/common/descriptors"
import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; import { InstantiationService } from "vs/platform/instantiation/common/instantiationService"
import { ConsoleLogger, getLogLevel, ILoggerService, ILogService, MultiplexLogService } from 'vs/platform/log/common/log'; import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"
import { LogLevelChannel } from 'vs/platform/log/common/logIpc'; import { ILocalizationsService } from "vs/platform/localizations/common/localizations"
import { LoggerService } from 'vs/platform/log/node/loggerService'; import { LocalizationsService } from "vs/platform/localizations/node/localizations"
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog'; import {
import product from 'vs/platform/product/common/product'; ConsoleLogger,
import { IProductService } from 'vs/platform/product/common/productService'; getLogLevel,
import { ConnectionType, ConnectionTypeRequest } from 'vs/platform/remote/common/remoteAgentConnection'; ILoggerService,
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment'; ILogService,
import { IRequestService } from 'vs/platform/request/common/request'; MultiplexLogService,
import { RequestChannel } from 'vs/platform/request/common/requestIpc'; } from "vs/platform/log/common/log"
import { RequestService } from 'vs/platform/request/node/requestService'; import { LogLevelChannel } from "vs/platform/log/common/logIpc"
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; import { LoggerService } from "vs/platform/log/node/loggerService"
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { SpdLogLogger } from "vs/platform/log/node/spdlogLog"
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender'; import product from "vs/platform/product/common/product"
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import { IProductService } from "vs/platform/product/common/productService"
import { combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { ConnectionType, ConnectionTypeRequest } from "vs/platform/remote/common/remoteAgentConnection"
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; import { RemoteAgentConnectionContext } from "vs/platform/remote/common/remoteAgentEnvironment"
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties'; import { IRequestService } from "vs/platform/request/common/request"
import { TelemetryChannel } from 'vs/server/common/telemetry'; import { RequestChannel } from "vs/platform/request/common/requestIpc"
import { Query, VscodeOptions, WorkbenchOptions } from 'vs/server/ipc'; import { RequestService } from "vs/platform/request/node/requestService"
import { ExtensionEnvironmentChannel, FileProviderChannel, TerminalProviderChannel } from 'vs/server/node/channel'; import ErrorTelemetry from "vs/platform/telemetry/browser/errorTelemetry"
import { Connection, ExtensionHostConnection, ManagementConnection } from 'vs/server/node/connection'; import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"
import { TelemetryClient } from 'vs/server/node/insights'; import { TelemetryLogAppender } from "vs/platform/telemetry/common/telemetryLogAppender"
import { logger } from 'vs/server/node/logger'; import { TelemetryService } from "vs/platform/telemetry/common/telemetryService"
import { getLocaleFromConfig, getNlsConfiguration } from 'vs/server/node/nls'; import { combinedAppender, NullTelemetryService } from "vs/platform/telemetry/common/telemetryUtils"
import { Protocol } from 'vs/server/node/protocol'; import { AppInsightsAppender } from "vs/platform/telemetry/node/appInsightsAppender"
import { getUriTransformer } from 'vs/server/node/util'; import { resolveCommonProperties } from "vs/platform/telemetry/common/commonProperties"
import { REMOTE_TERMINAL_CHANNEL_NAME } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { TelemetryChannel } from "vs/server/common/telemetry"
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteAgentFileSystemChannel'; import { Query, VscodeOptions, WorkbenchOptions } from "vs/server/ipc"
import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService'; import { ExtensionEnvironmentChannel, FileProviderChannel, TerminalProviderChannel } from "vs/server/node/channel"
import { localize } from 'vs/nls'; import { Connection, ExtensionHostConnection, ManagementConnection } from "vs/server/node/connection"
import { TelemetryClient } from "vs/server/node/insights"
import { logger } from "vs/server/node/logger"
import { getLocaleFromConfig, getNlsConfiguration } from "vs/server/node/nls"
import { Protocol } from "vs/server/node/protocol"
import { getUriTransformer } from "vs/server/node/util"
import { REMOTE_TERMINAL_CHANNEL_NAME } from "vs/workbench/contrib/terminal/common/remoteTerminalChannel"
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from "vs/workbench/services/remote/common/remoteAgentFileSystemChannel"
import { RemoteExtensionLogFileName } from "vs/workbench/services/remote/common/remoteAgentService"
export class Vscode { export class Vscode {
public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>(); public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>()
public readonly onDidClientConnect = this._onDidClientConnect.event; public readonly onDidClientConnect = this._onDidClientConnect.event
private readonly ipc = new IPCServer<RemoteAgentConnectionContext>(this.onDidClientConnect); private readonly ipc = new IPCServer<RemoteAgentConnectionContext>(this.onDidClientConnect)
private readonly maxExtraOfflineConnections = 0; private readonly maxExtraOfflineConnections = 0
private readonly connections = new Map<ConnectionType, Map<string, Connection>>(); private readonly connections = new Map<ConnectionType, Map<string, Connection>>()
private readonly services = new ServiceCollection(); private readonly services = new ServiceCollection()
private servicesPromise?: Promise<void>; private servicesPromise?: Promise<void>
public async cli(args: NativeParsedArgs): Promise<void> { public async cli(args: NativeParsedArgs): Promise<void> {
return main(args); return main(args)
} }
public async initialize(options: VscodeOptions): Promise<WorkbenchOptions> { public async initialize(options: VscodeOptions): Promise<WorkbenchOptions> {
const transformer = getUriTransformer(options.remoteAuthority); const transformer = getUriTransformer(options.remoteAuthority)
if (!this.servicesPromise) { if (!this.servicesPromise) {
this.servicesPromise = this.initializeServices(options.args); this.servicesPromise = this.initializeServices(options.args)
} }
await this.servicesPromise; await this.servicesPromise
const environment = this.services.get(IEnvironmentService) as INativeEnvironmentService; const environment = this.services.get(IEnvironmentService) as INativeEnvironmentService
const startPath = options.startPath; const startPath = options.startPath
const parseUrl = (url: string): URI => { const parseUrl = (url: string): URI => {
// This might be a fully-specified URL or just a path. // This might be a fully-specified URL or just a path.
try { try {
return URI.parse(url, true); return URI.parse(url, true)
} catch (error) { } catch (error) {
return URI.from({ return URI.from({
scheme: Schemas.vscodeRemote, scheme: Schemas.vscodeRemote,
authority: options.remoteAuthority, authority: options.remoteAuthority,
path: url, path: url,
}); })
} }
}; }
return { return {
workbenchWebConfiguration: { workbenchWebConfiguration: {
workspaceUri: startPath && startPath.workspace ? parseUrl(startPath.url) : undefined, workspaceUri: startPath && startPath.workspace ? parseUrl(startPath.url) : undefined,
@ -103,111 +111,112 @@ export class Vscode {
logLevel: getLogLevel(environment), logLevel: getLogLevel(environment),
workspaceProvider: { workspaceProvider: {
payload: [ payload: [
['userDataPath', environment.userDataPath], ["userDataPath", environment.userDataPath],
['enableProposedApi', JSON.stringify(options.args['enable-proposed-api'] || [])] ["enableProposedApi", JSON.stringify(options.args["enable-proposed-api"] || [])],
], ],
}, },
homeIndicator: options.args.home ? {
href: options.args.home,
icon: 'code',
title: localize('home', "Home"),
} : undefined,
}, },
remoteUserDataUri: transformer.transformOutgoing(URI.file(environment.userDataPath)), remoteUserDataUri: transformer.transformOutgoing(URI.file(environment.userDataPath)),
productConfiguration: product, productConfiguration: product,
nlsConfiguration: await getNlsConfiguration(environment.args.locale || await getLocaleFromConfig(environment.userDataPath), environment.userDataPath), nlsConfiguration: await getNlsConfiguration(
commit: product.commit || 'development', environment.args.locale || (await getLocaleFromConfig(environment.userDataPath)),
}; environment.userDataPath,
),
commit: product.commit || "development",
}
} }
public async handleWebSocket(socket: net.Socket, query: Query, permessageDeflate: boolean): Promise<true> { public async handleWebSocket(socket: net.Socket, query: Query, permessageDeflate: boolean): Promise<true> {
if (!query.reconnectionToken) { if (!query.reconnectionToken) {
throw new Error('Reconnection token is missing from query parameters'); throw new Error("Reconnection token is missing from query parameters")
} }
const protocol = new Protocol(socket, { const protocol = new Protocol(socket, {
reconnectionToken: <string>query.reconnectionToken, reconnectionToken: <string>query.reconnectionToken,
reconnection: query.reconnection === 'true', reconnection: query.reconnection === "true",
skipWebSocketFrames: query.skipWebSocketFrames === 'true', skipWebSocketFrames: query.skipWebSocketFrames === "true",
permessageDeflate, permessageDeflate,
recordInflateBytes: permessageDeflate, recordInflateBytes: permessageDeflate,
}); })
try { try {
await this.connect(await protocol.handshake(), protocol); await this.connect(await protocol.handshake(), protocol)
} catch (error) { } catch (error) {
protocol.sendMessage({ type: 'error', reason: error.message }); protocol.sendMessage({ type: "error", reason: error.message })
protocol.dispose(); protocol.dispose()
protocol.getSocket().dispose(); protocol.getSocket().dispose()
} }
return true; return true
} }
private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise<void> { private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise<void> {
if (product.commit && message.commit !== product.commit) { if (product.commit && message.commit !== product.commit) {
logger.warn(`Version mismatch (${message.commit} instead of ${product.commit})`); logger.warn(`Version mismatch (${message.commit} instead of ${product.commit})`)
} }
switch (message.desiredConnectionType) { switch (message.desiredConnectionType) {
case ConnectionType.ExtensionHost: case ConnectionType.ExtensionHost:
case ConnectionType.Management: case ConnectionType.Management:
if (!this.connections.has(message.desiredConnectionType)) { if (!this.connections.has(message.desiredConnectionType)) {
this.connections.set(message.desiredConnectionType, new Map()); this.connections.set(message.desiredConnectionType, new Map())
} }
const connections = this.connections.get(message.desiredConnectionType)!; const connections = this.connections.get(message.desiredConnectionType)!
const ok = async () => { const ok = async () => {
return message.desiredConnectionType === ConnectionType.ExtensionHost return message.desiredConnectionType === ConnectionType.ExtensionHost
? { debugPort: await this.getDebugPort() } ? { debugPort: await this.getDebugPort() }
: { type: 'ok' }; : { type: "ok" }
}; }
const token = protocol.options.reconnectionToken; const token = protocol.options.reconnectionToken
if (protocol.options.reconnection && connections.has(token)) { if (protocol.options.reconnection && connections.has(token)) {
protocol.sendMessage(await ok()); protocol.sendMessage(await ok())
const buffer = protocol.readEntireBuffer(); const buffer = protocol.readEntireBuffer()
protocol.dispose(); protocol.dispose()
return connections.get(token)!.reconnect(protocol.getSocket(), buffer); return connections.get(token)!.reconnect(protocol.getSocket(), buffer)
} else if (protocol.options.reconnection || connections.has(token)) { } else if (protocol.options.reconnection || connections.has(token)) {
throw new Error(protocol.options.reconnection throw new Error(
? 'Unrecognized reconnection token' protocol.options.reconnection ? "Unrecognized reconnection token" : "Duplicate reconnection token",
: 'Duplicate reconnection token' )
);
} }
logger.debug('New connection', field('token', token)); logger.debug("New connection", field("token", token))
protocol.sendMessage(await ok()); protocol.sendMessage(await ok())
let connection: Connection; let connection: Connection
if (message.desiredConnectionType === ConnectionType.Management) { if (message.desiredConnectionType === ConnectionType.Management) {
connection = new ManagementConnection(protocol, token); connection = new ManagementConnection(protocol, token)
this._onDidClientConnect.fire({ this._onDidClientConnect.fire({
protocol, onDidClientDisconnect: connection.onClose, protocol,
}); onDidClientDisconnect: connection.onClose,
})
} else { } else {
const buffer = protocol.readEntireBuffer(); const buffer = protocol.readEntireBuffer()
connection = new ExtensionHostConnection( connection = new ExtensionHostConnection(
message.args ? message.args.language : 'en', message.args ? message.args.language : "en",
protocol, buffer, token, protocol,
buffer,
token,
this.services.get(IEnvironmentService) as INativeEnvironmentService, this.services.get(IEnvironmentService) as INativeEnvironmentService,
); )
} }
connections.set(token, connection); connections.set(token, connection)
connection.onClose(() => { connection.onClose(() => {
logger.debug('Connection closed', field('token', token)); logger.debug("Connection closed", field("token", token))
connections.delete(token); connections.delete(token)
}); })
this.disposeOldOfflineConnections(connections); this.disposeOldOfflineConnections(connections)
break; break
case ConnectionType.Tunnel: return protocol.tunnel(); case ConnectionType.Tunnel:
default: throw new Error('Unrecognized connection type'); return protocol.tunnel()
default:
throw new Error("Unrecognized connection type")
} }
} }
private disposeOldOfflineConnections(connections: Map<string, Connection>): void { private disposeOldOfflineConnections(connections: Map<string, Connection>): void {
const offline = Array.from(connections.values()) const offline = Array.from(connections.values()).filter((connection) => typeof connection.offline !== "undefined")
.filter((connection) => typeof connection.offline !== 'undefined');
for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) { for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) {
logger.debug('Disposing offline connection', field('token', offline[i].token)); logger.debug("Disposing offline connection", field("token", offline[i].token))
offline[i].dispose(); offline[i].dispose()
} }
} }
@ -219,9 +228,9 @@ export class Vscode {
If upstream changes cause conflicts, look there ^. If upstream changes cause conflicts, look there ^.
3/11/21 @jsjoeio 3/11/21 @jsjoeio
*/ */
const environmentService = new NativeEnvironmentService(args); const environmentService = new NativeEnvironmentService(args)
// https://github.com/cdr/code-server/issues/1693 // https://github.com/cdr/code-server/issues/1693
fs.mkdirSync(environmentService.globalStorageHome.fsPath, { recursive: true }); fs.mkdirSync(environmentService.globalStorageHome.fsPath, { recursive: true })
/* /*
NOTE@coder: Made these updates on based on this file (and lines): NOTE@coder: Made these updates on based on this file (and lines):
Reference: - ../../electron-browser/sharedProcess/sharedProcessMain.ts#L144-L149 Reference: - ../../electron-browser/sharedProcess/sharedProcessMain.ts#L144-L149
@ -234,21 +243,26 @@ export class Vscode {
*/ */
const logService = new MultiplexLogService([ const logService = new MultiplexLogService([
new ConsoleLogger(getLogLevel(environmentService)), new ConsoleLogger(getLogLevel(environmentService)),
new SpdLogLogger(RemoteExtensionLogFileName, path.join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`), false, getLogLevel(environmentService)) new SpdLogLogger(
]); RemoteExtensionLogFileName,
const fileService = new FileService(logService); path.join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`),
fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(logService)); false,
getLogLevel(environmentService),
),
])
const fileService = new FileService(logService)
fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(logService))
const loggerService = new LoggerService(logService, fileService); const loggerService = new LoggerService(logService, fileService)
const piiPaths = [ const piiPaths = [
path.join(environmentService.userDataPath, 'clp'), // Language packs. path.join(environmentService.userDataPath, "clp"), // Language packs.
environmentService.appRoot, environmentService.appRoot,
environmentService.extensionsPath, environmentService.extensionsPath,
environmentService.builtinExtensionsPath, environmentService.builtinExtensionsPath,
...environmentService.extraExtensionPaths, ...environmentService.extraExtensionPaths,
...environmentService.extraBuiltinExtensionPaths, ...environmentService.extraBuiltinExtensionPaths,
]; ]
/* /*
NOTE@coder: we changed this channel registration from LogLevel to LogLevelChannel NOTE@coder: we changed this channel registration from LogLevel to LogLevelChannel
@ -256,67 +270,80 @@ export class Vscode {
3/15/21 jsjoeio 3/15/21 jsjoeio
*/ */
this.ipc.registerChannel('logger', new LogLevelChannel(logService)); this.ipc.registerChannel("logger", new LogLevelChannel(logService))
this.ipc.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ExtensionHostDebugBroadcastChannel()); this.ipc.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ExtensionHostDebugBroadcastChannel())
this.services.set(ILogService, logService); this.services.set(ILogService, logService)
this.services.set(IEnvironmentService, environmentService); this.services.set(IEnvironmentService, environmentService)
this.services.set(INativeEnvironmentService, environmentService); this.services.set(INativeEnvironmentService, environmentService)
/* /*
NOTE@coder: we changed this from LoggerService to the loggerService defined above. NOTE@coder: we changed this from LoggerService to the loggerService defined above.
3/11/21 @jsjoeio 3/11/21 @jsjoeio
*/ */
this.services.set(ILoggerService, loggerService); this.services.set(ILoggerService, loggerService)
const configurationService = new ConfigurationService(environmentService.settingsResource, fileService); const configurationService = new ConfigurationService(environmentService.settingsResource, fileService)
await configurationService.initialize(); await configurationService.initialize()
this.services.set(IConfigurationService, configurationService); this.services.set(IConfigurationService, configurationService)
this.services.set(IRequestService, new SyncDescriptor(RequestService)); this.services.set(IRequestService, new SyncDescriptor(RequestService))
this.services.set(IFileService, fileService); this.services.set(IFileService, fileService)
this.services.set(IProductService, { _serviceBrand: undefined, ...product }); this.services.set(IProductService, { _serviceBrand: undefined, ...product })
const machineId = await getMachineId(); const machineId = await getMachineId()
await new Promise((resolve) => { await new Promise((resolve) => {
const instantiationService = new InstantiationService(this.services); const instantiationService = new InstantiationService(this.services)
instantiationService.invokeFunction((accessor) => { instantiationService.invokeFunction((accessor) => {
instantiationService.createInstance(LogsDataCleaner); instantiationService.createInstance(LogsDataCleaner)
let telemetryService: ITelemetryService; let telemetryService: ITelemetryService
if (!environmentService.disableTelemetry) { if (!environmentService.disableTelemetry) {
telemetryService = new TelemetryService({ telemetryService = new TelemetryService(
appender: combinedAppender( {
new AppInsightsAppender('code-server', null, () => new TelemetryClient() as any), appender: combinedAppender(
new TelemetryLogAppender(accessor.get(ILoggerService), environmentService) new AppInsightsAppender("code-server", null, () => new TelemetryClient() as any),
), new TelemetryLogAppender(accessor.get(ILoggerService), environmentService),
sendErrorTelemetry: true, ),
commonProperties: resolveCommonProperties( sendErrorTelemetry: true,
fileService, release(), process.arch, product.commit, product.version, machineId, commonProperties: resolveCommonProperties(
[], environmentService.installSourcePath, 'code-server', fileService,
), release(),
piiPaths, process.arch,
}, configurationService); product.commit,
product.version,
machineId,
[],
environmentService.installSourcePath,
"code-server",
),
piiPaths,
},
configurationService,
)
} else { } else {
telemetryService = NullTelemetryService; telemetryService = NullTelemetryService
} }
this.services.set(ITelemetryService, telemetryService); this.services.set(ITelemetryService, telemetryService)
this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService))
this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService))
this.services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); this.services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService))
this.ipc.registerChannel('extensions', new ExtensionManagementChannel( this.ipc.registerChannel(
accessor.get(IExtensionManagementService), "extensions",
(context) => getUriTransformer(context.remoteAuthority), new ExtensionManagementChannel(accessor.get(IExtensionManagementService), (context) =>
)); getUriTransformer(context.remoteAuthority),
this.ipc.registerChannel('remoteextensionsenvironment', new ExtensionEnvironmentChannel( ),
environmentService, logService, telemetryService, '', )
)); this.ipc.registerChannel(
this.ipc.registerChannel('request', new RequestChannel(accessor.get(IRequestService))); "remoteextensionsenvironment",
this.ipc.registerChannel('telemetry', new TelemetryChannel(telemetryService)); new ExtensionEnvironmentChannel(environmentService, logService, telemetryService, ""),
)
this.ipc.registerChannel("request", new RequestChannel(accessor.get(IRequestService)))
this.ipc.registerChannel("telemetry", new TelemetryChannel(telemetryService))
/* /*
NOTE@coder: they renamed createChannelReceiver and made it part of the ProxyChannel namespace NOTE@coder: they renamed createChannelReceiver and made it part of the ProxyChannel namespace
See: https://github.com/microsoft/vscode/commit/e371faebfb679ca0dcdb61f4f2f33b3d69922a77 See: https://github.com/microsoft/vscode/commit/e371faebfb679ca0dcdb61f4f2f33b3d69922a77
@ -325,18 +352,24 @@ export class Vscode {
https://github.com/microsoft/vscode/blob/e371faebfb679ca0dcdb61f4f2f33b3d69922a77/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts#L273 https://github.com/microsoft/vscode/blob/e371faebfb679ca0dcdb61f4f2f33b3d69922a77/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts#L273
3/11/2021 by @jsjoeio 3/11/2021 by @jsjoeio
*/ */
this.ipc.registerChannel('localizations', <IServerChannel<any>>ProxyChannel.fromService(accessor.get(ILocalizationsService))); this.ipc.registerChannel(
this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); "localizations",
this.ipc.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new TerminalProviderChannel(logService)); <IServerChannel<any>>ProxyChannel.fromService(accessor.get(ILocalizationsService)),
resolve(new ErrorTelemetry(telemetryService)); )
}); this.ipc.registerChannel(
}); REMOTE_FILE_SYSTEM_CHANNEL_NAME,
new FileProviderChannel(environmentService, logService),
)
this.ipc.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new TerminalProviderChannel(logService))
resolve(new ErrorTelemetry(telemetryService))
})
})
} }
/** /**
* TODO: implement. * TODO: implement.
*/ */
private async getDebugPort(): Promise<number | undefined> { private async getDebugPort(): Promise<number | undefined> {
return undefined; return undefined
} }
} }

View File

@ -3,13 +3,13 @@ import { hash } from "../src/node/util"
import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "./constants" import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "./constants"
import { createCookieIfDoesntExist } from "./helpers" import { createCookieIfDoesntExist } from "./helpers"
describe("go home", () => { describe("Open Help > About", () => {
let browser: Browser let browser: Browser
let page: Page let page: Page
let context: BrowserContext let context: BrowserContext
beforeAll(async () => { beforeAll(async () => {
browser = await chromium.launch() browser = await chromium.launch({ headless: false })
// Create a new context with the saved storage state // Create a new context with the saved storage state
const storageState = JSON.parse(STORAGE) || {} const storageState = JSON.parse(STORAGE) || {}
@ -61,13 +61,11 @@ describe("go home", () => {
page = await context.newPage() page = await context.newPage()
}) })
// NOTE: this test will fail if you do not run code-server with --home $CODE_SERVER_ADDRESS/healthz it("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async () => {
it("should see a 'Go Home' button in the Application Menu that goes to /healthz", async () => {
const GO_HOME_URL = `${CODE_SERVER_ADDRESS}/healthz`
// Sometimes a dialog shows up when you navigate // Sometimes a dialog shows up when you navigate
// asking if you're sure you want to leave // asking if you're sure you want to leave
// so we listen if it comes, we accept it // so we listen if it comes, we accept it
page.on("dialog", (dialog) => dialog.accept()) // page.on("dialog", (dialog) => dialog.accept())
// waitUntil: "domcontentloaded" // waitUntil: "domcontentloaded"
// In case the page takes a long time to load // In case the page takes a long time to load
@ -76,16 +74,19 @@ describe("go home", () => {
// Make sure the editor actually loaded // Make sure the editor actually loaded
expect(await page.isVisible("div.monaco-workbench")) expect(await page.isVisible("div.monaco-workbench"))
// Click the Home menu // Click the Application menu
await page.click("[aria-label='Application Menu']") await page.click("[aria-label='Application Menu']")
// See the Go Home button // See the Help button
const goHomeButton = "a.action-menu-item span[aria-label='Go Home']" const helpButton = "a.action-menu-item span[aria-label='Help']"
expect(await page.isVisible(goHomeButton)) expect(await page.isVisible(helpButton))
// Click it and navigate to /healthz // Click it and navigate to /healthz
// NOTE: ran into issues of it failing intermittently // NOTE: ran into issues of it failing intermittently
// without having button: "middle" // without having button: "middle"
await Promise.all([page.waitForNavigation(), page.click(goHomeButton, { button: "middle" })]) await Promise.all([page.waitForNavigation(), page.click(helpButton, { button: "middle" })])
expect(page.url()).toBe(GO_HOME_URL)
// see the About button
const aboutButton = "a.action-menu-item span[aria-label='About']"
expect(await page.isVisible(aboutButton))
}) })
}) })