Path: blob/main/src/vs/platform/environment/common/environmentService.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { toLocalISOString } from '../../../base/common/date.js';6import { memoize } from '../../../base/common/decorators.js';7import { FileAccess, Schemas } from '../../../base/common/network.js';8import { dirname, join, normalize, resolve } from '../../../base/common/path.js';9import { env } from '../../../base/common/process.js';10import { joinPath } from '../../../base/common/resources.js';11import { URI } from '../../../base/common/uri.js';12import { NativeParsedArgs } from './argv.js';13import { ExtensionKind, IExtensionHostDebugParams, INativeEnvironmentService } from './environment.js';14import { IProductService } from '../../product/common/productService.js';1516export const EXTENSION_IDENTIFIER_WITH_LOG_REGEX = /^([^.]+\..+)[:=](.+)$/;1718export interface INativeEnvironmentPaths {1920/**21* The user data directory to use for anything that should be22* persisted except for the content that is meant for the `homeDir`.23*24* Only one instance of VSCode can use the same `userDataDir`.25*/26userDataDir: string;2728/**29* The user home directory mainly used for persisting extensions30* and global configuration that should be shared across all31* versions.32*/33homeDir: string;3435/**36* OS tmp dir.37*/38tmpDir: string;39}4041export abstract class AbstractNativeEnvironmentService implements INativeEnvironmentService {4243declare readonly _serviceBrand: undefined;4445@memoize46get appRoot(): string { return dirname(FileAccess.asFileUri('').fsPath); }4748@memoize49get userHome(): URI { return URI.file(this.paths.homeDir); }5051@memoize52get userDataPath(): string { return this.paths.userDataDir; }5354@memoize55get appSettingsHome(): URI { return URI.file(join(this.userDataPath, 'User')); }5657@memoize58get tmpDir(): URI { return URI.file(this.paths.tmpDir); }5960@memoize61get cacheHome(): URI { return URI.file(this.userDataPath); }6263@memoize64get stateResource(): URI { return joinPath(this.appSettingsHome, 'globalStorage', 'storage.json'); }6566@memoize67get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.vscodeUserData }); }6869@memoize70get userDataSyncHome(): URI { return joinPath(this.appSettingsHome, 'sync'); }7172get logsHome(): URI {73if (!this.args.logsPath) {74const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');75this.args.logsPath = join(this.userDataPath, 'logs', key);76}7778return URI.file(this.args.logsPath);79}8081@memoize82get sync(): 'on' | 'off' | undefined { return this.args.sync; }8384@memoize85get workspaceStorageHome(): URI { return joinPath(this.appSettingsHome, 'workspaceStorage'); }8687@memoize88get localHistoryHome(): URI { return joinPath(this.appSettingsHome, 'History'); }8990@memoize91get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }9293@memoize94get argvResource(): URI {95const vscodePortable = env['VSCODE_PORTABLE'];96if (vscodePortable) {97return URI.file(join(vscodePortable, 'argv.json'));98}99100return joinPath(this.userHome, this.productService.dataFolderName, 'argv.json');101}102103@memoize104get isExtensionDevelopment(): boolean { return !!this.args.extensionDevelopmentPath; }105106@memoize107get untitledWorkspacesHome(): URI { return URI.file(join(this.userDataPath, 'Workspaces')); }108109@memoize110get builtinExtensionsPath(): string {111const cliBuiltinExtensionsDir = this.args['builtin-extensions-dir'];112if (cliBuiltinExtensionsDir) {113return resolve(cliBuiltinExtensionsDir);114}115116return normalize(join(FileAccess.asFileUri('').fsPath, '..', 'extensions'));117}118119get extensionsDownloadLocation(): URI {120const cliExtensionsDownloadDir = this.args['extensions-download-dir'];121if (cliExtensionsDownloadDir) {122return URI.file(resolve(cliExtensionsDownloadDir));123}124125return URI.file(join(this.userDataPath, 'CachedExtensionVSIXs'));126}127128@memoize129get extensionsPath(): string {130const cliExtensionsDir = this.args['extensions-dir'];131if (cliExtensionsDir) {132return resolve(cliExtensionsDir);133}134135const vscodeExtensions = env['VSCODE_EXTENSIONS'];136if (vscodeExtensions) {137return vscodeExtensions;138}139140const vscodePortable = env['VSCODE_PORTABLE'];141if (vscodePortable) {142return join(vscodePortable, 'extensions');143}144145return joinPath(this.userHome, this.productService.dataFolderName, 'extensions').fsPath;146}147148@memoize149get extensionDevelopmentLocationURI(): URI[] | undefined {150const extensionDevelopmentPaths = this.args.extensionDevelopmentPath;151if (Array.isArray(extensionDevelopmentPaths)) {152return extensionDevelopmentPaths.map(extensionDevelopmentPath => {153if (/^[^:/?#]+?:\/\//.test(extensionDevelopmentPath)) {154return URI.parse(extensionDevelopmentPath);155}156157return URI.file(normalize(extensionDevelopmentPath));158});159}160161return undefined;162}163164@memoize165get extensionDevelopmentKind(): ExtensionKind[] | undefined {166return this.args.extensionDevelopmentKind?.map(kind => kind === 'ui' || kind === 'workspace' || kind === 'web' ? kind : 'workspace');167}168169@memoize170get extensionTestsLocationURI(): URI | undefined {171const extensionTestsPath = this.args.extensionTestsPath;172if (extensionTestsPath) {173if (/^[^:/?#]+?:\/\//.test(extensionTestsPath)) {174return URI.parse(extensionTestsPath);175}176177return URI.file(normalize(extensionTestsPath));178}179180return undefined;181}182183get disableExtensions(): boolean | string[] {184if (this.args['disable-extensions']) {185return true;186}187188const disableExtensions = this.args['disable-extension'];189if (disableExtensions) {190if (typeof disableExtensions === 'string') {191return [disableExtensions];192}193194if (Array.isArray(disableExtensions) && disableExtensions.length > 0) {195return disableExtensions;196}197}198199return false;200}201202@memoize203get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostDebugPort(this.args, this.isBuilt); }204get debugRenderer(): boolean { return !!this.args.debugRenderer; }205206get isBuilt(): boolean { return !env['VSCODE_DEV']; }207get verbose(): boolean { return !!this.args.verbose; }208209@memoize210get logLevel(): string | undefined { return this.args.log?.find(entry => !EXTENSION_IDENTIFIER_WITH_LOG_REGEX.test(entry)); }211@memoize212get extensionLogLevel(): [string, string][] | undefined {213const result: [string, string][] = [];214for (const entry of this.args.log || []) {215const matches = EXTENSION_IDENTIFIER_WITH_LOG_REGEX.exec(entry);216if (matches && matches[1] && matches[2]) {217result.push([matches[1], matches[2]]);218}219}220return result.length ? result : undefined;221}222223@memoize224get serviceMachineIdResource(): URI { return joinPath(URI.file(this.userDataPath), 'machineid'); }225226get crashReporterId(): string | undefined { return this.args['crash-reporter-id']; }227get crashReporterDirectory(): string | undefined { return this.args['crash-reporter-directory']; }228229@memoize230get disableTelemetry(): boolean { return !!this.args['disable-telemetry']; }231232@memoize233get disableExperiments(): boolean { return !!this.args['disable-experiments']; }234235@memoize236get disableWorkspaceTrust(): boolean { return !!this.args['disable-workspace-trust']; }237238@memoize239get useInMemorySecretStorage(): boolean { return !!this.args['use-inmemory-secretstorage']; }240241@memoize242get policyFile(): URI | undefined {243if (this.args['__enable-file-policy']) {244const vscodePortable = env['VSCODE_PORTABLE'];245if (vscodePortable) {246return URI.file(join(vscodePortable, 'policy.json'));247}248249return joinPath(this.userHome, this.productService.dataFolderName, 'policy.json');250}251return undefined;252}253254get editSessionId(): string | undefined { return this.args['editSessionId']; }255256get continueOn(): string | undefined {257return this.args['continueOn'];258}259260set continueOn(value: string | undefined) {261this.args['continueOn'] = value;262}263264get args(): NativeParsedArgs { return this._args; }265266get isSimulation(): boolean {267return env['SIMULATION'] === '1';268}269270constructor(271private readonly _args: NativeParsedArgs,272private readonly paths: INativeEnvironmentPaths,273protected readonly productService: IProductService274) { }275}276277export function parseExtensionHostDebugPort(args: NativeParsedArgs, isBuilt: boolean): IExtensionHostDebugParams {278return parseDebugParams(args['inspect-extensions'], args['inspect-brk-extensions'], 5870, isBuilt, args.debugId, args.extensionEnvironment);279}280281export function parseDebugParams(debugArg: string | undefined, debugBrkArg: string | undefined, defaultBuildPort: number, isBuilt: boolean, debugId?: string, environmentString?: string): IExtensionHostDebugParams {282const portStr = debugBrkArg || debugArg;283const port = Number(portStr) || (!isBuilt ? defaultBuildPort : null);284const brk = port ? Boolean(!!debugBrkArg) : false;285let env: Record<string, string> | undefined;286if (environmentString) {287try {288env = JSON.parse(environmentString);289} catch {290// ignore291}292}293294return { port, break: brk, debugId, env };295}296297298