shell.ts 23.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
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';
J
Joao Moreno 已提交
90
import { 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
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
97 98
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
99
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview';
100 101
import { readdir } from 'vs/base/node/pfs';
import { join } from 'path';
102
import 'vs/platform/opener/browser/opener.contribution';
103

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

114 115
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

147 148 149 150
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

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

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

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

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

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

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
206
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
207 208 209
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
B
Benjamin Pasero 已提交
210
			emptyWorkbench: !this.contextService.hasWorkspace(),
211 212 213
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
214
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
215
			theme: info.themeId,
216
			language: platform.language,
217 218
			experiments: this.telemetryService.getExperiments(),
			pinnedViewlets: info.pinnedViewlets
219 220
		});

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

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

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

		// Profiler: startup cpu profile
J
Johannes Rieken 已提交
240 241
		const { profileStartup } = this.environmentService;
		if (profileStartup) {
242

J
Johannes Rieken 已提交
243
			stopProfiling(profileStartup.dir, profileStartup.prefix).then(() => {
244

J
Johannes Rieken 已提交
245 246
				readdir(profileStartup.dir).then(files => {
					return files.filter(value => value.indexOf(profileStartup.prefix) === 0);
247 248
				}).then(files => {

J
Johannes Rieken 已提交
249
					const profileFiles = files.reduce((prev, cur) => `${prev}${join(profileStartup.dir, cur)}\n`, '\n');
250 251 252 253 254 255 256 257 258 259 260 261 262

					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);

J
Johannes Rieken 已提交
263 264
						createIssue = action.run(`:warning: Make sure to **attach** these files: :warning:\n${files.map(file => `-\`${join(profileStartup.dir, file)}\``).join('\n')}`).then(() => {
							return this.windowsService.showItemInFolder(profileStartup.dir);
265 266
						});
					}
J
Johannes Rieken 已提交
267
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--prof-startup'] }));
268 269 270 271
				});

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

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

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

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

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

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

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

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

298 299 300 301 302
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

		sharedProcess
			.done(client => client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel)));
303

B
Benjamin Pasero 已提交
304
		// Storage Sevice
B
Benjamin Pasero 已提交
305
		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 已提交
306
		this.storageService = instantiationService.createInstance(StorageService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
307
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
308

309 310 311 312
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

379
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
380

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

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

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

388
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
389

390
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
391

392
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
393

394
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
395

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

398
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
399

400
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
401

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

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

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

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

413
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
414 415 416 417 418 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
	}

	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();

		// 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 {
446
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
447 448 449 450
		if (!errorMsg) {
			return;
		}

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

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

471
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
472 473
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
474
		this.contextViewService.layout();
E
Erich Gamma 已提交
475 476 477 478 479 480 481
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
482
	public dispose(): void {
E
Erich Gamma 已提交
483 484 485

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
486
			this.workbench.dispose();
E
Erich Gamma 已提交
487 488
		}

B
Benjamin Pasero 已提交
489
		this.contextViewService.dispose();
E
Erich Gamma 已提交
490 491

		// Listeners
J
Joao Moreno 已提交
492
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
493 494 495 496

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