shell.ts 24.6 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 } 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';
J
Johannes Rieken 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
import { RequestService } from 'vs/platform/request/node/requestService';
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 215 216 217
			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(() => {
			const initialStartup = !!timers.isInitialStartup;
			const start = initialStartup ? timers.perfStartTime : timers.perfWindowLoadTime;
			let totalmem: number;
B
Benjamin Pasero 已提交
218
			let freemem: number;
219
			let cpus: { count: number; speed: number; model: string; };
B
Benjamin Pasero 已提交
220 221
			let platform: string;
			let release: string;
222 223 224

			try {
				totalmem = os.totalmem();
B
Benjamin Pasero 已提交
225 226 227
				freemem = os.freemem();
				platform = os.platform();
				release = os.release();
228 229 230 231 232 233 234 235 236 237 238 239 240

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

			if (initialStartup) {
259
				startupTimeEvent.timers.ellapsedWindowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
260 261 262 263 264
			}

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

266
		// Telemetry: workspace tags
267
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
268
		workspaceStats.reportWorkspaceTags(this.options);
J
Joao Moreno 已提交
269 270 271 272

		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 已提交
273 274
	}

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

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

281 282 283 284
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
285
		serviceCollection.set(IEnvironmentService, this.environmentService);
286

J
Joao Moreno 已提交
287 288
		const instantiationServiceImpl = new InstantiationService(serviceCollection, true);
		const instantiationService = instantiationServiceImpl as IInstantiationService;
289

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

J
Joao Moreno 已提交
294 295 296 297 298 299 300 301
		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()}`);
302
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
303 304 305

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

306 307 308 309 310 311 312 313
			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 已提交
314
		// Storage Sevice
315
		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 已提交
316
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
317
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
318

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

325
			const config: ITelemetryServiceConfig = {
326
				appender: new TelemetryAppenderClient(channel),
327
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
328
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
329
				experiments: loadExperiments(this.storageService, this.configurationService)
330
			};
331

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

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

338 339 340 341
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
342
				));
343

344
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
345
		} else {
346
			NullTelemetryService._experiments = loadExperiments(this.storageService, this.configurationService);
347
			this.telemetryService = NullTelemetryService;
348
		}
E
Erich Gamma 已提交
349

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

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

357
		const lifecycleService = instantiationService.createInstance(LifecycleService);
358 359
		this.toUnbind.push(lifecycleService.onShutdown(() => disposables.dispose()));
		serviceCollection.set(ILifecycleService, lifecycleService);
360

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

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

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

373 374 375 376 377 378 379 380 381
		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 已提交
382

383
		serviceCollection.set(ICommandService, new CommandService(instantiationService, this.extensionService));
384

385 386
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
387

J
Joao Moreno 已提交
388
		const requestService = instantiationService.createInstance(RequestService);
389
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
390

391
		const markerService = instantiationService.createInstance(MarkerService);
392
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
393

394
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
395
		serviceCollection.set(IModeService, modeService);
396

397
		const modelService = instantiationService.createInstance(ModelServiceImpl);
398
		serviceCollection.set(IModelService, modelService);
399

400
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
401
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
402

403
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
404 405 406
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

		this.themeService = instantiationService.createInstance(ThemeService);
407
		serviceCollection.set(IThemeService, this.themeService);
408

409
		const searchService = instantiationService.createInstance(SearchService);
410 411
		serviceCollection.set(ISearchService, searchService);

J
Joao Moreno 已提交
412
		const codeEditorService = instantiationServiceImpl.createInstance(CodeEditorServiceImpl);
413 414
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
415 416 417
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

J
Joao Moreno 已提交
418 419 420 421
		const updateChannel = mainProcessClient.getChannel('update');
		const updateChannelClient = new UpdateChannelClient(updateChannel);
		serviceCollection.set(IUpdateService, updateChannelClient);

J
Joao Moreno 已提交
422
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
423
		const urlChannelClient = new URLChannelClient(urlChannel, windowIPCService.getWindowId());
J
Joao Moreno 已提交
424 425
		serviceCollection.set(IURLService, urlChannelClient);

J
Joao Moreno 已提交
426
		return [instantiationServiceImpl, serviceCollection];
E
Erich Gamma 已提交
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
	}

	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 已提交
455
		this.themeService.initialize(this.container).then(null, error => {
456 457
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
458 459 460 461 462 463 464 465 466
	}

	private registerListeners(): void {

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

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

469 470
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
471
			events.push({
472 473
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
474
				topic: 'Startup',
475 476
				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 已提交
477
			});
478
		}
E
Erich Gamma 已提交
479

480 481 482 483 484 485 486 487
		// 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 已提交
488

489 490 491 492 493 494 495 496 497 498 499
		// 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 已提交
500 501 502
	}

	public onUnexpectedError(error: any): void {
503
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
504 505 506 507
		if (!errorMsg) {
			return;
		}

508
		const now = Date.now();
E
Erich Gamma 已提交
509 510 511 512 513 514 515 516 517 518 519
		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
520
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
521
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
522 523 524
		}
	}

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

528
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
529 530
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
531
		this.contextViewService.layout();
E
Erich Gamma 已提交
532 533 534 535 536 537 538
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
539
	public dispose(): void {
E
Erich Gamma 已提交
540 541 542

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
543
			this.workbench.dispose();
E
Erich Gamma 已提交
544 545
		}

B
Benjamin Pasero 已提交
546
		this.contextViewService.dispose();
E
Erich Gamma 已提交
547 548

		// Listeners
J
Joao Moreno 已提交
549
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
550 551 552 553 554

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