shell.ts 24.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 } 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
197
		const { filesToOpen, filesToCreate, filesToDiff, untitledToRestore } = 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 205
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
			'workbench.untitledToRestore': untitledToRestore && untitledToRestore.length || undefined,
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
			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;
			let cpus: { count: number; speed: number; model: string; };

			try {
				totalmem = os.totalmem();

				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),
					extensionsReady: Math.round(timers.perfAfterExtensionLoad - start),
					ellapsedRequire: Math.round(timers.perfAfterLoadWorkbenchMain - timers.perfBeforeLoadWorkbenchMain),
					ellapsedViewletRestore: Math.round(restoreViewletDuration),
					ellapsedEditorRestore: Math.round(restoreEditorsDuration),
					ellapsedWorkbench: Math.round(workbenchStarted - timers.perfBeforeWorkbenchOpen)
				},
				totalmem,
				cpus,
				initialStartup,
				hasAccessibilitySupport: !!timers.hasAccessibilitySupport,
				emptyWorkbench: !this.contextService.getWorkspace()
			};

			if (initialStartup) {
				startupTimeEvent.timers.ellapsedMain = Math.round(timers.perfBeforeLoadWorkbenchMain - timers.perfStartTime);
				startupTimeEvent.timers.windowLoad = Math.round(timers.perfWindowLoadTime - timers.perfStartTime);
			}

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

258
		// Telemetry: workspace tags
259
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
260
		workspaceStats.reportWorkspaceTags(this.options);
J
Joao Moreno 已提交
261 262 263 264

		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 已提交
265 266
	}

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

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

273 274 275 276
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
277
		serviceCollection.set(IEnvironmentService, this.environmentService);
278

J
Joao Moreno 已提交
279 280
		const instantiationServiceImpl = new InstantiationService(serviceCollection, true);
		const instantiationService = instantiationServiceImpl as IInstantiationService;
281

J
Joao Moreno 已提交
282 283 284
		// TODO@joao remove this
		const windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, windowIPCService);
285

J
Joao Moreno 已提交
286 287 288 289 290 291 292 293
		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()}`);
294
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
295 296 297

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

298 299 300 301 302 303 304 305
			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 已提交
306
		// Storage Sevice
307
		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 已提交
308
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
309
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
310

311
		// Telemetry
312
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
313
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
314 315
			const commit = product.commit;
			const version = pkg.version;
316

317
			const config: ITelemetryServiceConfig = {
318
				appender: new TelemetryAppenderClient(channel),
319
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
320
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
321
				experiments: loadExperiments(this.storageService, this.configurationService)
322
			};
323

J
Joao Moreno 已提交
324
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
325 326
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
327
			const errorTelemetry = new ErrorTelemetry(telemetryService);
328
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
329

330 331 332 333
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
334
				));
335

336
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
337
		} else {
338
			NullTelemetryService._experiments = loadExperiments(this.storageService, this.configurationService);
339
			this.telemetryService = NullTelemetryService;
340
		}
E
Erich Gamma 已提交
341

342
		serviceCollection.set(ITelemetryService, this.telemetryService);
343
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
344

345
		this.messageService = instantiationService.createInstance(MessageService, container);
346
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
347
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
348

349
		const lifecycleService = instantiationService.createInstance(LifecycleService);
350 351
		this.toUnbind.push(lifecycleService.onShutdown(() => disposables.dispose()));
		serviceCollection.set(ILifecycleService, lifecycleService);
352

S
Sandeep Somavarapu 已提交
353 354 355 356
		const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
		const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
		serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);

357 358 359
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
360

361
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
362
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
363
		serviceCollection.set(IThreadService, this.threadService);
364

365 366 367 368 369 370 371 372 373
		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 已提交
374

375
		serviceCollection.set(ICommandService, new CommandService(instantiationService, this.extensionService));
376

377 378
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
379

J
Joao Moreno 已提交
380
		const requestService = instantiationService.createInstance(RequestService);
381
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
382

383
		const markerService = instantiationService.createInstance(MarkerService);
384
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
385

386
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
387
		serviceCollection.set(IModeService, modeService);
388

389
		const modelService = instantiationService.createInstance(ModelServiceImpl);
390
		serviceCollection.set(IModelService, modelService);
391

392
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
393
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
394

395
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
396 397 398
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

		this.themeService = instantiationService.createInstance(ThemeService);
399
		serviceCollection.set(IThemeService, this.themeService);
400

401
		const searchService = instantiationService.createInstance(SearchService);
402 403
		serviceCollection.set(ISearchService, searchService);

J
Joao Moreno 已提交
404
		const codeEditorService = instantiationServiceImpl.createInstance(CodeEditorServiceImpl);
405 406
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
407 408 409
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

J
Joao Moreno 已提交
410 411 412 413
		const updateChannel = mainProcessClient.getChannel('update');
		const updateChannelClient = new UpdateChannelClient(updateChannel);
		serviceCollection.set(IUpdateService, updateChannelClient);

J
Joao Moreno 已提交
414
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
415
		const urlChannelClient = new URLChannelClient(urlChannel, windowIPCService.getWindowId());
J
Joao Moreno 已提交
416 417
		serviceCollection.set(IURLService, urlChannelClient);

J
Joao Moreno 已提交
418
		return [instantiationServiceImpl, serviceCollection];
E
Erich Gamma 已提交
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
	}

	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 已提交
447
		this.themeService.initialize(this.container).then(null, error => {
448 449
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
450 451 452 453 454 455 456 457 458
	}

	private registerListeners(): void {

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

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

461 462
		// Window
		if (timers.isInitialStartup && timers.perfStartTime) {
E
Erich Gamma 已提交
463
			events.push({
464 465
				startTime: timers.perfStartTime,
				stopTime: timers.perfBeforeLoadWorkbenchMain,
E
Erich Gamma 已提交
466
				topic: 'Startup',
467 468
				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 已提交
469
			});
470
		}
E
Erich Gamma 已提交
471

472 473 474 475 476 477 478 479
		// 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 已提交
480

481 482 483 484 485 486 487 488 489 490 491
		// 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 已提交
492 493 494
	}

	public onUnexpectedError(error: any): void {
495
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
496 497 498 499
		if (!errorMsg) {
			return;
		}

500
		const now = Date.now();
E
Erich Gamma 已提交
501 502 503 504 505 506 507 508 509 510 511
		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
512
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
513
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
514 515 516
		}
	}

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

520
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
521 522
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
523
		this.contextViewService.layout();
E
Erich Gamma 已提交
524 525 526 527 528 529 530
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
531
	public dispose(): void {
E
Erich Gamma 已提交
532 533 534

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
535
			this.workbench.dispose();
E
Erich Gamma 已提交
536 537
		}

B
Benjamin Pasero 已提交
538
		this.contextViewService.dispose();
E
Erich Gamma 已提交
539 540

		// Listeners
J
Joao Moreno 已提交
541
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
542 543 544 545 546

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