shell.ts 27.0 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
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import product from 'vs/platform/node/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
23
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
24
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
25
import { NullTelemetryService, configurationTelemetry, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
26
import { IExperimentService, ExperimentService } from 'vs/platform/telemetry/common/experiments';
J
Johannes Rieken 已提交
27 28 29
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 已提交
30
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
31
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
32 33
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
34
import { WorkspaceStats } from 'vs/workbench/services/telemetry/node/workspaceStats';
35
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
36
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
37
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
38
import { IRequestService } from 'vs/platform/request/node/request';
39
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
40 41 42 43 44 45 46 47 48 49 50 51
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';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
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';
52
import { ExtensionService } from 'vs/workbench/services/extensions/electron-browser/extensionService';
J
Johannes Rieken 已提交
53
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
54
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
55 56 57
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 已提交
58
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
59 60
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
61
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
62 63 64 65
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';
66
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
67
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
68
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
69 70
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
71
import { ICrashReporterService, NullCrashReporterService, CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
72
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
73 74 75
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';
76 77
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
B
Benjamin Pasero 已提交
78
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
79
import { remote, ipcRenderer as ipc } from 'electron';
80
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
81 82
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
83
import 'vs/platform/opener/browser/opener.contribution';
84 85
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
86 87
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
88
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
89
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
90 91
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
92
import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService';
B
Benjamin Pasero 已提交
93 94
import { HashService } from 'vs/workbench/services/hash/node/hashService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
95

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

107 108
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
109
/**
B
Benjamin Pasero 已提交
110
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
111 112 113
 * 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 已提交
114
	private storageService: IStorageService;
115
	private messageService: MessageService;
J
Johannes Rieken 已提交
116
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
117
	private contextViewService: ContextViewService;
118 119
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
120
	private telemetryService: ITelemetryService;
121
	private experimentService: IExperimentService;
122
	private extensionService: ExtensionService;
123
	private broadcastService: IBroadcastService;
B
Benjamin Pasero 已提交
124
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
125
	private themeService: WorkbenchThemeService;
126
	private lifecycleService: LifecycleService;
127 128
	private mainProcessServices: ServiceCollection;

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

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

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

142
		this.configuration = configuration;
143

B
Benjamin Pasero 已提交
144 145 146 147 148
		this.contextService = coreServices.contextService;
		this.configurationService = coreServices.configurationService;
		this.environmentService = coreServices.environmentService;
		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 170 171
		try {
			this.workbench.startup({
				onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
172

173 174
					// run workbench started logic
					this.onWorkbenchStarted(info);
175

176 177
					// start cached data manager
					instantiationService.createInstance(NodeCachedDataManager);
178

179 180 181 182 183 184 185 186 187 188 189 190 191
					// Set lifecycle phase to `Runnning` so that other contributions
					// can now do something
					this.lifecycleService.phase = LifecyclePhase.Running;
				}
			});
		} catch (error) {

			// Print out error
			console.error(toErrorMessage(error, true));

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

193
		// Window
194
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
195 196

		// Handle case where workbench is not starting up properly
197
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
198 199 200 201 202 203 204 205 206 207
			console.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
		}, 10000);

		this.workbench.joinCreation().then(() => {
			clearTimeout(timeoutHandle);
		});

		return workbenchContainer;
	}

B
Benjamin Pasero 已提交
208
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
209 210

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
211
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;
K
kieferrm 已提交
212
		/* __GDPR__
K
kieferrm 已提交
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
			"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" }
			}
		*/
234 235 236
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
237
			emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY,
238 239 240
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0,
241
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
242
			theme: this.themeService.getColorTheme().id,
243
			language: platform.language,
244
			experiments: this.experimentService.getExperiments(),
245 246
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
247 248
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
249 250
		});

B
Benjamin Pasero 已提交
251
		// Telemetry: startup metrics
252
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
253 254
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
255
		this.extensionService.onReady().done(() => {
K
kieferrm 已提交
256
			/* __GDPR__
K
kieferrm 已提交
257 258 259 260 261 262
				"startupTime" : {
					"${include}": [
						"${IStartupMetrics}"
					]
				}
			*/
B
Benjamin Pasero 已提交
263
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
264
		});
B
Benjamin Pasero 已提交
265

266
		// Telemetry: workspace tags
267
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
B
Benjamin Pasero 已提交
268
		workspaceStats.reportWorkspaceTags(this.configuration);
K
kieferrm 已提交
269
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
270 271 272 273

		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'."));
		}
B
Benjamin Pasero 已提交
274 275
	}

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

279 280 281
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
282
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
283
		serviceCollection.set(ITimerService, this.timerService);
284
		serviceCollection.set(IStorageService, this.storageService);
285 286 287
		this.mainProcessServices.forEach((serviceIdentifier, serviceInstance) => {
			serviceCollection.set(serviceIdentifier, serviceInstance);
		});
288

289
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
290

291 292
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
293

294
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id));
J
Joao Moreno 已提交
295

296
		const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
297
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
298 299 300

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

302 303 304 305
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

B
Benjamin Pasero 已提交
306 307 308
		// Hash
		serviceCollection.set(IHashService, new SyncDescriptor(HashService));

309 310 311 312
		// Experiments
		this.experimentService = instantiationService.createInstance(ExperimentService);
		serviceCollection.set(IExperimentService, this.experimentService);

313
		// Telemetry
C
Christof Marti 已提交
314
		this.sendMachineIdToMain(this.storageService);
315
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
316
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
317 318
			const commit = product.commit;
			const version = pkg.version;
319

320
			const config: ITelemetryServiceConfig = {
321
				appender: new TelemetryAppenderClient(channel),
322
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version, this.environmentService.installSource),
323
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
324
			};
325

J
Joao Moreno 已提交
326
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
327 328
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
329
			const errorTelemetry = new ErrorTelemetry(telemetryService);
330
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
331

332
			const listener = idleMonitor.onStatusChange(status =>
K
kieferrm 已提交
333
				/* __GDPR__
K
kieferrm 已提交
334 335
					"UserIdleStart" : {}
				*/
K
kieferrm 已提交
336
				/* __GDPR__
K
kieferrm 已提交
337 338
					"UserIdleStop" : {}
				*/
339 340 341
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
342
				));
343

J
Johannes Rieken 已提交
344
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
345
		} else {
346
			this.telemetryService = NullTelemetryService;
347
		}
E
Erich Gamma 已提交
348

349
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
350
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
351

352
		let crashReporterService = NullCrashReporterService;
353
		if (!this.environmentService.disableCrashReporter && product.crashReporter && product.hockeyApp) {
354 355 356 357
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

358
		this.messageService = instantiationService.createInstance(MessageService, container);
359
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
360
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
361

362
		const lifecycleService = instantiationService.createInstance(LifecycleService);
J
Johannes Rieken 已提交
363
		this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
364
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
365
		serviceCollection.set(ILifecycleService, lifecycleService);
J
Johannes Rieken 已提交
366
		disposables.push(lifecycleTelemetry(this.telemetryService, lifecycleService));
367
		this.lifecycleService = lifecycleService;
368

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

372 373
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
374
		disposables.push(extensionEnablementService);
375

376
		this.extensionService = instantiationService.createInstance(ExtensionService);
377
		serviceCollection.set(IExtensionService, this.extensionService);
378 379

		this.timerService.beforeExtensionLoad = Date.now();
380
		this.extensionService.onReady().done(() => {
381
			this.timerService.afterExtensionLoad = Date.now();
382
		});
E
Erich Gamma 已提交
383

B
Benjamin Pasero 已提交
384 385 386
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

387
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
388

389 390
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
391

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

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

396
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
397

398
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
399

400 401
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

402
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
403

404
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
405

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

408
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
409

410
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
411

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

414
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
415 416
	}

C
Christof Marti 已提交
417 418 419 420 421 422
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
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
	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 {
453
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
454 455 456 457
		if (!errorMsg) {
			return;
		}

458
		const now = Date.now();
E
Erich Gamma 已提交
459 460 461 462 463 464 465 466 467 468 469
		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;

		// Log to console
		console.error(errorMsg);

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

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

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

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

	public joinCreation(): TPromise<boolean> {
		return this.workbench.joinCreation();
	}

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

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

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

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

		// Container
		$(this.container).empty();
	}
504
}
505 506

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

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

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

520 521 522 523 524 525 526
	// 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}; }`);
	}

527 528 529 530 531 532 533 534 535 536 537
	// 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 已提交
538
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
539 540 541 542 543 544 545 546 547 548 549 550 551
	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 已提交
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 596 597
	// 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
598
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
599 600 601 602 603 604 605 606
	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 已提交
607
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
608 609 610 611 612 613 614
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
615
});