shell.ts 24.0 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';
B
Benjamin Pasero 已提交
104 105
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/themeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/themeService';
106

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

117 118
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

148
	constructor(container: HTMLElement, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
149 150
		this.container = container;

151 152 153 154
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

164
		// ARIA
B
Benjamin Pasero 已提交
165
		aria.setARIAContainer(document.body);
166

E
Erich Gamma 已提交
167
		// Workbench Container
168
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
169 170

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

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

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

				// run workbench started logic
184
				this.onWorkbenchStarted(info);
185 186 187

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
E
Erich Gamma 已提交
188 189 190
			}
		});

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

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

207
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
208 209

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

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

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

		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'."));
		}
242 243

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

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

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

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

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

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

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

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

287
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
288

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

293
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
294 295
		disposables.add(mainProcessClient);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

365 366 367
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
368

369
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
370
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
371
		serviceCollection.set(IThreadService, this.threadService);
372

B
Benjamin Pasero 已提交
373
		this.timerService.beforeExtensionLoad = new Date();
374 375 376 377

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

B
Benjamin Pasero 已提交
384 385 386
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

387
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
388

389 390
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
391

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

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

396
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
397

398
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
399

400
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
401

402
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
403

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

406
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
407

408
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
409

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

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

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

418
		const backupChannel = mainProcessClient.getChannel('backup');
419
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
420

421
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
422 423
	}

C
Christof Marti 已提交
424 425 426 427 428 429
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

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

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

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

485
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
486 487
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
488
		this.contextViewService.layout();
E
Erich Gamma 已提交
489 490 491 492 493 494 495
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
496
	public dispose(): void {
E
Erich Gamma 已提交
497 498 499

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
500
			this.workbench.dispose();
E
Erich Gamma 已提交
501 502
		}

B
Benjamin Pasero 已提交
503
		this.contextViewService.dispose();
E
Erich Gamma 已提交
504 505

		// Listeners
J
Joao Moreno 已提交
506
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
507 508 509 510

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