shell.ts 23.4 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
import { stopProfiling } from 'vs/base/node/profiler';
20
import product from 'vs/platform/node/product';
21
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
22
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
23
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
24
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
25
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
26 27
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
28 29 30
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 已提交
31
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
32
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
J
Johannes Rieken 已提交
33 34
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
35 36 37 38
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 已提交
39
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
40
import { IRequestService } from 'vs/platform/request/node/request';
41
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
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 已提交
58
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
59 60 61 62 63 64 65 66 67 68 69 70
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 { 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';
71
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
72
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
73
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
74 75 76
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
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
80
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
81
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
82 83
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
84 85
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
86 87
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
88 89
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
90
import { ReloadWindowAction, ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
91
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
92
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
93
import { remote } from 'electron';
A
Alex Dima 已提交
94
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
95
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
96 97
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { readFontInfo } from 'vs/editor/browser/config/configuration';
98
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview';
99 100
import { readdir } from 'vs/base/node/pfs';
import { join } from 'path';
101
import 'vs/platform/opener/browser/opener.contribution';
102

103 104 105 106 107 108
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
109
	environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
110
	timerService: ITimerService;
111 112
}

113 114
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
115
/**
B
Benjamin Pasero 已提交
116
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
117 118 119
 * 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 已提交
120
	private storageService: IStorageService;
121
	private messageService: MessageService;
J
Johannes Rieken 已提交
122
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
123 124
	private contextViewService: ContextViewService;
	private threadService: MainThreadService;
125 126
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
127
	private telemetryService: ITelemetryService;
128
	private extensionService: MainProcessExtensionService;
129
	private windowsService: IWindowsService;
130
	private windowIPCService: IWindowIPCService;
B
Benjamin Pasero 已提交
131
	private timerService: ITimerService;
E
Erich Gamma 已提交
132 133

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

	private options: IOptions;
	private workbench: Workbench;

143
	constructor(container: HTMLElement, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
144 145
		this.container = container;

146 147 148 149
		this.options = options;

		this.contextService = services.contextService;
		this.configurationService = services.configurationService;
150
		this.environmentService = services.environmentService;
B
Benjamin Pasero 已提交
151
		this.timerService = services.timerService;
E
Erich Gamma 已提交
152 153 154 155 156 157 158

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

				// run workbench started logic
179
				this.onWorkbenchStarted(info);
180 181 182

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

186 187 188
		// Window
		const activeWindow = this.workbench.getInstantiationService().createInstance(ElectronWindow, currentWindow, this.container);
		this.windowIPCService.registerWindow(activeWindow);
E
Erich Gamma 已提交
189 190

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

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

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
205
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
206 207 208
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
B
Benjamin Pasero 已提交
209
			emptyWorkbench: !this.contextService.hasWorkspace(),
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,
B
Benjamin Pasero 已提交
214
			theme: info.themeId,
215
			language: platform.language,
216 217
			experiments: this.telemetryService.getExperiments(),
			pinnedViewlets: info.pinnedViewlets
218 219
		});

B
Benjamin Pasero 已提交
220
		// Telemetry: startup metrics
221
		const workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
222 223 224
		this.timerService.workbenchStarted = new Date(workbenchStarted);
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
225
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
226
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
227
		});
B
Benjamin Pasero 已提交
228

229
		// Telemetry: workspace tags
230
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
231
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
232
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
233 234 235 236

		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'."));
		}
237 238

		// Profiler: startup cpu profile
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
		const { performanceStartupProfile } = this.environmentService;
		if (performanceStartupProfile) {

			stopProfiling(performanceStartupProfile.dir, performanceStartupProfile.prefix).then(() => {

				readdir(performanceStartupProfile.dir).then(files => {
					return files.filter(value => value.indexOf(performanceStartupProfile.prefix) === 0);
				}).then(files => {

					const profileFiles = files.reduce((prev, cur) => `${prev}${join(performanceStartupProfile.dir, cur)}\n`, '\n');

					const primaryButton = this.messageService.confirm({
						type: 'info',
						message: nls.localize('prof.message', "Successfully created profiles."),
						detail: nls.localize('prof.detail', "Please create an issue and manually attach the following files:\n{0}", profileFiles),
						primaryButton: nls.localize('prof.restartAndFileIssue', "Create Issue and Restart"),
						secondaryButton: nls.localize('prof.restart', "Restart")
					});

					let createIssue = TPromise.as(undefined);
					if (primaryButton) {
						const action = this.workbench.getInstantiationService().createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL);

						createIssue = action.run(`:warning: Make sure to **attach** these files: :warning:\n${files.map(file => `-\`${join(performanceStartupProfile.dir, file)}\``).join('\n')}`).then(() => {
							return this.windowsService.showItemInFolder(performanceStartupProfile.dir);
						});
					}
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--performance-startup-profile'] }));
267 268 269 270
				});

			}, err => console.error(err));
		}
B
Benjamin Pasero 已提交
271 272
	}

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

276 277 278
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
279
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
280
		serviceCollection.set(ITimerService, this.timerService);
281

282
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
283

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

288
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
289 290
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
291
		const windowsChannel = mainProcessClient.getChannel('windows');
292 293
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
294

295
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, this.windowIPCService.getWindowId()));
J
Joao Moreno 已提交
296

297
		const sharedProcess = connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`);
298
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
299

300 301
			// Choice channel
			client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel));
S
Sandeep Somavarapu 已提交
302

303 304 305 306 307 308 309 310
			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 已提交
311
		// Storage Sevice
B
Benjamin Pasero 已提交
312
		const disableWorkspaceStorage = this.environmentService.extensionTestsPath || (!this.contextService.hasWorkspace() && !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 已提交
313
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
314
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
315

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

322
			const config: ITelemetryServiceConfig = {
323
				appender: new TelemetryAppenderClient(channel),
324
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
325
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
C
Christof Marti 已提交
326
				experiments: instantiationService.invokeFunction(loadExperiments)
327
			};
328

J
Joao Moreno 已提交
329
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
330 331
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
332
			const errorTelemetry = new ErrorTelemetry(telemetryService);
333
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
334

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

341
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
342
		} else {
C
Christof Marti 已提交
343
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
344
			this.telemetryService = NullTelemetryService;
345
		}
E
Erich Gamma 已提交
346

347
		serviceCollection.set(ITelemetryService, this.telemetryService);
348
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
349

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

354
		const lifecycleService = instantiationService.createInstance(LifecycleService);
355
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
356
		serviceCollection.set(ILifecycleService, lifecycleService);
357
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
358

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

362 363 364
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
365

366
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
367
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
368
		serviceCollection.set(IThreadService, this.threadService);
369

B
Benjamin Pasero 已提交
370
		this.timerService.beforeExtensionLoad = new Date();
371 372 373 374

		// TODO@Joao: remove
		const disabledExtensions = SCMPreview.enabled ? [] : ['vscode.git'];
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService, disabledExtensions);
375 376 377
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
378
			this.timerService.afterExtensionLoad = new Date();
379
		});
E
Erich Gamma 已提交
380

381
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
382

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

386
		serviceCollection.set(IRequestService, new SyncDescriptor(RequestService));
E
Erich Gamma 已提交
387

388
		serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService));
E
Erich Gamma 已提交
389

390
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
391

392
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
393

394
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
395

396
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
397

A
Alex Dima 已提交
398 399
		serviceCollection.set(ITextMateService, new SyncDescriptor(MainProcessTextMateSyntax));

400
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
401

402
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
403

404
		serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
A
Alex Dima 已提交
405

J
Joao Moreno 已提交
406
		const updateChannel = mainProcessClient.getChannel('update');
407
		serviceCollection.set(IUpdateService, new SyncDescriptor(UpdateChannelClient, updateChannel));
J
Joao Moreno 已提交
408

J
Joao Moreno 已提交
409
		const urlChannel = mainProcessClient.getChannel('url');
410
		serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, this.windowIPCService.getWindowId()));
J
Joao Moreno 已提交
411

412
		const backupChannel = mainProcessClient.getChannel('backup');
413
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
414

415
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
416 417 418 419 420 421 422 423 424
	}

	public open(): void {

		// Listen on unexpected errors
		errors.setUnexpectedErrorHandler((error: any) => {
			this.onUnexpectedError(error);
		});

425 426 427
		// Warm up font cache information before building up too many dom elements
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor')));

E
Erich Gamma 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
		// Shell Class for CSS Scoping
		$(this.container).addClass('monaco-shell');

		// Controls
		this.content = $('.monaco-shell-content').appendTo(this.container).getHTMLElement();

		// Create Contents
		this.contentsContainer = this.createContents($(this.content));

		// Layout
		this.layout();

		// Listeners
		this.registerListeners();
	}

	private registerListeners(): void {

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

	public onUnexpectedError(error: any): void {
451
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
452 453 454 455
		if (!errorMsg) {
			return;
		}

456
		const now = Date.now();
E
Erich Gamma 已提交
457 458 459 460 461 462 463 464 465 466 467
		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
468
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
469
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
470 471 472
		}
	}

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

476
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
477 478
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
479
		this.contextViewService.layout();
E
Erich Gamma 已提交
480 481 482 483 484 485 486
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
487
	public dispose(): void {
E
Erich Gamma 已提交
488 489 490

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
491
			this.workbench.dispose();
E
Erich Gamma 已提交
492 493
		}

B
Benjamin Pasero 已提交
494
		this.contextViewService.dispose();
E
Erich Gamma 已提交
495 496

		// Listeners
J
Joao Moreno 已提交
497
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
498 499 500 501

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