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

'use strict';

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

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable, Disposables } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import product from 'vs/platform/node/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
23
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
24
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
25 26
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
27 28 29
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 已提交
30
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
31
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
32 33
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
34
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
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';
55
import { MainProcessExtensionService } from 'vs/workbench/api/electron-browser/mainThreadExtensionService';
J
Johannes Rieken 已提交
56 57
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
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
62
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
63 64
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
65
import { IMessageService, IChoiceService, Severity, CloseAction } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
66 67 68 69 70
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';
C
Christof Marti 已提交
93
import { remote, ipcRenderer as ipc } 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
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
97 98
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
99
import 'vs/platform/opener/browser/opener.contribution';
100 101
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
102
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
103
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
104

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

115 116
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
117
/**
B
Benjamin Pasero 已提交
118
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
119 120 121
 * With the Shell being the top level element in the page, it is also responsible for driving the layouting.
 */
export class WorkbenchShell {
B
Benjamin Pasero 已提交
122
	private storageService: IStorageService;
123
	private messageService: MessageService;
J
Johannes Rieken 已提交
124
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
125 126
	private contextViewService: ContextViewService;
	private threadService: MainThreadService;
127 128
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
129
	private telemetryService: ITelemetryService;
130
	private extensionService: MainProcessExtensionService;
131
	private windowsService: IWindowsService;
132
	private windowIPCService: IWindowIPCService;
B
Benjamin Pasero 已提交
133
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
134
	private themeService: WorkbenchThemeService;
135
	private lifecycleService: ILifecycleService;
E
Erich Gamma 已提交
136 137

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

	private options: IOptions;
	private workbench: Workbench;

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

150 151 152 153
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

		//crash reporting
J
Joao Moreno 已提交
173 174 175 176
		if (product.crashReporter && product.hockeyApp) {
			let submitURL: string;

			if (platform.isWindows) {
J
Joao Moreno 已提交
177
				submitURL = product.hockeyApp[`win32-${process.arch}`];
J
Joao Moreno 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
			} else if (platform.isMacintosh) {
				submitURL = product.hockeyApp.darwin;
			} else if (platform.isLinux) {
				submitURL = product.hockeyApp[`linux-${process.arch}`];
			}

			if (submitURL) {
				const opts: Electron.CrashReporterStartOptions = {
					companyName: product.crashReporter.companyName,
					productName: product.crashReporter.productName,
					submitURL
				};

				instantiationService.createInstance(CrashReporter, opts);
			}
E
Erich Gamma 已提交
193 194 195
		}

		// Workbench
196
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.options, serviceCollection);
E
Erich Gamma 已提交
197
		this.workbench.startup({
198
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
199 200

				// run workbench started logic
201
				this.onWorkbenchStarted(instantiationService, info);
202 203 204

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
E
Erich Gamma 已提交
205 206 207
			}
		});

208 209 210
		// Window
		const activeWindow = this.workbench.getInstantiationService().createInstance(ElectronWindow, currentWindow, this.container);
		this.windowIPCService.registerWindow(activeWindow);
E
Erich Gamma 已提交
211 212

		// Handle case where workbench is not starting up properly
213
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
214 215 216 217 218 219 220 221 222 223
			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;
	}

224
	private onWorkbenchStarted(instantiationService: IInstantiationService, info: IWorkbenchStartedInfo): void {
225 226

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
227
		const { filesToOpen, filesToCreate, filesToDiff } = this.options;
228 229 230
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
B
Benjamin Pasero 已提交
231
			emptyWorkbench: !this.contextService.hasWorkspace(),
232 233 234
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || undefined,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || undefined,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || undefined,
235
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
236
			theme: this.themeService.getColorTheme().id,
237
			language: platform.language,
238
			experiments: this.telemetryService.getExperiments(),
239 240
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
241 242
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
243 244
		});

B
Benjamin Pasero 已提交
245
		// Telemetry: startup metrics
246
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
247 248
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
249
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
250
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
251 252 253 254 255 256

			// 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);
			}
257
		});
B
Benjamin Pasero 已提交
258

259
		// Telemetry: workspace tags
260
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
261
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
262
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
263 264 265 266

		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'."));
		}
B
Benjamin Pasero 已提交
267 268
	}

269 270
	private handleNegativePerformanceNumbers(i: IInstantiationService, time: number): void {
		this.messageService.show(Severity.Warning, {
271
			message: `Something went wrong measuring startup performance numbers (ellapsed: ${time}ms). We would like to learn more about this issue.`,
272 273 274 275 276 277 278
			actions: [
				i.createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL),
				CloseAction
			]
		});
	}

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
		this.lifecycleService = lifecycleService;
363

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

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

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

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

J
Joao Moreno 已提交
377
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
378 379 380
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
381
			this.timerService.afterExtensionLoad = Date.now();
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
}
512 513

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

	// Foreground
B
Benjamin Pasero 已提交
516
	const windowForeground = theme.getColor(foreground);
517 518 519
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
520

521 522 523 524 525 526
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

527 528 529 530 531 532 533
	// Input placeholder
	const placeholderForeground = theme.getColor(inputPlaceholderForeground);
	if (placeholderForeground) {
		collector.addRule(`.monaco-shell input::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
		collector.addRule(`.monaco-shell textarea::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
	}

534 535 536 537 538 539 540 541 542 543 544
	// 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 已提交
545
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
546 547 548 549 550 551 552 553 554 555 556 557 558
	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 已提交
559 560 561 562 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
	// 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
605
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
606 607 608 609 610 611 612 613
	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 已提交
614
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
615 616 617 618 619 620 621
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
622
});