shell.ts 25.5 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';
24
import { Workbench, IWorkbenchStartedInfo } 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, lifecycleTelemetry } 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
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';
77
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
78 79 80 81
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';
82
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
83
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
84 85
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
86 87
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
88 89
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
90 91
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
J
Johannes Rieken 已提交
92
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
93
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
94
import { remote } from 'electron';
95
import * as os from 'os';
96 97

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

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

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

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

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

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

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

		this.workspace = workspace;
144 145 146 147 148
		this.options = options;

		this.contextService = services.contextService;
		this.eventService = services.eventService;
		this.configurationService = services.configurationService;
149
		this.environmentService = services.environmentService;
E
Erich Gamma 已提交
150 151 152 153 154 155 156

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

	private createContents(parent: Builder): Builder {

157
		// ARIA
B
Benjamin Pasero 已提交
158
		aria.setARIAContainer(document.body);
159

E
Erich Gamma 已提交
160
		// Workbench Container
161
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
162 163

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

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

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

				// run workbench started logic
177
				this.onWorkbenchStarted(info);
178 179 180

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

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

		// Handle case where workbench is not starting up properly
188
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
189 190 191 192 193 194 195 196 197 198
			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;
	}

199
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
200 201 202 203 204

		// 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 已提交
205
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
206 207 208 209
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
			emptyWorkbench: !this.contextService.getWorkspace(),
210 211 212
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
213
			customKeybindingsCount: info.customKeybindingsCount,
214 215
			theme: this.themeService.getColorTheme(),
			language: platform.language,
216 217
			experiments: this.telemetryService.getExperiments(),
			pinnedViewlets: info.pinnedViewlets
218 219 220 221 222 223
		});

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

			try {
				totalmem = os.totalmem();
B
Benjamin Pasero 已提交
237 238 239
				freemem = os.freemem();
				platform = os.platform();
				release = os.release();
240 241
				loadavg = os.loadavg();
				meminfo = process.getProcessMemoryInfo();
242 243 244 245 246 247 248 249 250 251

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

			if (initialStartup) {
277
				startupTimeEvent.timers.ellapsedWindowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
278 279 280 281 282
			}

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

284
		// Telemetry: workspace tags
285
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
286
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
287
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
288 289 290 291

		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 已提交
292 293
	}

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

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

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

J
Joao Moreno 已提交
306 307
		const instantiationServiceImpl = new InstantiationService(serviceCollection, true);
		const instantiationService = instantiationServiceImpl as IInstantiationService;
308

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

J
Joao Moreno 已提交
313 314 315 316 317 318 319 320
		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()}`);
321
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
322 323 324

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

325 326 327 328 329 330 331 332
			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 已提交
333
		// Storage Sevice
334
		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 已提交
335
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
336
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
337

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

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

J
Joao Moreno 已提交
351
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
352 353
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
354
			const errorTelemetry = new ErrorTelemetry(telemetryService);
355
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
356

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

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

369
		serviceCollection.set(ITelemetryService, this.telemetryService);
370
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
371

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

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

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

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

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

393 394 395 396 397 398 399 400 401
		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 已提交
402

403
		serviceCollection.set(ICommandService, new CommandService(instantiationService, this.extensionService));
404

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

J
Joao Moreno 已提交
408
		const requestService = instantiationService.createInstance(RequestService);
409
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
410

411
		const markerService = instantiationService.createInstance(MarkerService);
412
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
413

414
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
415
		serviceCollection.set(IModeService, modeService);
416

417
		const modelService = instantiationService.createInstance(ModelServiceImpl);
418
		serviceCollection.set(IModelService, modelService);
419

420
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
421
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
422

423
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
424 425 426
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

		this.themeService = instantiationService.createInstance(ThemeService);
427
		serviceCollection.set(IThemeService, this.themeService);
428

429
		const searchService = instantiationService.createInstance(SearchService);
430 431
		serviceCollection.set(ISearchService, searchService);

J
Joao Moreno 已提交
432
		const codeEditorService = instantiationServiceImpl.createInstance(CodeEditorServiceImpl);
433 434
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
435 436 437
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

J
Joao Moreno 已提交
438 439 440 441
		const updateChannel = mainProcessClient.getChannel('update');
		const updateChannelClient = new UpdateChannelClient(updateChannel);
		serviceCollection.set(IUpdateService, updateChannelClient);

J
Joao Moreno 已提交
442
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
443
		const urlChannelClient = new URLChannelClient(urlChannel, windowIPCService.getWindowId());
J
Joao Moreno 已提交
444 445
		serviceCollection.set(IURLService, urlChannelClient);

446 447 448 449
		const backupChannel = mainProcessClient.getChannel('backup');
		const backupChannelClient = new BackupChannelClient(backupChannel);
		serviceCollection.set(IBackupService, backupChannelClient);

J
Joao Moreno 已提交
450
		return [instantiationServiceImpl, serviceCollection];
E
Erich Gamma 已提交
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	}

	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 已提交
479
		this.themeService.initialize(this.container).then(null, error => {
480 481
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
482 483 484 485 486 487 488 489 490
	}

	private registerListeners(): void {

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

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

493 494
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
495
			events.push({
496 497
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
498
				topic: 'Startup',
499 500
				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 已提交
501
			});
502
		}
E
Erich Gamma 已提交
503

504 505 506 507 508 509 510 511
		// 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 已提交
512

513 514 515 516 517 518 519 520 521 522 523
		// 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 已提交
524 525 526
	}

	public onUnexpectedError(error: any): void {
527
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
528 529 530 531
		if (!errorMsg) {
			return;
		}

532
		const now = Date.now();
E
Erich Gamma 已提交
533 534 535 536 537 538 539 540 541 542 543
		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
544
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
545
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
546 547 548
		}
	}

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

552
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
553 554
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
555
		this.contextViewService.layout();
E
Erich Gamma 已提交
556 557 558 559 560 561 562
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
563
	public dispose(): void {
E
Erich Gamma 已提交
564 565 566

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
567
			this.workbench.dispose();
E
Erich Gamma 已提交
568 569
		}

B
Benjamin Pasero 已提交
570
		this.contextViewService.dispose();
E
Erich Gamma 已提交
571 572

		// Listeners
J
Joao Moreno 已提交
573
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
574 575 576 577

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