shell.ts 23.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';
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 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
J
Johannes Rieken 已提交
239 240
		const { profileStartup } = this.environmentService;
		if (profileStartup) {
241

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

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

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

					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 已提交
262 263
						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);
264 265
						});
					}
J
Johannes Rieken 已提交
266
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--prof-startup'] }));
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 298 299 300 301
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

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

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

J
Joao Moreno 已提交
321
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
322 323
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
324
			const errorTelemetry = new ErrorTelemetry(telemetryService);
325
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
326

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

333
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
334
		} else {
C
Christof Marti 已提交
335
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
336
			this.telemetryService = NullTelemetryService;
337
		}
E
Erich Gamma 已提交
338

339
		serviceCollection.set(ITelemetryService, this.telemetryService);
340
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
341

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

346
		const lifecycleService = instantiationService.createInstance(LifecycleService);
347
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
348
		serviceCollection.set(ILifecycleService, lifecycleService);
349
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
350

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

354 355 356
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
357

358
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
359
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
360
		serviceCollection.set(IThreadService, this.threadService);
361

B
Benjamin Pasero 已提交
362
		this.timerService.beforeExtensionLoad = new Date();
363 364 365 366

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

373
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
374

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

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

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

382
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
383

384
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
385

386
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
387

388
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
389

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

392
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
393

394
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
395

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

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

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

404
		const backupChannel = mainProcessClient.getChannel('backup');
405
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
406

407
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
408 409 410 411 412 413 414 415 416
	}

	public open(): void {

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

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

E
Erich Gamma 已提交
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
		// 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 {
443
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
444 445 446 447
		if (!errorMsg) {
			return;
		}

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

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

468
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
469 470
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
471
		this.contextViewService.layout();
E
Erich Gamma 已提交
472 473 474 475 476 477 478
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
479
	public dispose(): void {
E
Erich Gamma 已提交
480 481 482

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
483
			this.workbench.dispose();
E
Erich Gamma 已提交
484 485
		}

B
Benjamin Pasero 已提交
486
		this.contextViewService.dispose();
E
Erich Gamma 已提交
487 488

		// Listeners
J
Joao Moreno 已提交
489
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
490 491 492 493

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