shell.ts 27.8 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, StartupKind } 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
import { stopTimer } from 'vs/base/node/startupTimers';
105

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

116 117
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

151 152 153 154
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

			if (platform.isWindows) {
J
Joao Moreno 已提交
178
				submitURL = product.hockeyApp[`win32-${process.arch}`];
J
Joao Moreno 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
			} 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 已提交
194 195 196
		}

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

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

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

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

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

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

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

246 247 248 249
		if (this.lifecycleService.startupKind === StartupKind.NewWindow) {
			stopTimer('elapsed:overall');
		}

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

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

264
		// Telemetry: workspace tags
265
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
266
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
267
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
268 269 270 271

		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 已提交
272 273
	}

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

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

287 288 289
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
290
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
291
		serviceCollection.set(ITimerService, this.timerService);
292

293
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
294

J
Joao Moreno 已提交
295
		// TODO@joao remove this
296 297
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
298

299
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
300 301
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
302
		const windowsChannel = mainProcessClient.getChannel('windows');
303 304
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
305

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

308 309 310 311 312
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

319 320 321 322
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

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

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

J
Joao Moreno 已提交
337
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
338 339
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
340
			const errorTelemetry = new ErrorTelemetry(telemetryService);
341
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
342

343 344 345 346
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
347
				));
348

349
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
350
		} else {
C
Christof Marti 已提交
351
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
352
			this.telemetryService = NullTelemetryService;
353
		}
E
Erich Gamma 已提交
354

355
		serviceCollection.set(ITelemetryService, this.telemetryService);
356
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
357

358
		this.messageService = instantiationService.createInstance(MessageService, container);
359
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
360
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
361

362
		const lifecycleService = instantiationService.createInstance(LifecycleService);
363
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
364
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
365
		serviceCollection.set(ILifecycleService, lifecycleService);
366
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
367
		this.lifecycleService = lifecycleService;
368

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

372 373 374
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
375

376
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
377
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
378
		serviceCollection.set(IThreadService, this.threadService);
379

380
		this.timerService.beforeExtensionLoad = Date.now();
381

J
Joao Moreno 已提交
382
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
383 384 385
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
386
			this.timerService.afterExtensionLoad = Date.now();
387
		});
E
Erich Gamma 已提交
388

B
Benjamin Pasero 已提交
389 390 391
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

392
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
393

394 395
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
396

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

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

401
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
402

403
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
404

405
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
406

407
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
408

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

411
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
412

413
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
414

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

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

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

423
		const backupChannel = mainProcessClient.getChannel('backup');
424
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
425

426
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
427 428
	}

C
Christof Marti 已提交
429 430 431 432 433 434
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

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

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

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

490
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
491 492
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
493
		this.contextViewService.layout();
E
Erich Gamma 已提交
494 495 496 497 498 499 500
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
501
	public dispose(): void {
E
Erich Gamma 已提交
502 503 504

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
505
			this.workbench.dispose();
E
Erich Gamma 已提交
506 507
		}

B
Benjamin Pasero 已提交
508
		this.contextViewService.dispose();
E
Erich Gamma 已提交
509 510

		// Listeners
J
Joao Moreno 已提交
511
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
512 513 514 515

		// Container
		$(this.container).empty();
	}
516
}
517 518

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

	// Foreground
B
Benjamin Pasero 已提交
521
	const windowForeground = theme.getColor(foreground);
522 523 524
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
525

526 527 528 529 530 531
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

532 533 534 535 536 537 538
	// 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}; }`);
	}

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