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 20
import product from 'vs/platform/product';
import pkg from 'vs/platform/package';
J
Johannes Rieken 已提交
21
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
E
Erich Gamma 已提交
22
import timer = require('vs/base/common/timer');
23
import { IStartupFingerprint, IMemoryInfo } from 'vs/workbench/electron-browser/common';
J
Johannes Rieken 已提交
24
import { Workbench } from 'vs/workbench/electron-browser/workbench';
B
Benjamin Pasero 已提交
25
import { StorageService, inMemoryLocalStorageInstance } from 'vs/workbench/services/storage/common/storageService';
26
import { ITelemetryService, NullTelemetryService, configurationTelemetry, loadExperiments } from 'vs/platform/telemetry/common/telemetry';
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';
J
Johannes Rieken 已提交
31 32 33
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { ElectronIntegration } from 'vs/workbench/electron-browser/integration';
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
34 35 36 37
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 已提交
38
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
39
import { IRequestService } from 'vs/platform/request/node/request';
40
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
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 已提交
57
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
58 59 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 { 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';
72
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
J
Johannes Rieken 已提交
73 74 75 76 77 78 79 80
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';
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';
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 89
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
90
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
91
import { remote } from 'electron';
92
import * as os from 'os';
93 94

// self registering services
95
import 'vs/platform/opener/browser/opener.contribution';
96

97 98 99 100 101 102 103
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	eventService: IEventService;
	configurationService: IConfigurationService;
104
	environmentService: IEnvironmentService;
105 106
}

107 108
const timers = (<any>window).MonacoEnvironment.timers;

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;
116
	private eventService: IEventService;
J
Johannes Rieken 已提交
117
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
118 119
	private contextViewService: ContextViewService;
	private threadService: MainThreadService;
120
	private configurationService: IConfigurationService;
M
Martin Aeschlimann 已提交
121
	private themeService: ThemeService;
122
	private contextService: IWorkspaceContextService;
123
	private telemetryService: ITelemetryService;
124
	private extensionService: MainProcessExtensionService;
E
Erich Gamma 已提交
125 126

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

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

137
	constructor(container: HTMLElement, workspace: IWorkspace, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
138 139 140
		this.container = container;

		this.workspace = workspace;
141 142 143 144 145
		this.options = options;

		this.contextService = services.contextService;
		this.eventService = services.eventService;
		this.configurationService = services.configurationService;
146
		this.environmentService = services.environmentService;
E
Erich Gamma 已提交
147 148 149 150 151 152 153

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

	private createContents(parent: Builder): Builder {

154
		// ARIA
B
Benjamin Pasero 已提交
155
		aria.setARIAContainer(document.body);
156

E
Erich Gamma 已提交
157
		// Workbench Container
158
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
159 160

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

		//crash reporting
164
		if (!!product.crashReporter) {
165
			instantiationService.createInstance(CrashReporter, product.crashReporter);
E
Erich Gamma 已提交
166 167 168
		}

		// Workbench
B
Benjamin Pasero 已提交
169
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.workspace, this.options, serviceCollection);
E
Erich Gamma 已提交
170
		this.workbench.startup({
171 172
			onWorkbenchStarted: (customKeybindingsCount, restoreViewletDuration, restoreEditorsDuration) => {
				this.onWorkbenchStarted(customKeybindingsCount, restoreViewletDuration, restoreEditorsDuration);
E
Erich Gamma 已提交
173 174 175 176 177 178 179
			}
		});

		// Electron integration
		this.workbench.getInstantiationService().createInstance(ElectronIntegration).integrate(this.container);

		// Handle case where workbench is not starting up properly
180
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
181 182 183 184 185 186 187 188 189 190
			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;
	}

191 192 193 194 195 196
	private onWorkbenchStarted(customKeybindingsCount: number, restoreViewletDuration: number, restoreEditorsDuration: number): void {

		// 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 已提交
197
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
198 199 200 201
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
			emptyWorkbench: !this.contextService.getWorkspace(),
202 203 204
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
205 206 207 208 209 210 211 212 213 214
			customKeybindingsCount,
			theme: this.themeService.getColorTheme(),
			language: platform.language,
			experiments: this.telemetryService.getExperiments()
		});

		// Telemetry: performance info
		const workbenchStarted = Date.now();
		timers.workbenchStarted = new Date(workbenchStarted);
		this.extensionService.onReady().done(() => {
215
			const now = Date.now();
216 217 218
			const initialStartup = !!timers.isInitialStartup;
			const start = initialStartup ? timers.perfStartTime : timers.perfWindowLoadTime;
			let totalmem: number;
B
Benjamin Pasero 已提交
219
			let freemem: number;
220
			let cpus: { count: number; speed: number; model: string; };
B
Benjamin Pasero 已提交
221 222
			let platform: string;
			let release: string;
223 224
			let loadavg: number[];
			let meminfo: IMemoryInfo;
225 226 227

			try {
				totalmem = os.totalmem();
B
Benjamin Pasero 已提交
228 229 230
				freemem = os.freemem();
				platform = os.platform();
				release = os.release();
231 232
				loadavg = os.loadavg();
				meminfo = process.getProcessMemoryInfo();
233 234 235 236 237 238 239 240 241 242

				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 = {
243
				version: 1,
244 245 246
				ellapsed: Math.round(workbenchStarted - start),
				timers: {
					ellapsedExtensions: Math.round(timers.perfAfterExtensionLoad - timers.perfBeforeExtensionLoad),
247
					ellapsedExtensionsReady: Math.round(timers.perfAfterExtensionLoad - start),
248 249 250
					ellapsedRequire: Math.round(timers.perfAfterLoadWorkbenchMain - timers.perfBeforeLoadWorkbenchMain),
					ellapsedViewletRestore: Math.round(restoreViewletDuration),
					ellapsedEditorRestore: Math.round(restoreEditorsDuration),
251
					ellapsedWorkbench: Math.round(workbenchStarted - timers.perfBeforeWorkbenchOpen),
252 253
					ellapsedWindowLoadToRequire: Math.round(timers.perfBeforeLoadWorkbenchMain - timers.perfWindowLoadTime),
					ellapsedTimersToTimersComputed: Date.now() - now
254
				},
B
Benjamin Pasero 已提交
255 256
				platform,
				release,
257
				totalmem,
B
Benjamin Pasero 已提交
258
				freemem,
259
				meminfo,
260
				cpus,
261
				loadavg,
262 263 264 265 266 267
				initialStartup,
				hasAccessibilitySupport: !!timers.hasAccessibilitySupport,
				emptyWorkbench: !this.contextService.getWorkspace()
			};

			if (initialStartup) {
268
				startupTimeEvent.timers.ellapsedWindowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
269 270 271 272 273
			}

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

275
		// Telemetry: workspace tags
276
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
277
		workspaceStats.reportWorkspaceTags(this.options);
J
Joao Moreno 已提交
278 279 280 281

		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 已提交
282 283
	}

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

287
		const mainProcessClient = new ElectronIPCClient(String(`window${remote.getCurrentWindow().id}`));
J
Joao Moreno 已提交
288
		disposables.add(mainProcessClient);
J
Joao Moreno 已提交
289

290 291 292 293
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
294
		serviceCollection.set(IEnvironmentService, this.environmentService);
295

J
Joao Moreno 已提交
296 297
		const instantiationServiceImpl = new InstantiationService(serviceCollection, true);
		const instantiationService = instantiationServiceImpl as IInstantiationService;
298

J
Joao Moreno 已提交
299 300 301
		// TODO@joao remove this
		const windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, windowIPCService);
302

J
Joao Moreno 已提交
303 304 305 306 307 308 309 310
		const windowsChannel = mainProcessClient.getChannel('windows');
		const windowsChannelClient = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, windowsChannelClient);

		const windowService = new WindowService(windowIPCService.getWindowId(), windowsChannelClient);
		serviceCollection.set(IWindowService, windowService);

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

			client.registerChannel('choice', new ChoiceChannel(this.messageService));

315 316 317 318 319 320 321 322
			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 已提交
323
		// Storage Sevice
324
		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 已提交
325
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
326
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
327

328
		// Telemetry
329
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
330
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
331 332
			const commit = product.commit;
			const version = pkg.version;
333

334
			const config: ITelemetryServiceConfig = {
335
				appender: new TelemetryAppenderClient(channel),
336
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
337
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
338
				experiments: loadExperiments(this.contextService, this.storageService, this.configurationService)
339
			};
340

J
Joao Moreno 已提交
341
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
342 343
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
344
			const errorTelemetry = new ErrorTelemetry(telemetryService);
345
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
346

347 348 349 350
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
351
				));
352

353
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
354
		} else {
355
			NullTelemetryService._experiments = loadExperiments(this.contextService, this.storageService, this.configurationService);
356
			this.telemetryService = NullTelemetryService;
357
		}
E
Erich Gamma 已提交
358

359
		serviceCollection.set(ITelemetryService, this.telemetryService);
360
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
361

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

366
		const lifecycleService = instantiationService.createInstance(LifecycleService);
367
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
368
		serviceCollection.set(ILifecycleService, lifecycleService);
369

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

374 375 376
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
377

378
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
379
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
380
		serviceCollection.set(IThreadService, this.threadService);
381

382 383 384 385 386 387 388 389 390
		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 已提交
391

392
		serviceCollection.set(ICommandService, new CommandService(instantiationService, this.extensionService));
393

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

J
Joao Moreno 已提交
397
		const requestService = instantiationService.createInstance(RequestService);
398
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
399

400
		const markerService = instantiationService.createInstance(MarkerService);
401
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
402

403
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
404
		serviceCollection.set(IModeService, modeService);
405

406
		const modelService = instantiationService.createInstance(ModelServiceImpl);
407
		serviceCollection.set(IModelService, modelService);
408

409
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
410
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
411

412
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
413 414 415
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

		this.themeService = instantiationService.createInstance(ThemeService);
416
		serviceCollection.set(IThemeService, this.themeService);
417

418
		const searchService = instantiationService.createInstance(SearchService);
419 420
		serviceCollection.set(ISearchService, searchService);

J
Joao Moreno 已提交
421
		const codeEditorService = instantiationServiceImpl.createInstance(CodeEditorServiceImpl);
422 423
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
424 425 426
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

J
Joao Moreno 已提交
427 428 429 430
		const updateChannel = mainProcessClient.getChannel('update');
		const updateChannelClient = new UpdateChannelClient(updateChannel);
		serviceCollection.set(IUpdateService, updateChannelClient);

J
Joao Moreno 已提交
431
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
432
		const urlChannelClient = new URLChannelClient(urlChannel, windowIPCService.getWindowId());
J
Joao Moreno 已提交
433 434
		serviceCollection.set(IURLService, urlChannelClient);

J
Joao Moreno 已提交
435
		return [instantiationServiceImpl, serviceCollection];
E
Erich Gamma 已提交
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 462 463
	}

	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 已提交
464
		this.themeService.initialize(this.container).then(null, error => {
465 466
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
467 468 469 470 471 472 473 474 475
	}

	private registerListeners(): void {

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

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

478 479
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
480
			events.push({
481 482
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
483
				topic: 'Startup',
484 485
				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 已提交
486
			});
487
		}
E
Erich Gamma 已提交
488

489 490 491 492 493 494 495 496
		// 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 已提交
497

498 499 500 501 502 503 504 505 506 507 508
		// 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 已提交
509 510 511
	}

	public onUnexpectedError(error: any): void {
512
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
513 514 515 516
		if (!errorMsg) {
			return;
		}

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

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

537
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
538 539
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
540
		this.contextViewService.layout();
E
Erich Gamma 已提交
541 542 543 544 545 546 547
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
548
	public dispose(): void {
E
Erich Gamma 已提交
549 550 551

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
552
			this.workbench.dispose();
E
Erich Gamma 已提交
553 554
		}

B
Benjamin Pasero 已提交
555
		this.contextViewService.dispose();
E
Erich Gamma 已提交
556 557

		// Listeners
J
Joao Moreno 已提交
558
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
559 560 561 562

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