shell.ts 25.2 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
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 90
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 已提交
91
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
92
import { remote } from 'electron';
93
import * as os from 'os';
94 95

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

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

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

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

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

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

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

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

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

				// run workbench started logic
175
				this.onWorkbenchStarted(customKeybindingsCount, restoreViewletDuration, restoreEditorsDuration);
176 177 178

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

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

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

197 198 199 200 201 202
	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 已提交
203
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
204 205 206 207
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
			emptyWorkbench: !this.contextService.getWorkspace(),
208 209 210
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
211 212 213 214 215 216 217 218 219 220
			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(() => {
221
			const now = Date.now();
222 223 224
			const initialStartup = !!timers.isInitialStartup;
			const start = initialStartup ? timers.perfStartTime : timers.perfWindowLoadTime;
			let totalmem: number;
B
Benjamin Pasero 已提交
225
			let freemem: number;
226
			let cpus: { count: number; speed: number; model: string; };
B
Benjamin Pasero 已提交
227 228
			let platform: string;
			let release: string;
229 230
			let loadavg: number[];
			let meminfo: IMemoryInfo;
231 232 233

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

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

			if (initialStartup) {
274
				startupTimeEvent.timers.ellapsedWindowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
275 276 277 278 279
			}

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

281
		// Telemetry: workspace tags
282
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
283
		workspaceStats.reportWorkspaceTags(this.options);
J
Joao Moreno 已提交
284 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
}