shell.ts 25.3 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 282 283 284
		// Telemetry: node cached data error
		const onNodeCachedDataError = (err) => { this.telemetryService.publicLog('nodeCachedData', { errorCode: err.errorCode, path: err.path }); };
		(<any>self).require.config({ onNodeCachedDataError }, true);
		(<any[]>(<any>window).MonacoEnvironment.nodeCachedDataErrors).forEach(onNodeCachedDataError);
		delete (<any>window).MonacoEnvironment.nodeCachedDataErrors;

J
Joao Moreno 已提交
285 286 287
		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 已提交
288 289
	}

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

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

296 297 298 299
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
300
		serviceCollection.set(IEnvironmentService, this.environmentService);
301

J
Joao Moreno 已提交
302 303
		const instantiationServiceImpl = new InstantiationService(serviceCollection, true);
		const instantiationService = instantiationServiceImpl as IInstantiationService;
304

J
Joao Moreno 已提交
305 306 307
		// TODO@joao remove this
		const windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, windowIPCService);
308

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

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

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

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

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

J
Joao Moreno 已提交
347
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
348 349
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
350
			const errorTelemetry = new ErrorTelemetry(telemetryService);
351
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
352

353 354 355 356
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
357
				));
358

359
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
360
		} else {
361
			NullTelemetryService._experiments = loadExperiments(this.contextService, this.storageService, this.configurationService);
362
			this.telemetryService = NullTelemetryService;
363
		}
E
Erich Gamma 已提交
364

365
		serviceCollection.set(ITelemetryService, this.telemetryService);
366
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
367

368
		this.messageService = instantiationService.createInstance(MessageService, container);
369
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
370
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
371

372
		const lifecycleService = instantiationService.createInstance(LifecycleService);
373
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
374
		serviceCollection.set(ILifecycleService, lifecycleService);
375

S
Sandeep Somavarapu 已提交
376 377 378 379
		const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
		const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
		serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);

380 381 382
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
383

384
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
385
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
386
		serviceCollection.set(IThreadService, this.threadService);
387

388 389 390 391 392 393 394 395 396
		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 已提交
397

398
		serviceCollection.set(ICommandService, new CommandService(instantiationService, this.extensionService));
399

400 401
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
402

J
Joao Moreno 已提交
403
		const requestService = instantiationService.createInstance(RequestService);
404
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
405

406
		const markerService = instantiationService.createInstance(MarkerService);
407
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
408

409
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
410
		serviceCollection.set(IModeService, modeService);
411

412
		const modelService = instantiationService.createInstance(ModelServiceImpl);
413
		serviceCollection.set(IModelService, modelService);
414

415
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
416
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
417

418
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
419 420 421
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

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

424
		const searchService = instantiationService.createInstance(SearchService);
425 426
		serviceCollection.set(ISearchService, searchService);

J
Joao Moreno 已提交
427
		const codeEditorService = instantiationServiceImpl.createInstance(CodeEditorServiceImpl);
428 429
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
430 431 432
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

J
Joao Moreno 已提交
433 434 435 436
		const updateChannel = mainProcessClient.getChannel('update');
		const updateChannelClient = new UpdateChannelClient(updateChannel);
		serviceCollection.set(IUpdateService, updateChannelClient);

J
Joao Moreno 已提交
437
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
438
		const urlChannelClient = new URLChannelClient(urlChannel, windowIPCService.getWindowId());
J
Joao Moreno 已提交
439 440
		serviceCollection.set(IURLService, urlChannelClient);

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

	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 已提交
470
		this.themeService.initialize(this.container).then(null, error => {
471 472
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
473 474 475 476 477 478 479 480 481
	}

	private registerListeners(): void {

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

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

484 485
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
486
			events.push({
487 488
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
489
				topic: 'Startup',
490 491
				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 已提交
492
			});
493
		}
E
Erich Gamma 已提交
494

495 496 497 498 499 500 501 502
		// 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 已提交
503

504 505 506 507 508 509 510 511 512 513 514
		// 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 已提交
515 516 517
	}

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

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

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

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

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

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

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

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

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

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

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