shell.ts 23.6 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';
C
Christof Marti 已提交
33 34
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
35
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
36 37 38 39
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 已提交
40
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
41
import { IRequestService } from 'vs/platform/request/node/request';
42
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
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 已提交
59
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
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 { 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';
72
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
73
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
74
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
75 76 77
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';
78
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
79 80
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
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
89 90
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
J
Joao Moreno 已提交
91
import { ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/actions';
S
Sandeep Somavarapu 已提交
92
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
93
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
94
import { remote, ipcRenderer as ipc } from 'electron';
A
Alex Dima 已提交
95
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
96
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
97
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
98 99
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
100
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview';
101 102
import { readdir } from 'vs/base/node/pfs';
import { join } from 'path';
103
import 'vs/platform/opener/browser/opener.contribution';
104

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

115 116
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

148 149 150 151
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

					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 已提交
264 265
						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);
266 267
						});
					}
J
Johannes Rieken 已提交
268
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--prof-startup'] }));
269 270 271 272
				});

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

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

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

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

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

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

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

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

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

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

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

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

314
		// Telemetry
C
Christof Marti 已提交
315
		this.sendMachineIdToMain(this.storageService);
316
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
317
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
318 319
			const commit = product.commit;
			const version = pkg.version;
320

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

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

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

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

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

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

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

353
		const lifecycleService = instantiationService.createInstance(LifecycleService);
354
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
355
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
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
	}

C
Christof Marti 已提交
418 419 420 421 422 423
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
	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 {
454
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
455 456 457 458
		if (!errorMsg) {
			return;
		}

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

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

479
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
480 481
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
482
		this.contextViewService.layout();
E
Erich Gamma 已提交
483 484 485 486 487 488 489
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
490
	public dispose(): void {
E
Erich Gamma 已提交
491 492 493

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
494
			this.workbench.dispose();
E
Erich Gamma 已提交
495 496
		}

B
Benjamin Pasero 已提交
497
		this.contextViewService.dispose();
E
Erich Gamma 已提交
498 499

		// Listeners
J
Joao Moreno 已提交
500
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
501 502 503 504

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