shell.ts 24.4 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, Disposables } 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 { stopProfiling } from 'vs/base/node/profiler';
20
import product from 'vs/platform/node/product';
21
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
22
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
23
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
24
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
25
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
26 27
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
28 29 30
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 已提交
31
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
32
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
33 34
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
35
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
36 37 38 39
import { IWindowIPCService, WindowIPCService } from 'vs/workbench/services/window/electron-browser/windowService';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
40
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
41
import { IRequestService } from 'vs/platform/request/node/request';
42
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
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 { MainThreadService } from 'vs/workbench/services/thread/electron-browser/threadService';
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';
import { MainProcessExtensionService } from 'vs/workbench/api/node/mainThreadExtensionService';
import { IOptions } from 'vs/workbench/common/options';
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
59
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
60 61 62 63 64 65 66 67 68 69 70 71
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
72
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
73
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
74
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
75 76 77
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { CrashReporter } from 'vs/workbench/electron-browser/crashReporter';
78
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
79 80
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
81
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
82
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
83 84
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
85 86
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
87 88
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
89 90
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
J
Joao Moreno 已提交
91
import { ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
92
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
93
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
94
import { remote, ipcRenderer as ipc } from 'electron';
A
Alex Dima 已提交
95
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
96
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
97
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
98 99
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
100
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview';
101 102
import { readdir } from 'vs/base/node/pfs';
import { join } from 'path';
103
import 'vs/platform/opener/browser/opener.contribution';
B
Benjamin Pasero 已提交
104 105
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/themeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/themeService';
106 107
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { WINDOW_FOREGROUND } from 'vs/workbench/common/theme';
108

109 110 111 112 113 114
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
115
	environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
116
	timerService: ITimerService;
117 118
}

119 120
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
121
/**
B
Benjamin Pasero 已提交
122
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
123 124 125
 * 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 已提交
126
	private storageService: IStorageService;
127
	private messageService: MessageService;
J
Johannes Rieken 已提交
128
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
129 130
	private contextViewService: ContextViewService;
	private threadService: MainThreadService;
131 132
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
133
	private telemetryService: ITelemetryService;
134
	private extensionService: MainProcessExtensionService;
135
	private windowsService: IWindowsService;
136
	private windowIPCService: IWindowIPCService;
B
Benjamin Pasero 已提交
137
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
138
	private themeService: WorkbenchThemeService;
E
Erich Gamma 已提交
139 140

	private container: HTMLElement;
141
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
142 143 144 145 146 147 148 149
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

	private options: IOptions;
	private workbench: Workbench;

150
	constructor(container: HTMLElement, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
151 152
		this.container = container;

153 154 155 156
		this.options = options;

		this.contextService = services.contextService;
		this.configurationService = services.configurationService;
157
		this.environmentService = services.environmentService;
B
Benjamin Pasero 已提交
158
		this.timerService = services.timerService;
E
Erich Gamma 已提交
159 160 161 162 163 164 165

		this.toUnbind = [];
		this.previousErrorTime = 0;
	}

	private createContents(parent: Builder): Builder {

166
		// ARIA
B
Benjamin Pasero 已提交
167
		aria.setARIAContainer(document.body);
168

E
Erich Gamma 已提交
169
		// Workbench Container
170
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
171 172

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

		//crash reporting
176
		if (!!product.crashReporter) {
177
			instantiationService.createInstance(CrashReporter, product.crashReporter);
E
Erich Gamma 已提交
178 179 180
		}

		// Workbench
181
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.options, serviceCollection);
E
Erich Gamma 已提交
182
		this.workbench.startup({
183
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
184 185

				// run workbench started logic
186
				this.onWorkbenchStarted(info);
187 188 189

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
E
Erich Gamma 已提交
190 191 192
			}
		});

193 194 195
		// Window
		const activeWindow = this.workbench.getInstantiationService().createInstance(ElectronWindow, currentWindow, this.container);
		this.windowIPCService.registerWindow(activeWindow);
E
Erich Gamma 已提交
196 197

		// Handle case where workbench is not starting up properly
198
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
199 200 201 202 203 204 205 206 207 208
			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;
	}

209
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
210 211

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
212
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
213 214 215
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
B
Benjamin Pasero 已提交
216
			emptyWorkbench: !this.contextService.hasWorkspace(),
217 218 219
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
220
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
221
			theme: this.themeService.getColorTheme().id,
222
			language: platform.language,
223 224
			experiments: this.telemetryService.getExperiments(),
			pinnedViewlets: info.pinnedViewlets
225 226
		});

B
Benjamin Pasero 已提交
227
		// Telemetry: startup metrics
228
		const workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
229 230 231
		this.timerService.workbenchStarted = new Date(workbenchStarted);
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
232
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
233
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
234
		});
B
Benjamin Pasero 已提交
235

236
		// Telemetry: workspace tags
237
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
238
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
239
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
240 241 242 243

		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'."));
		}
244 245

		// Profiler: startup cpu profile
J
Johannes Rieken 已提交
246 247
		const { profileStartup } = this.environmentService;
		if (profileStartup) {
248

J
Johannes Rieken 已提交
249
			stopProfiling(profileStartup.dir, profileStartup.prefix).then(() => {
250

J
Johannes Rieken 已提交
251 252
				readdir(profileStartup.dir).then(files => {
					return files.filter(value => value.indexOf(profileStartup.prefix) === 0);
253 254
				}).then(files => {

J
Johannes Rieken 已提交
255
					const profileFiles = files.reduce((prev, cur) => `${prev}${join(profileStartup.dir, cur)}\n`, '\n');
256 257 258 259 260 261 262 263 264 265 266 267 268

					const primaryButton = this.messageService.confirm({
						type: 'info',
						message: nls.localize('prof.message', "Successfully created profiles."),
						detail: nls.localize('prof.detail', "Please create an issue and manually attach the following files:\n{0}", profileFiles),
						primaryButton: nls.localize('prof.restartAndFileIssue', "Create Issue and Restart"),
						secondaryButton: nls.localize('prof.restart', "Restart")
					});

					let createIssue = TPromise.as(undefined);
					if (primaryButton) {
						const action = this.workbench.getInstantiationService().createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL);

J
Johannes Rieken 已提交
269 270
						createIssue = action.run(`:warning: Make sure to **attach** these files: :warning:\n${files.map(file => `-\`${join(profileStartup.dir, file)}\``).join('\n')}`).then(() => {
							return this.windowsService.showItemInFolder(profileStartup.dir);
271 272
						});
					}
J
Johannes Rieken 已提交
273
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--prof-startup'] }));
274 275 276 277
				});

			}, err => console.error(err));
		}
B
Benjamin Pasero 已提交
278 279
	}

280
	private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
J
Joao Moreno 已提交
281 282
		const disposables = new Disposables();

283 284 285
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
286
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
287
		serviceCollection.set(ITimerService, this.timerService);
288

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

J
Joao Moreno 已提交
291
		// TODO@joao remove this
292 293
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
294

295
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
296 297
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
298
		const windowsChannel = mainProcessClient.getChannel('windows');
299 300
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
301

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

304 305 306 307 308
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

B
Benjamin Pasero 已提交
310
		// Storage Sevice
B
Benjamin Pasero 已提交
311
		const disableWorkspaceStorage = this.environmentService.extensionTestsPath || (!this.contextService.hasWorkspace() && !this.environmentService.isExtensionDevelopment); // without workspace or in any extension test, we use inMemory storage unless we develop an extension where we want to preserve state
B
Benjamin Pasero 已提交
312
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
313
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
314

315 316 317 318
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

319
		// Telemetry
C
Christof Marti 已提交
320
		this.sendMachineIdToMain(this.storageService);
321
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
322
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
323 324
			const commit = product.commit;
			const version = pkg.version;
325

326
			const config: ITelemetryServiceConfig = {
327
				appender: new TelemetryAppenderClient(channel),
328
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
329
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
C
Christof Marti 已提交
330
				experiments: instantiationService.invokeFunction(loadExperiments)
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 340 341 342
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
343
				));
344

345
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
346
		} else {
C
Christof Marti 已提交
347
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
348
			this.telemetryService = NullTelemetryService;
349
		}
E
Erich Gamma 已提交
350

351
		serviceCollection.set(ITelemetryService, this.telemetryService);
352
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
353

354
		this.messageService = instantiationService.createInstance(MessageService, container);
355
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
356
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
357

358
		const lifecycleService = instantiationService.createInstance(LifecycleService);
359
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
360
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
361
		serviceCollection.set(ILifecycleService, lifecycleService);
362
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
363

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

367 368 369
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
370

371
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
372
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
373
		serviceCollection.set(IThreadService, this.threadService);
374

B
Benjamin Pasero 已提交
375
		this.timerService.beforeExtensionLoad = new Date();
376 377 378 379

		// TODO@Joao: remove
		const disabledExtensions = SCMPreview.enabled ? [] : ['vscode.git'];
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService, disabledExtensions);
380 381 382
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
383
			this.timerService.afterExtensionLoad = new Date();
384
		});
E
Erich Gamma 已提交
385

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

389
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
390

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

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

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

398
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
399

400
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
401

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

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

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

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

J
Joao Moreno 已提交
414
		const updateChannel = mainProcessClient.getChannel('update');
415
		serviceCollection.set(IUpdateService, new SyncDescriptor(UpdateChannelClient, updateChannel));
J
Joao Moreno 已提交
416

J
Joao Moreno 已提交
417
		const urlChannel = mainProcessClient.getChannel('url');
418
		serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, this.windowIPCService.getWindowId()));
J
Joao Moreno 已提交
419

420
		const backupChannel = mainProcessClient.getChannel('backup');
421
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
422

423
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
424 425
	}

C
Christof Marti 已提交
426 427 428 429 430 431
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
	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 {
462
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
463 464 465 466
		if (!errorMsg) {
			return;
		}

467
		const now = Date.now();
E
Erich Gamma 已提交
468 469 470 471 472 473 474 475 476 477 478
		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
479
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
480
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
481 482 483
		}
	}

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

487
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
488 489
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
490
		this.contextViewService.layout();
E
Erich Gamma 已提交
491 492 493 494 495 496 497
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
498
	public dispose(): void {
E
Erich Gamma 已提交
499 500 501

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
502
			this.workbench.dispose();
E
Erich Gamma 已提交
503 504
		}

B
Benjamin Pasero 已提交
505
		this.contextViewService.dispose();
E
Erich Gamma 已提交
506 507

		// Listeners
J
Joao Moreno 已提交
508
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
509 510 511 512

		// Container
		$(this.container).empty();
	}
513
}
514 515 516 517 518 519 520

registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
	const windowForeground = theme.getColor(WINDOW_FOREGROUND);
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
});