shell.ts 28.2 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/shell';

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable, Disposables } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import { stopProfiling } from 'vs/base/node/profiler';
20
import product from 'vs/platform/node/product';
21
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
22
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
23
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
24
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
25
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
26 27
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
28 29 30
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { IdleMonitor, UserStatus } from 'vs/platform/telemetry/browser/idleMonitor';
J
Joao Moreno 已提交
31
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
32
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
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
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';
66
import { IMessageService, IChoiceService, Severity, CloseAction } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
67 68 69 70 71
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 101
import { readdir } from 'vs/base/node/pfs';
import { join } from 'path';
102
import 'vs/platform/opener/browser/opener.contribution';
103 104
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
105
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
106
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground } from 'vs/platform/theme/common/colorRegistry';
107

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

118 119
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

152 153 154 155
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

				// run workbench started logic
185
				this.onWorkbenchStarted(instantiationService, info);
186 187 188

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

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

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

208
	private onWorkbenchStarted(instantiationService: IInstantiationService, info: IWorkbenchStartedInfo): void {
209 210

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

B
Benjamin Pasero 已提交
226
		// Telemetry: startup metrics
227
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
228 229
		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 233 234 235 236 237

			// Check for negative performance numbers (insiders only)
			// TODO@Ben remove me
			if (product.quality !== 'stable' && this.timerService.startupMetrics.ellapsed < 0) {
				this.handleNegativePerformanceNumbers(instantiationService, this.timerService.startupMetrics.ellapsed);
			}
238
		});
B
Benjamin Pasero 已提交
239

240
		// Telemetry: workspace tags
241
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
242
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
243
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
244 245 246 247

		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'."));
		}
248 249

		// Profiler: startup cpu profile
J
Johannes Rieken 已提交
250 251
		const { profileStartup } = this.environmentService;
		if (profileStartup) {
252
			this.extensionService.onReady().then(() => stopProfiling(profileStartup.dir, profileStartup.prefix)).then(() => {
J
Johannes Rieken 已提交
253 254
				readdir(profileStartup.dir).then(files => {
					return files.filter(value => value.indexOf(profileStartup.prefix) === 0);
255
				}).then(files => {
J
Johannes Rieken 已提交
256
					const profileFiles = files.reduce((prev, cur) => `${prev}${join(profileStartup.dir, cur)}\n`, '\n');
257 258 259 260 261 262 263 264 265

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

266
					let createIssue = TPromise.as<void>(void 0);
267 268 269
					if (primaryButton) {
						const action = this.workbench.getInstantiationService().createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL);

J
Johannes Rieken 已提交
270
						createIssue = action.run(`:warning: Make sure to **attach** these files: :warning:\n${files.map(file => `-\`${join(profileStartup.dir, file)}\``).join('\n')}`).then(() => {
J
Johannes Rieken 已提交
271
							return this.windowsService.showItemInFolder(join(profileStartup.dir, files[0]));
272 273
						});
					}
J
Johannes Rieken 已提交
274
					createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--prof-startup'] }));
275 276 277 278
				});

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

281 282 283 284 285 286 287 288 289 290
	private handleNegativePerformanceNumbers(i: IInstantiationService, time: number): void {
		this.messageService.show(Severity.Warning, {
			message: nls.localize('handleNegativePerformanceNumbers', "Something went wrong measuring startup performance numbers (ellapsed: {0}ms). We would like to learn more about this issue.", time),
			actions: [
				i.createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL),
				CloseAction
			]
		});
	}

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

294 295 296
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
297
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
298
		serviceCollection.set(ITimerService, this.timerService);
299

300
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
301

J
Joao Moreno 已提交
302
		// TODO@joao remove this
303 304
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
305

306
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
307 308
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
309
		const windowsChannel = mainProcessClient.getChannel('windows');
310 311
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
312

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

315 316 317 318 319
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

326 327 328 329
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

330
		// Telemetry
C
Christof Marti 已提交
331
		this.sendMachineIdToMain(this.storageService);
332
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
333
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
334 335
			const commit = product.commit;
			const version = pkg.version;
336

337
			const config: ITelemetryServiceConfig = {
338
				appender: new TelemetryAppenderClient(channel),
339
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
340
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
C
Christof Marti 已提交
341
				experiments: instantiationService.invokeFunction(loadExperiments)
342
			};
343

J
Joao Moreno 已提交
344
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
345 346
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
347
			const errorTelemetry = new ErrorTelemetry(telemetryService);
348
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
349

350 351 352 353
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
354
				));
355

356
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
357
		} else {
C
Christof Marti 已提交
358
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
359
			this.telemetryService = NullTelemetryService;
360
		}
E
Erich Gamma 已提交
361

362
		serviceCollection.set(ITelemetryService, this.telemetryService);
363
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
364

365
		this.messageService = instantiationService.createInstance(MessageService, container);
366
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
367
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
368

369
		const lifecycleService = instantiationService.createInstance(LifecycleService);
370
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
371
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
372
		serviceCollection.set(ILifecycleService, lifecycleService);
373
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
374

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

378 379 380
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
381

382
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
383
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
384
		serviceCollection.set(IThreadService, this.threadService);
385

386
		this.timerService.beforeExtensionLoad = Date.now();
387

J
Joao Moreno 已提交
388
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
389 390 391
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
392
			this.timerService.afterExtensionLoad = Date.now();
393
		});
E
Erich Gamma 已提交
394

B
Benjamin Pasero 已提交
395 396 397
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

398
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
399

400 401
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
402

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

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

407
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
408

409
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
410

411
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
412

413
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
414

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

417
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
418

419
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
420

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

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

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

429
		const backupChannel = mainProcessClient.getChannel('backup');
430
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
431

432
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
433 434
	}

C
Christof Marti 已提交
435 436 437 438 439 440
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
	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 {
471
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
472 473 474 475
		if (!errorMsg) {
			return;
		}

476
		const now = Date.now();
E
Erich Gamma 已提交
477 478 479 480 481 482 483 484 485 486 487
		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
488
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
489
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
490 491 492
		}
	}

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

496
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
497 498
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
499
		this.contextViewService.layout();
E
Erich Gamma 已提交
500 501 502 503 504 505 506
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
507
	public dispose(): void {
E
Erich Gamma 已提交
508 509 510

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
511
			this.workbench.dispose();
E
Erich Gamma 已提交
512 513
		}

B
Benjamin Pasero 已提交
514
		this.contextViewService.dispose();
E
Erich Gamma 已提交
515 516

		// Listeners
J
Joao Moreno 已提交
517
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
518 519 520 521

		// Container
		$(this.container).empty();
	}
522
}
523 524

registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
B
Benjamin Pasero 已提交
525 526

	// Foreground
B
Benjamin Pasero 已提交
527
	const windowForeground = theme.getColor(foreground);
528 529 530
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
531

532 533 534 535 536 537
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

538 539 540 541 542 543 544 545 546 547 548
	// List highlight
	const listHighlightForegroundColor = theme.getColor(listHighlightForeground);
	if (listHighlightForegroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
			.monaco-shell .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
				color: ${listHighlightForegroundColor};
			}
		`);
	}

B
Benjamin Pasero 已提交
549
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
550 551 552 553 554 555 556 557 558 559 560 561 562
	let workbenchBackground: string;
	switch (theme.type) {
		case 'dark':
			workbenchBackground = '#252526';
			break;
		case 'light':
			workbenchBackground = '#F3F3F3';
			break;
		default:
			workbenchBackground = '#000000';
	}
	collector.addRule(`.monaco-workbench { background-color: ${workbenchBackground}; }`);

B
Benjamin Pasero 已提交
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
	// Scrollbars
	const scrollbarShadowColor = theme.getColor(scrollbarShadow);
	if (scrollbarShadowColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .shadow.top {
				box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.left {
				box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.top.left {
				box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
			}
		`);
	}

	const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);
	if (scrollbarSliderBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider {
				background: ${scrollbarSliderBackgroundColor};
			}
		`);
	}

	const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);
	if (scrollbarSliderHoverBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider:hover {
				background: ${scrollbarSliderHoverBackgroundColor};
			}
		`);
	}

	const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);
	if (scrollbarSliderActiveBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider.active {
				background: ${scrollbarSliderActiveBackgroundColor};
			}
		`);
	}

	// Focus outline
609
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
610 611 612 613 614 615 616 617
	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,
B
Benjamin Pasero 已提交
618
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
619 620 621 622 623 624 625
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
626
});