shell.ts 24.9 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 product from 'vs/platform/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
E
Erich Gamma 已提交
23
import timer = require('vs/base/common/timer');
24
import { IStartupFingerprint, IMemoryInfo } from 'vs/workbench/electron-browser/common';
25
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
B
Benjamin Pasero 已提交
26
import { StorageService, inMemoryLocalStorageInstance } from 'vs/workbench/services/storage/common/storageService';
27
import { ITelemetryService, NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetry';
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';
J
Johannes Rieken 已提交
33 34
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
35 36 37 38
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 已提交
39
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
40
import { IRequestService } from 'vs/platform/request/node/request';
41
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
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 已提交
58
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72
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 { IEventService } from 'vs/platform/event/common/event';
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';
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
73
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
J
Johannes Rieken 已提交
74 75 76 77
import { MainThreadModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
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 81 82
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ThemeService } from 'vs/workbench/services/themes/electron-browser/themeService';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
83
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
84
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
85 86
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
87 88
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
89 90
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
91 92
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
J
Johannes Rieken 已提交
93
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
94
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
95
import { remote } from 'electron';
96
import * as os from 'os';
97 98

// self registering services
99
import 'vs/platform/opener/browser/opener.contribution';
100

101 102 103 104 105 106 107
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	eventService: IEventService;
	configurationService: IConfigurationService;
108
	environmentService: IEnvironmentService;
109 110
}

111 112
const timers = (<any>window).MonacoEnvironment.timers;

113 114
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
115
/**
B
Benjamin Pasero 已提交
116
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
117 118 119
 * 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 已提交
120
	private storageService: IStorageService;
121
	private messageService: MessageService;
122
	private eventService: IEventService;
J
Johannes Rieken 已提交
123
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
124 125
	private contextViewService: ContextViewService;
	private threadService: MainThreadService;
126
	private configurationService: IConfigurationService;
M
Martin Aeschlimann 已提交
127
	private themeService: ThemeService;
128
	private contextService: IWorkspaceContextService;
129
	private telemetryService: ITelemetryService;
130
	private extensionService: MainProcessExtensionService;
131
	private windowIPCService: IWindowIPCService;
E
Erich Gamma 已提交
132 133

	private container: HTMLElement;
134
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
135 136 137 138 139 140 141 142 143
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

	private workspace: IWorkspace;
	private options: IOptions;
	private workbench: Workbench;

144
	constructor(container: HTMLElement, workspace: IWorkspace, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
145 146 147
		this.container = container;

		this.workspace = workspace;
148 149 150 151 152
		this.options = options;

		this.contextService = services.contextService;
		this.eventService = services.eventService;
		this.configurationService = services.configurationService;
153
		this.environmentService = services.environmentService;
E
Erich Gamma 已提交
154 155 156 157 158 159 160

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

	private createContents(parent: Builder): Builder {

161
		// ARIA
B
Benjamin Pasero 已提交
162
		aria.setARIAContainer(document.body);
163

E
Erich Gamma 已提交
164
		// Workbench Container
165
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
166 167

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

		//crash reporting
171
		if (!!product.crashReporter) {
172
			instantiationService.createInstance(CrashReporter, product.crashReporter);
E
Erich Gamma 已提交
173 174 175
		}

		// Workbench
B
Benjamin Pasero 已提交
176
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.workspace, this.options, serviceCollection);
E
Erich Gamma 已提交
177
		this.workbench.startup({
178
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
179 180

				// run workbench started logic
181
				this.onWorkbenchStarted(info);
182 183 184

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
E
Erich Gamma 已提交
185 186 187
			}
		});

188 189 190
		// Window
		const activeWindow = this.workbench.getInstantiationService().createInstance(ElectronWindow, currentWindow, this.container);
		this.windowIPCService.registerWindow(activeWindow);
E
Erich Gamma 已提交
191 192

		// Handle case where workbench is not starting up properly
193
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
194 195 196 197 198 199 200 201 202 203
			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;
	}

204
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
205 206 207 208 209

		// Log to timer
		timer.start(timer.Topic.STARTUP, '[renderer] overall workbench load', timers.perfBeforeWorkbenchOpen, 'Workbench has opened after this event with viewlet and editor restored').stop();

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

		// Telemetry: performance info
		const workbenchStarted = Date.now();
		timers.workbenchStarted = new Date(workbenchStarted);
		this.extensionService.onReady().done(() => {
229
			const now = Date.now();
230 231 232
			const initialStartup = !!timers.isInitialStartup;
			const start = initialStartup ? timers.perfStartTime : timers.perfWindowLoadTime;
			let totalmem: number;
B
Benjamin Pasero 已提交
233
			let freemem: number;
234
			let cpus: { count: number; speed: number; model: string; };
B
Benjamin Pasero 已提交
235 236
			let platform: string;
			let release: string;
237 238
			let loadavg: number[];
			let meminfo: IMemoryInfo;
239 240 241

			try {
				totalmem = os.totalmem();
B
Benjamin Pasero 已提交
242 243 244
				freemem = os.freemem();
				platform = os.platform();
				release = os.release();
245 246
				loadavg = os.loadavg();
				meminfo = process.getProcessMemoryInfo();
247 248 249 250 251 252 253 254 255 256

				const rawCpus = os.cpus();
				if (rawCpus && rawCpus.length > 0) {
					cpus = { count: rawCpus.length, speed: rawCpus[0].speed, model: rawCpus[0].model };
				}
			} catch (error) {
				console.error(error); // be on the safe side with these hardware method calls
			}

			const startupTimeEvent: IStartupFingerprint = {
257
				version: 1,
258 259 260
				ellapsed: Math.round(workbenchStarted - start),
				timers: {
					ellapsedExtensions: Math.round(timers.perfAfterExtensionLoad - timers.perfBeforeExtensionLoad),
261
					ellapsedExtensionsReady: Math.round(timers.perfAfterExtensionLoad - start),
262
					ellapsedRequire: Math.round(timers.perfAfterLoadWorkbenchMain - timers.perfBeforeLoadWorkbenchMain),
263 264
					ellapsedViewletRestore: Math.round(info.restoreViewletDuration),
					ellapsedEditorRestore: Math.round(info.restoreEditorsDuration),
265
					ellapsedWorkbench: Math.round(workbenchStarted - timers.perfBeforeWorkbenchOpen),
266 267
					ellapsedWindowLoadToRequire: Math.round(timers.perfBeforeLoadWorkbenchMain - timers.perfWindowLoadTime),
					ellapsedTimersToTimersComputed: Date.now() - now
268
				},
B
Benjamin Pasero 已提交
269 270
				platform,
				release,
271
				totalmem,
B
Benjamin Pasero 已提交
272
				freemem,
273
				meminfo,
274
				cpus,
275
				loadavg,
276 277 278 279 280 281
				initialStartup,
				hasAccessibilitySupport: !!timers.hasAccessibilitySupport,
				emptyWorkbench: !this.contextService.getWorkspace()
			};

			if (initialStartup) {
282
				startupTimeEvent.timers.ellapsedWindowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
283 284 285 286 287
			}

			this.telemetryService.publicLog('startupTime', startupTimeEvent);
			timers.fingerprint = startupTimeEvent;
		});
B
Benjamin Pasero 已提交
288

289
		// Telemetry: workspace tags
290
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
291
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
292
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
293 294 295 296

		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 已提交
297 298
	}

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

302 303 304 305
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
306
		serviceCollection.set(IEnvironmentService, this.environmentService);
307

308
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
309

J
Joao Moreno 已提交
310
		// TODO@joao remove this
311 312
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
313

314
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
315 316
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
317
		const windowsChannel = mainProcessClient.getChannel('windows');
318
		serviceCollection.set(IWindowsService, new SyncDescriptor(WindowsChannelClient, windowsChannel));
J
Joao Moreno 已提交
319

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

322
		const sharedProcess = connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`);
323
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
324

325 326
			// Choice channel
			client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel));
S
Sandeep Somavarapu 已提交
327

328 329 330 331 332 333 334 335
			client.onClose(() => {
				this.messageService.show(Severity.Error, {
					message: nls.localize('sharedProcessCrashed', "The shared process terminated unexpectedly. Please reload the window to recover."),
					actions: [instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL)]
				});
			});
		}, errors.onUnexpectedError);

B
Benjamin Pasero 已提交
336
		// Storage Sevice
337
		const disableWorkspaceStorage = this.environmentService.extensionTestsPath || (!this.workspace && !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 已提交
338
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
339
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
340

341
		// Telemetry
342
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
343
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
344 345
			const commit = product.commit;
			const version = pkg.version;
346

347
			const config: ITelemetryServiceConfig = {
348
				appender: new TelemetryAppenderClient(channel),
349
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
350
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
351
				experiments: loadExperiments(this.contextService, this.storageService, this.configurationService)
352
			};
353

J
Joao Moreno 已提交
354
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
355 356
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
357
			const errorTelemetry = new ErrorTelemetry(telemetryService);
358
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
359

360 361 362 363
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
364
				));
365

366
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
367
		} else {
368
			NullTelemetryService._experiments = loadExperiments(this.contextService, this.storageService, this.configurationService);
369
			this.telemetryService = NullTelemetryService;
370
		}
E
Erich Gamma 已提交
371

372
		serviceCollection.set(ITelemetryService, this.telemetryService);
373
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
374

375
		this.messageService = instantiationService.createInstance(MessageService, container);
376
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
377
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
378

379
		const lifecycleService = instantiationService.createInstance(LifecycleService);
380
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
381
		serviceCollection.set(ILifecycleService, lifecycleService);
382
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
383

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

387 388 389
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
390

391
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
392
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
393
		serviceCollection.set(IThreadService, this.threadService);
394

395 396 397 398 399 400 401 402 403
		const extensionTimer = timer.start(timer.Topic.STARTUP, '[renderer] create extension host => extensions onReady()');
		timers.perfBeforeExtensionLoad = new Date();
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
			extensionTimer.stop();
			timers.perfAfterExtensionLoad = new Date();
		});
E
Erich Gamma 已提交
404

405
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
406

407 408
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
409

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

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

414
		serviceCollection.set(IModeService, new SyncDescriptor(MainThreadModeServiceImpl));
415

416
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
417

418
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
419

420
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
421 422

		this.themeService = instantiationService.createInstance(ThemeService);
423
		serviceCollection.set(IThemeService, this.themeService);
424

425
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
426

427
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
428

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

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

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

437
		const backupChannel = mainProcessClient.getChannel('backup');
438
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
439

440
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
	}

	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();

		// Handle Load Performance Timers
		this.writeTimers();

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

		// Layout
		this.layout();

		// Listeners
		this.registerListeners();

		// Enable theme support
M
Martin Aeschlimann 已提交
469
		this.themeService.initialize(this.container).then(null, error => {
470 471
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
472 473 474 475 476 477 478 479 480
	}

	private registerListeners(): void {

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

	private writeTimers(): void {
481
		const events: timer.IExistingTimerEvent[] = [];
E
Erich Gamma 已提交
482

483 484
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
485
			events.push({
486 487
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
488
				topic: 'Startup',
489 490
				name: '[main] initial start => begin to require(workbench.main.js)',
				description: 'Time spend in main process until we load JavaScript of the workbench'
E
Erich Gamma 已提交
491
			});
492
		}
E
Erich Gamma 已提交
493

494 495 496 497 498 499 500 501
		// Load
		events.push({
			startTime: timers.perfBeforeLoadWorkbenchMain,
			stopTime: timers.perfAfterLoadWorkbenchMain,
			topic: 'Startup',
			name: '[renderer] require(workbench.main.js)',
			description: 'Time it takes to load VSCodes main modules'
		});
E
Erich Gamma 已提交
502

503 504 505 506 507 508 509 510 511 512 513
		// Ready
		events.push({
			startTime: timers.perfBeforeDOMContentLoaded,
			stopTime: timers.perfAfterDOMContentLoaded,
			topic: 'Startup',
			name: '[renderer] event DOMContentLoaded',
			description: 'Time it takes for the DOM to emit DOMContentLoaded event'
		});

		// Write to Timer
		timer.getTimeKeeper().setInitialCollectedEvents(events, timers.start);
E
Erich Gamma 已提交
514 515 516
	}

	public onUnexpectedError(error: any): void {
517
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
518 519 520 521
		if (!errorMsg) {
			return;
		}

522
		const now = Date.now();
E
Erich Gamma 已提交
523 524 525 526 527 528 529 530 531 532 533
		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
534
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
535
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
536 537 538
		}
	}

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

542
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
543 544
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
545
		this.contextViewService.layout();
E
Erich Gamma 已提交
546 547 548 549 550 551 552
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
553
	public dispose(): void {
E
Erich Gamma 已提交
554 555 556

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
557
			this.workbench.dispose();
E
Erich Gamma 已提交
558 559
		}

B
Benjamin Pasero 已提交
560
		this.contextViewService.dispose();
E
Erich Gamma 已提交
561 562

		// Listeners
J
Joao Moreno 已提交
563
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
564 565 566 567

		// Container
		$(this.container).empty();
	}
568
}