shell.ts 27.3 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 62 63 64
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';
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;
E
Erich Gamma 已提交
135 136

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

	private options: IOptions;
	private workbench: Workbench;

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

149 150 151 152
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

		//crash reporting
J
Joao Moreno 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
		if (product.crashReporter && product.hockeyApp) {
			let submitURL: string;

			if (platform.isWindows) {
				submitURL = product.hockeyApp.win32;
			} 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 已提交
192 193 194
		}

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

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

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

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

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

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

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

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

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

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

		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 已提交
263 264
	}

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

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

278 279 280
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
281
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
282
		serviceCollection.set(ITimerService, this.timerService);
283

284
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
285

J
Joao Moreno 已提交
286
		// TODO@joao remove this
287 288
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
289

290
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
291 292
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
293
		const windowsChannel = mainProcessClient.getChannel('windows');
294 295
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
296

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

299 300 301 302 303
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

310 311 312 313
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

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

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

J
Joao Moreno 已提交
328
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
329 330
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
331
			const errorTelemetry = new ErrorTelemetry(telemetryService);
332
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
333

334 335 336 337
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
338
				));
339

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

346
		serviceCollection.set(ITelemetryService, this.telemetryService);
347
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
348

349
		this.messageService = instantiationService.createInstance(MessageService, container);
350
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
351
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
352

353
		const lifecycleService = instantiationService.createInstance(LifecycleService);
354
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
355
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
356
		serviceCollection.set(ILifecycleService, lifecycleService);
357
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
358

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

362 363 364
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
365

366
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
367
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
368
		serviceCollection.set(IThreadService, this.threadService);
369

370
		this.timerService.beforeExtensionLoad = Date.now();
371

J
Joao Moreno 已提交
372
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
373 374 375
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
376
			this.timerService.afterExtensionLoad = Date.now();
377
		});
E
Erich Gamma 已提交
378

B
Benjamin Pasero 已提交
379 380 381
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

382
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
383

384 385
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
386

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

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

391
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
392

393
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
394

395
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
396

397
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
398

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

401
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
402

403
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
404

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

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

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

413
		const backupChannel = mainProcessClient.getChannel('backup');
414
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
415

416
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
417 418
	}

C
Christof Marti 已提交
419 420 421 422 423 424
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
425 426 427 428 429 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
	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 {
455
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
456 457 458 459
		if (!errorMsg) {
			return;
		}

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

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

480
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
481 482
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
483
		this.contextViewService.layout();
E
Erich Gamma 已提交
484 485 486 487 488 489 490
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
491
	public dispose(): void {
E
Erich Gamma 已提交
492 493 494

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
495
			this.workbench.dispose();
E
Erich Gamma 已提交
496 497
		}

B
Benjamin Pasero 已提交
498
		this.contextViewService.dispose();
E
Erich Gamma 已提交
499 500

		// Listeners
J
Joao Moreno 已提交
501
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
502 503 504 505

		// Container
		$(this.container).empty();
	}
506
}
507 508

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

	// Foreground
B
Benjamin Pasero 已提交
511
	const windowForeground = theme.getColor(foreground);
512 513 514
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
515

516 517 518 519 520 521
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

522 523 524 525 526 527 528
	// 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}; }`);
	}

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