shell.ts 24.9 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
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
106
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
B
Benjamin Pasero 已提交
107
import { foreground, focus } from 'vs/platform/theme/common/colorRegistry';
108

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

119 120
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

153 154 155 156
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

				// run workbench started logic
186
				this.onWorkbenchStarted(info);
187 188 189

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

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

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

209
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
210 211

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

374
		this.timerService.beforeExtensionLoad = Date.now();
375 376 377 378

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Erich Gamma 已提交
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 460
	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 {
461
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
462 463 464 465
		if (!errorMsg) {
			return;
		}

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

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

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

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

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

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

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

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

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

		// Container
		$(this.container).empty();
	}
512
}
513 514

registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
B
Benjamin Pasero 已提交
515
	const windowForeground = theme.getColor(foreground);
516 517 518
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535

	const focusOutline = theme.getColor(focus);
	if (focusOutline) {
		collector.addRule(`
			.monaco-shell [tabindex="0"]:focus,
			.monaco-shell .synthetic-focus,
			.monaco-shell select:focus,
			.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
			.monaco-shell input[type="button"]:focus,
			.monaco-shell input[type="text"]:focus,
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
536
});