shell.ts 26.8 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/shell';

10
import * as nls from 'vs/nls';
J
Joao Moreno 已提交
11
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
12
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
13
import dom = require('vs/base/browser/dom');
14
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
15
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
16
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
17
import { toErrorMessage } from 'vs/base/common/errorMessage';
18
import product from 'vs/platform/node/product';
19
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
20
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
21
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
22
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
23
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
24
import { NullTelemetryService, configurationTelemetry, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
25
import { IExperimentService, ExperimentService } from 'vs/platform/telemetry/common/experiments';
J
Johannes Rieken 已提交
26 27 28
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { IdleMonitor, UserStatus } from 'vs/platform/telemetry/browser/idleMonitor';
J
Joao Moreno 已提交
29
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
30
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
31
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
32
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
33
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
34
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
35
import { IRequestService } from 'vs/platform/request/node/request';
36
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
37 38 39 40 41 42 43
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { MarkerService } from 'vs/platform/markers/common/markerService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServiceImpl';
44
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
J
Johannes Rieken 已提交
45 46 47 48
import { IntegrityServiceImpl } from 'vs/platform/integrity/node/integrityServiceImpl';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
49
import { ExtensionService } from 'vs/workbench/services/extensions/electron-browser/extensionService';
J
Johannes Rieken 已提交
50
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
51
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
52 53 54
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
S
Sandeep Somavarapu 已提交
55
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
56 57
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
58
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
59 60 61 62
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
63
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
64
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
65
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
66 67
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
68
import { ICrashReporterService, NullCrashReporterService, CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
J
Johannes Rieken 已提交
69 70 71
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
72 73
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
B
Benjamin Pasero 已提交
74
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
75
import { remote } from 'electron';
76
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
77 78
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
79
import 'vs/platform/opener/browser/opener.contribution';
80 81
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
82 83
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
84
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
85
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
86 87
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
88
import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService';
B
Benjamin Pasero 已提交
89 90
import { HashService } from 'vs/workbench/services/hash/node/hashService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
J
Joao Moreno 已提交
91
import { ILogService } from 'vs/platform/log/common/log';
92

93 94 95 96 97 98
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
99
	environmentService: IEnvironmentService;
J
Joao Moreno 已提交
100
	logService: ILogService;
B
Benjamin Pasero 已提交
101
	timerService: ITimerService;
102
	storageService: IStorageService;
103 104
}

105 106
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
107
/**
B
Benjamin Pasero 已提交
108
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
109 110 111
 * With the Shell being the top level element in the page, it is also responsible for driving the layouting.
 */
export class WorkbenchShell {
B
Benjamin Pasero 已提交
112
	private storageService: IStorageService;
113
	private messageService: MessageService;
J
Johannes Rieken 已提交
114
	private environmentService: IEnvironmentService;
J
Joao Moreno 已提交
115
	private logService: ILogService;
B
Benjamin Pasero 已提交
116
	private contextViewService: ContextViewService;
117 118
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
119
	private telemetryService: ITelemetryService;
120
	private experimentService: IExperimentService;
121
	private extensionService: ExtensionService;
122
	private broadcastService: IBroadcastService;
B
Benjamin Pasero 已提交
123
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
124
	private themeService: WorkbenchThemeService;
125
	private lifecycleService: LifecycleService;
126 127
	private mainProcessServices: ServiceCollection;

E
Erich Gamma 已提交
128
	private container: HTMLElement;
129
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
130 131 132 133 134
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

135
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
136 137
	private workbench: Workbench;

B
Benjamin Pasero 已提交
138
	constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, configuration: IWindowConfiguration) {
E
Erich Gamma 已提交
139 140
		this.container = container;

141
		this.configuration = configuration;
142

B
Benjamin Pasero 已提交
143 144 145
		this.contextService = coreServices.contextService;
		this.configurationService = coreServices.configurationService;
		this.environmentService = coreServices.environmentService;
J
Joao Moreno 已提交
146
		this.logService = coreServices.logService;
B
Benjamin Pasero 已提交
147 148
		this.timerService = coreServices.timerService;
		this.storageService = coreServices.storageService;
E
Erich Gamma 已提交
149

150 151
		this.mainProcessServices = mainProcessServices;

E
Erich Gamma 已提交
152 153 154 155 156 157
		this.toUnbind = [];
		this.previousErrorTime = 0;
	}

	private createContents(parent: Builder): Builder {

158
		// ARIA
B
Benjamin Pasero 已提交
159
		aria.setARIAContainer(document.body);
160

E
Erich Gamma 已提交
161
		// Workbench Container
162
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
163 164

		// Instantiation service with services
165
		const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement());
E
Erich Gamma 已提交
166 167

		// Workbench
168
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection, this.lifecycleService);
169
		try {
B
Benjamin Pasero 已提交
170
			this.workbench.startup().done(startupInfos => this.onWorkbenchStarted(startupInfos, instantiationService));
171 172
		} catch (error) {

173 174 175 176
			// Log to console and log
			const msg = toErrorMessage(error, true);
			console.error(msg);
			this.logService.error(msg);
177 178 179 180

			// Rethrow
			throw error;
		}
E
Erich Gamma 已提交
181

182
		// Window
183
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
184 185

		// Handle case where workbench is not starting up properly
186
		const timeoutHandle = setTimeout(() => {
187 188 189
			const msg = 'Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.';
			console.warn(msg);
			this.logService.warn(msg);
E
Erich Gamma 已提交
190 191
		}, 10000);

192
		this.lifecycleService.when(LifecyclePhase.Running).then(() => {
E
Erich Gamma 已提交
193 194 195 196 197 198
			clearTimeout(timeoutHandle);
		});

		return workbenchContainer;
	}

199
	private onWorkbenchStarted(info: IWorkbenchStartedInfo, instantiationService: IInstantiationService): void {
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214
		// Startup Telemetry
		this.logStartupTelemetry(info);

		// Root Warning
		if ((platform.isLinux || platform.isMacintosh) && process.getuid() === 0) {
			this.messageService.show(Severity.Warning, nls.localize('runningAsRoot', "It is recommended not to run Code as 'root'."));
		}

		// Set lifecycle phase to `Runnning` so that other contributions can now do something
		this.lifecycleService.phase = LifecyclePhase.Running;

		// Set lifecycle phase to `Runnning For A Bit` after a short delay
		let timeoutHandle = setTimeout(() => {
			timeoutHandle = void 0;
B
Benjamin Pasero 已提交
215
			this.lifecycleService.phase = LifecyclePhase.Eventually;
216 217 218 219 220 221 222 223 224 225 226
		}, 3000);
		this.toUnbind.push({
			dispose: () => {
				if (timeoutHandle) {
					clearTimeout(timeoutHandle);
				}
			}
		});
	}

	private logStartupTelemetry(info: IWorkbenchStartedInfo): void {
B
Benjamin Pasero 已提交
227
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;
K
kieferrm 已提交
228
		/* __GDPR__
K
kieferrm 已提交
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
			"workspaceLoad" : {
				"userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" },
				"experiments": { "${inline}": [ "${IExperiments}" ] },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
			}
		*/
250 251 252
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
253
			emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY,
254 255 256
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0,
257
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
258
			theme: this.themeService.getColorTheme().id,
259
			language: platform.language,
260
			experiments: this.experimentService.getExperiments(),
261 262
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
263 264
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
265 266
		});

B
Benjamin Pasero 已提交
267
		// Telemetry: startup metrics
268
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
269 270
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
271
		this.extensionService.whenInstalledExtensionsRegistered().done(() => {
K
kieferrm 已提交
272
			/* __GDPR__
K
kieferrm 已提交
273 274 275 276 277 278
				"startupTime" : {
					"${include}": [
						"${IStartupMetrics}"
					]
				}
			*/
B
Benjamin Pasero 已提交
279
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
280
		});
B
Benjamin Pasero 已提交
281 282
	}

283
	private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
J
Johannes Rieken 已提交
284
		const disposables: IDisposable[] = [];
J
Joao Moreno 已提交
285

286 287 288
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
289
		serviceCollection.set(IEnvironmentService, this.environmentService);
J
Joao Moreno 已提交
290
		serviceCollection.set(ILogService, this.logService);
B
Benjamin Pasero 已提交
291
		serviceCollection.set(ITimerService, this.timerService);
292
		serviceCollection.set(IStorageService, this.storageService);
293 294 295
		this.mainProcessServices.forEach((serviceIdentifier, serviceInstance) => {
			serviceCollection.set(serviceIdentifier, serviceInstance);
		});
296

297
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
298

299 300
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
301

302
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id, this.configuration));
J
Joao Moreno 已提交
303

304
		const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
305
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
306 307 308

		sharedProcess
			.done(client => client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel)));
309

310 311
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
312
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), browser.getZoomLevel()));
313

B
Benjamin Pasero 已提交
314 315 316
		// Hash
		serviceCollection.set(IHashService, new SyncDescriptor(HashService));

317 318 319 320
		// Experiments
		this.experimentService = instantiationService.createInstance(ExperimentService);
		serviceCollection.set(IExperimentService, this.experimentService);

321
		// Telemetry
322
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
323
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
324 325
			const commit = product.commit;
			const version = pkg.version;
326

327
			const config: ITelemetryServiceConfig = {
328
				appender: new TelemetryAppenderClient(channel),
329
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version, this.configuration.machineId, this.environmentService.installSourcePath),
330
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
331
			};
332

J
Joao Moreno 已提交
333
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
334 335
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
336
			const errorTelemetry = new ErrorTelemetry(telemetryService);
337
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
338

339
			const listener = idleMonitor.onStatusChange(status =>
K
kieferrm 已提交
340
				/* __GDPR__
K
kieferrm 已提交
341 342
					"UserIdleStart" : {}
				*/
K
kieferrm 已提交
343
				/* __GDPR__
K
kieferrm 已提交
344 345
					"UserIdleStop" : {}
				*/
346 347 348
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
349
				));
350

J
Johannes Rieken 已提交
351
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
352
		} else {
353
			this.telemetryService = NullTelemetryService;
354
		}
E
Erich Gamma 已提交
355

356
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
357
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
358

359
		let crashReporterService = NullCrashReporterService;
360
		if (!this.environmentService.disableCrashReporter && product.crashReporter && product.hockeyApp) {
361 362 363 364
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

365
		this.messageService = instantiationService.createInstance(MessageService, container);
366
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
367
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
368

369
		const lifecycleService = instantiationService.createInstance(LifecycleService);
J
Johannes Rieken 已提交
370
		this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
371
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
372
		serviceCollection.set(ILifecycleService, lifecycleService);
J
Johannes Rieken 已提交
373
		disposables.push(lifecycleTelemetry(this.telemetryService, lifecycleService));
374
		this.lifecycleService = lifecycleService;
375

S
Sandeep Somavarapu 已提交
376
		const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
377
		serviceCollection.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementChannelClient, extensionManagementChannel));
S
Sandeep Somavarapu 已提交
378

379 380
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
381
		disposables.push(extensionEnablementService);
382

383
		this.extensionService = instantiationService.createInstance(ExtensionService);
384
		serviceCollection.set(IExtensionService, this.extensionService);
385 386

		this.timerService.beforeExtensionLoad = Date.now();
387
		this.extensionService.whenInstalledExtensionsRegistered().done(() => {
388
			this.timerService.afterExtensionLoad = Date.now();
389
		});
E
Erich Gamma 已提交
390

B
Benjamin Pasero 已提交
391 392 393
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

394
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
395

396 397
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
398

399
		serviceCollection.set(IRequestService, new SyncDescriptor(RequestService));
E
Erich Gamma 已提交
400

401
		serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService));
E
Erich Gamma 已提交
402

403
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
404

405
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
406

407 408
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

409
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
410

411
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
412

413
		serviceCollection.set(ITextMateService, new SyncDescriptor(TextMateService));
A
Alex Dima 已提交
414

415
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
416

417
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
418

419
		serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
A
Alex Dima 已提交
420

421
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
	}

	public open(): void {

		// Listen on unexpected errors
		errors.setUnexpectedErrorHandler((error: any) => {
			this.onUnexpectedError(error);
		});

		// Shell Class for CSS Scoping
		$(this.container).addClass('monaco-shell');

		// Controls
		this.content = $('.monaco-shell-content').appendTo(this.container).getHTMLElement();

		// Create Contents
		this.contentsContainer = this.createContents($(this.content));

		// Layout
		this.layout();

		// Listeners
		this.registerListeners();
	}

	private registerListeners(): void {

		// Resize
		$(window).on(dom.EventType.RESIZE, () => this.layout(), this.toUnbind);
	}

	public onUnexpectedError(error: any): void {
454
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
455 456 457 458
		if (!errorMsg) {
			return;
		}

459
		const now = Date.now();
E
Erich Gamma 已提交
460 461 462 463 464 465 466
		if (errorMsg === this.previousErrorValue && now - this.previousErrorTime <= 1000) {
			return; // Return if error message identical to previous and shorter than 1 second
		}

		this.previousErrorTime = now;
		this.previousErrorValue = errorMsg;

467
		// Log to console and log
E
Erich Gamma 已提交
468
		console.error(errorMsg);
469
		this.logService.error(errorMsg);
E
Erich Gamma 已提交
470 471

		// Show to user if friendly message provided
472
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
473
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
474 475 476
		}
	}

B
Benjamin Pasero 已提交
477
	private layout(): void {
478
		const clArea = $(this.container).getClientArea();
E
Erich Gamma 已提交
479

480
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
481 482
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
483
		this.contextViewService.layout();
E
Erich Gamma 已提交
484 485 486
		this.workbench.layout();
	}

B
Benjamin Pasero 已提交
487
	public dispose(): void {
E
Erich Gamma 已提交
488 489 490

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
491
			this.workbench.dispose();
E
Erich Gamma 已提交
492 493
		}

B
Benjamin Pasero 已提交
494
		this.contextViewService.dispose();
E
Erich Gamma 已提交
495 496

		// Listeners
J
Joao Moreno 已提交
497
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
498 499 500 501

		// Container
		$(this.container).empty();
	}
502
}
503 504

registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
B
Benjamin Pasero 已提交
505 506

	// Foreground
B
Benjamin Pasero 已提交
507
	const windowForeground = theme.getColor(foreground);
508 509 510
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
511

512 513 514 515 516 517
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

518 519 520 521 522 523 524
	// Input placeholder
	const placeholderForeground = theme.getColor(inputPlaceholderForeground);
	if (placeholderForeground) {
		collector.addRule(`.monaco-shell input::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
		collector.addRule(`.monaco-shell textarea::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
	}

525 526 527 528 529 530 531 532 533 534 535
	// List highlight
	const listHighlightForegroundColor = theme.getColor(listHighlightForeground);
	if (listHighlightForegroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
			.monaco-shell .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
				color: ${listHighlightForegroundColor};
			}
		`);
	}

B
Benjamin Pasero 已提交
536
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
537 538 539 540 541 542 543 544 545 546 547 548 549
	let workbenchBackground: string;
	switch (theme.type) {
		case 'dark':
			workbenchBackground = '#252526';
			break;
		case 'light':
			workbenchBackground = '#F3F3F3';
			break;
		default:
			workbenchBackground = '#000000';
	}
	collector.addRule(`.monaco-workbench { background-color: ${workbenchBackground}; }`);

B
Benjamin Pasero 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
	// Scrollbars
	const scrollbarShadowColor = theme.getColor(scrollbarShadow);
	if (scrollbarShadowColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .shadow.top {
				box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.left {
				box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.top.left {
				box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
			}
		`);
	}

	const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);
	if (scrollbarSliderBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider {
				background: ${scrollbarSliderBackgroundColor};
			}
		`);
	}

	const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);
	if (scrollbarSliderHoverBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider:hover {
				background: ${scrollbarSliderHoverBackgroundColor};
			}
		`);
	}

	const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);
	if (scrollbarSliderActiveBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider.active {
				background: ${scrollbarSliderActiveBackgroundColor};
			}
		`);
	}

	// Focus outline
596
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
597 598 599 600 601 602 603 604
	if (focusOutline) {
		collector.addRule(`
			.monaco-shell [tabindex="0"]:focus,
			.monaco-shell .synthetic-focus,
			.monaco-shell select:focus,
			.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
			.monaco-shell input[type="button"]:focus,
			.monaco-shell input[type="text"]:focus,
B
Benjamin Pasero 已提交
605
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
606 607 608 609 610 611 612
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
613
});