environmentService.ts 8.9 KB
Newer Older
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import { Schemas } from 'vs/base/common/network';
7
import { joinPath } from 'vs/base/common/resources';
8 9
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
B
Benjamin Pasero 已提交
10
import { BACKUPS, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment';
11 12
import { IPath } from 'vs/platform/windows/common/windows';
import { IWorkbenchEnvironmentService, IEnvironmentConfiguration } from 'vs/workbench/services/environment/common/environmentService';
13
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
M
Matt Bierner 已提交
14
import product from 'vs/platform/product/common/product';
15
import { memoize } from 'vs/base/common/decorators';
16
import { onUnexpectedError } from 'vs/base/common/errors';
17

18
export class BrowserEnvironmentConfiguration implements IEnvironmentConfiguration {
19

20 21 22
	constructor(
		private readonly options: IBrowserWorkbenchEnvironmentConstructionOptions,
		private readonly payload: Map<string, string> | undefined,
23
		private readonly backupHome: URI
24
	) { }
25

B
Benjamin Pasero 已提交
26 27 28
	@memoize
	get sessionId(): string { return generateUuid(); }

B
Benjamin Pasero 已提交
29
	@memoize
30 31
	get remoteAuthority(): string | undefined { return this.options.remoteAuthority; }

B
Benjamin Pasero 已提交
32
	@memoize
33
	get backupWorkspaceResource(): URI { return joinPath(this.backupHome, this.options.workspaceId); }
B
Benjamin Pasero 已提交
34

35 36 37 38 39 40 41 42 43 44 45 46
	@memoize
	get filesToOpenOrCreate(): IPath[] | undefined {
		if (this.payload) {
			const fileToOpen = this.payload.get('openFile');
			if (fileToOpen) {
				return [{ fileUri: URI.parse(fileToOpen) }];
			}
		}

		return undefined;
	}

47 48 49 50 51 52 53 54 55 56 57 58
	@memoize
	get filesToDiff(): IPath[] | undefined {
		if (this.payload) {
			const fileToDiffDetail = this.payload.get('diffFileDetail');
			const fileToDiffMaster = this.payload.get('diffFileMaster');
			if (fileToDiffDetail && fileToDiffMaster) {
				return [
					{ fileUri: URI.parse(fileToDiffDetail) },
					{ fileUri: URI.parse(fileToDiffMaster) }
				];
			}
		}
B
Benjamin Pasero 已提交
59

60 61
		return undefined;
	}
B
Benjamin Pasero 已提交
62

63 64
	get highContrast() {
		return false; // could investigate to detect high contrast theme automatically
B
Benjamin Pasero 已提交
65
	}
66 67
}

S
SteVen Batten 已提交
68
interface IBrowserWorkbenchEnvironmentConstructionOptions extends IWorkbenchConstructionOptions {
S
Sandeep Somavarapu 已提交
69
	workspaceId: string;
70
	logsPath: URI;
S
Sandeep Somavarapu 已提交
71 72
}

B
Benjamin Pasero 已提交
73 74 75
interface IExtensionHostDebugEnvironment {
	params: IExtensionHostDebugParams;
	isExtensionDevelopment: boolean;
76
	extensionDevelopmentLocationURI?: URI[];
77
	extensionTestsLocationURI?: URI;
78
	extensionEnabledProposedApi?: string[];
B
Benjamin Pasero 已提交
79 80
}

81
export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironmentService {
82

83
	_serviceBrand: undefined;
84

85 86
	private _configuration: IEnvironmentConfiguration | undefined = undefined;
	get configuration(): IEnvironmentConfiguration {
87
		if (!this._configuration) {
88
			this._configuration = new BrowserEnvironmentConfiguration(this.options, this.payload, this.backupHome);
89 90 91 92
		}

		return this._configuration;
	}
93

94 95 96
	@memoize
	get isBuilt(): boolean { return !!product.commit; }

97 98
	@memoize
	get logsPath(): string { return this.options.logsPath.path; }
99

100 101
	get logLevel(): string | undefined { return this.payload?.get('logLevel'); }

102 103
	@memoize
	get logFile(): URI { return joinPath(this.options.logsPath, 'window.log'); }
104

105 106
	@memoize
	get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); }
107

108 109
	@memoize
	get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
110

B
Benjamin Pasero 已提交
111 112 113
	@memoize
	get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }

114 115 116
	@memoize
	get snippetsHome(): URI { return joinPath(this.userRoamingDataHome, 'snippets'); }

117 118 119 120 121
	/*
	 * In Web every workspace can potentially have scoped user-data and/or extensions and if Sync state is shared then it can make
	 * Sync error prone - say removing extensions from another workspace. Hence scope Sync state per workspace.
	 * Sync scoped to a workspace is capable of handling even if workspaces/windows share same user data and extensions.
	 */
122
	@memoize
123
	get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync', this.options.workspaceId); }
124

125 126 127
	@memoize
	get userDataSyncLogResource(): URI { return joinPath(this.options.logsPath, 'userDataSync.log'); }

S
Sandeep Somavarapu 已提交
128
	@memoize
129
	get sync(): 'on' | 'off' | undefined { return undefined; }
130

S
Sandeep Somavarapu 已提交
131 132
	@memoize
	get enableSyncByDefault(): boolean { return !!this.options.enableSyncByDefault; }
133

134 135 136
	@memoize
	get keybindingsResource(): URI { return joinPath(this.userRoamingDataHome, 'keybindings.json'); }

B
Benjamin Pasero 已提交
137
	@memoize
138 139
	get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }

B
Benjamin Pasero 已提交
140 141 142 143 144 145
	@memoize
	get backupHome(): URI { return joinPath(this.userRoamingDataHome, BACKUPS); }

	@memoize
	get untitledWorkspacesHome(): URI { return joinPath(this.userRoamingDataHome, 'Workspaces'); }

S
Sandeep Somavarapu 已提交
146 147 148
	@memoize
	get serviceMachineIdResource(): URI { return joinPath(this.userRoamingDataHome, 'machineid'); }

B
Benjamin Pasero 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	private _extensionHostDebugEnvironment: IExtensionHostDebugEnvironment | undefined = undefined;
	get debugExtensionHost(): IExtensionHostDebugParams {
		if (!this._extensionHostDebugEnvironment) {
			this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
		}

		return this._extensionHostDebugEnvironment.params;
	}

	get isExtensionDevelopment(): boolean {
		if (!this._extensionHostDebugEnvironment) {
			this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
		}

		return this._extensionHostDebugEnvironment.isExtensionDevelopment;
	}

166
	get extensionDevelopmentLocationURI(): URI[] | undefined {
B
Benjamin Pasero 已提交
167 168 169 170 171 172 173
		if (!this._extensionHostDebugEnvironment) {
			this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
		}

		return this._extensionHostDebugEnvironment.extensionDevelopmentLocationURI;
	}

174 175 176 177 178 179 180 181
	get extensionTestsLocationURI(): URI | undefined {
		if (!this._extensionHostDebugEnvironment) {
			this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
		}

		return this._extensionHostDebugEnvironment.extensionTestsLocationURI;
	}

182 183 184 185 186 187 188 189
	get extensionEnabledProposedApi(): string[] | undefined {
		if (!this._extensionHostDebugEnvironment) {
			this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
		}

		return this._extensionHostDebugEnvironment.extensionEnabledProposedApi;
	}

190 191
	get disableExtensions() { return this.payload?.get('disableExtensions') === 'true'; }

B
Benjamin Pasero 已提交
192 193
	@memoize
	get webviewExternalEndpoint(): string {
194
		// TODO@matt: get fallback from product.json
M
Matt Bierner 已提交
195
		return (this.options.webviewEndpoint || 'https://{{uuid}}.vscode-webview-test.com/{{commit}}').replace('{{commit}}', product.commit || '0d728c31ebdf03869d2687d9be0b017667c9ff37');
B
Benjamin Pasero 已提交
196 197 198 199 200 201 202 203 204 205 206 207
	}

	@memoize
	get webviewResourceRoot(): string {
		return `${this.webviewExternalEndpoint}/vscode-resource/{{resource}}`;
	}

	@memoize
	get webviewCspSource(): string {
		return this.webviewExternalEndpoint.replace('{{uuid}}', '*');
	}

208 209 210 211
	get disableTelemetry(): boolean { return false; }

	get verbose(): boolean { return this.payload?.get('verbose') === 'true'; }
	get logExtensionHostCommunication(): boolean { return this.payload?.get('logExtensionHostCommunication') === 'true'; }
212

213 214 215 216
	private payload: Map<string, string> | undefined;

	constructor(readonly options: IBrowserWorkbenchEnvironmentConstructionOptions) {
		if (options.workspaceProvider && Array.isArray(options.workspaceProvider.payload)) {
217 218 219 220 221
			try {
				this.payload = new Map(options.workspaceProvider.payload);
			} catch (error) {
				onUnexpectedError(error); // possible invalid payload for map
			}
222 223
		}
	}
224

B
Benjamin Pasero 已提交
225 226 227 228 229 230 231
	private resolveExtensionHostDebugEnvironment(): IExtensionHostDebugEnvironment {
		const extensionHostDebugEnvironment: IExtensionHostDebugEnvironment = {
			params: {
				port: null,
				break: false
			},
			isExtensionDevelopment: false,
232
			extensionDevelopmentLocationURI: undefined
233
		};
M
Matt Bierner 已提交
234

235
		// Fill in selected extra environmental properties
236 237
		if (this.payload) {
			for (const [key, value] of this.payload) {
238 239
				switch (key) {
					case 'extensionDevelopmentPath':
B
Benjamin Pasero 已提交
240 241
						extensionHostDebugEnvironment.extensionDevelopmentLocationURI = [URI.parse(value)];
						extensionHostDebugEnvironment.isExtensionDevelopment = true;
242
						break;
A
Andre Weinand 已提交
243 244 245
					case 'extensionTestsPath':
						extensionHostDebugEnvironment.extensionTestsLocationURI = URI.parse(value);
						break;
246
					case 'debugId':
B
Benjamin Pasero 已提交
247
						extensionHostDebugEnvironment.params.debugId = value;
248 249
						break;
					case 'inspect-brk-extensions':
B
Benjamin Pasero 已提交
250
						extensionHostDebugEnvironment.params.port = parseInt(value);
251
						extensionHostDebugEnvironment.params.break = true;
252
						break;
253 254 255
					case 'enableProposedApi':
						extensionHostDebugEnvironment.extensionEnabledProposedApi = [];
						break;
256 257 258
				}
			}
		}
S
Sandeep Somavarapu 已提交
259

B
Benjamin Pasero 已提交
260 261
		return extensionHostDebugEnvironment;
	}
262 263

	get skipReleaseNotes(): boolean { return false; }
264
}