shell.ts 26.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 } 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 { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
25 26
import { NullTelemetryService, configurationTelemetry, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { loadExperiments } from 'vs/platform/telemetry/common/experiments';
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';
35
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
36 37
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
38
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
39
import { IRequestService } from 'vs/platform/request/node/request';
40
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53
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';
54
import { MainProcessExtensionService } from 'vs/workbench/api/electron-browser/mainThreadExtensionService';
B
Benjamin Pasero 已提交
55 56
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspacesIpc';
J
Johannes Rieken 已提交
57 58
import { IOptions } from 'vs/workbench/common/options';
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
59
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
60 61 62
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
63
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
64 65
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
66
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
67 68 69 70 71
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
72
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
73
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
74
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
75 76
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
77 78
import { ICrashReporterService, NullCrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
import { CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
79
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
80 81
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
82
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
83
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
84 85
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
86 87
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
88 89
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
S
Sandeep Somavarapu 已提交
90
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
91
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
92
import { remote, ipcRenderer as ipc } from 'electron';
93
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
94 95
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
96
import 'vs/platform/opener/browser/opener.contribution';
97 98
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
99 100
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
101
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
102
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
103 104
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
105
import { IBroadcastService, BroadcastService } from "vs/platform/broadcast/electron-browser/broadcastService";
106

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

118 119
const currentWindow = remote.getCurrentWindow();

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

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

147
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
148 149 150
	private options: IOptions;
	private workbench: Workbench;

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

154
		this.configuration = configuration;
155 156 157 158
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

169
		// ARIA
B
Benjamin Pasero 已提交
170
		aria.setARIAContainer(document.body);
171

E
Erich Gamma 已提交
172
		// Workbench Container
173
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
174 175

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

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

				// run workbench started logic
B
Benjamin Pasero 已提交
184
				this.onWorkbenchStarted(info);
185 186 187

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
188 189 190 191

				// Set lifecycle phase to `Runnning` so that other contributions
				// can now do something
				this.lifecycleService.phase = LifecyclePhase.Running;
E
Erich Gamma 已提交
192 193 194
			}
		});

195
		// Window
196
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
197 198

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

B
Benjamin Pasero 已提交
210
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
211 212

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

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

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

		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 已提交
247 248
	}

249
	private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
J
Johannes Rieken 已提交
250
		const disposables: IDisposable[] = [];
J
Joao Moreno 已提交
251

252 253 254
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
255
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
256
		serviceCollection.set(ITimerService, this.timerService);
257
		serviceCollection.set(IStorageService, this.storageService);
258

259
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
260

261 262
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
263

264
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
J
Johannes Rieken 已提交
265
		disposables.push(mainProcessClient);
266

J
Joao Moreno 已提交
267
		const windowsChannel = mainProcessClient.getChannel('windows');
268 269
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
270

271
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id));
J
Joao Moreno 已提交
272

273
		const sharedProcess = this.windowsService.whenSharedProcessReady()
274
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
275 276 277

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

279 280 281 282
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

283
		// Telemetry
C
Christof Marti 已提交
284
		this.sendMachineIdToMain(this.storageService);
285
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
286
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
287 288
			const commit = product.commit;
			const version = pkg.version;
289

290
			const config: ITelemetryServiceConfig = {
291
				appender: new TelemetryAppenderClient(channel),
292
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
293
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
294
			};
295

J
Joao Moreno 已提交
296
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
297 298
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
299
			const errorTelemetry = new ErrorTelemetry(telemetryService);
300
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
301

302 303 304 305
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
306
				));
307

J
Johannes Rieken 已提交
308
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
309
		} else {
310
			this.telemetryService = NullTelemetryService;
311
		}
E
Erich Gamma 已提交
312

313
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
314
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
315

316 317 318 319 320 321
		let crashReporterService = NullCrashReporterService;
		if (product.crashReporter && product.hockeyApp) {
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

322
		this.messageService = instantiationService.createInstance(MessageService, container);
323
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
324
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
325

326
		const lifecycleService = instantiationService.createInstance(LifecycleService);
J
Johannes Rieken 已提交
327
		this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
328
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
329
		serviceCollection.set(ILifecycleService, lifecycleService);
J
Johannes Rieken 已提交
330
		disposables.push(lifecycleTelemetry(this.telemetryService, lifecycleService));
331
		this.lifecycleService = lifecycleService;
332

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

336 337
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
338
		disposables.push(extensionEnablementService);
339

340
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
341
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
342
		serviceCollection.set(IThreadService, this.threadService);
343

344
		this.timerService.beforeExtensionLoad = Date.now();
345

J
Joao Moreno 已提交
346
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
347 348 349
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
350
			this.timerService.afterExtensionLoad = Date.now();
351
		});
E
Erich Gamma 已提交
352

B
Benjamin Pasero 已提交
353 354 355
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

356
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
357

358 359
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
360

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

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

365
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
366

367
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
368

369 370
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

371
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
372

373
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
374

375
		serviceCollection.set(ITextMateService, new SyncDescriptor(TextMateService));
A
Alex Dima 已提交
376

377
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
378

379
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
380

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

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

J
Joao Moreno 已提交
386
		const urlChannel = mainProcessClient.getChannel('url');
387
		serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, currentWindow.id));
J
Joao Moreno 已提交
388

B
Benjamin Pasero 已提交
389 390 391
		const workspacesChannel = mainProcessClient.getChannel('workspaces');
		serviceCollection.set(IWorkspacesService, new SyncDescriptor(WorkspacesChannelClient, workspacesChannel));

392
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
393 394
	}

C
Christof Marti 已提交
395 396 397 398 399 400
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
	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 {
431
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
432 433 434 435
		if (!errorMsg) {
			return;
		}

436
		const now = Date.now();
E
Erich Gamma 已提交
437 438 439 440 441 442 443 444 445 446 447
		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
448
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
449
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
450 451 452
		}
	}

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

456
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
457 458
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
459
		this.contextViewService.layout();
E
Erich Gamma 已提交
460 461 462 463 464 465 466
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
467
	public dispose(): void {
E
Erich Gamma 已提交
468 469 470

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
471
			this.workbench.dispose();
E
Erich Gamma 已提交
472 473
		}

B
Benjamin Pasero 已提交
474
		this.contextViewService.dispose();
E
Erich Gamma 已提交
475 476

		// Listeners
J
Joao Moreno 已提交
477
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
478 479 480 481

		// Container
		$(this.container).empty();
	}
482
}
483 484

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

	// Foreground
B
Benjamin Pasero 已提交
487
	const windowForeground = theme.getColor(foreground);
488 489 490
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
491

492 493 494 495 496 497
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

498 499 500 501 502 503 504
	// 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}; }`);
	}

505 506 507 508 509 510 511 512 513 514 515
	// 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 已提交
516
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
517 518 519 520 521 522 523 524 525 526 527 528 529
	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 已提交
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
	// 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
576
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
577 578 579 580 581 582 583 584
	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 已提交
585
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
586 587 588 589 590 591 592
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
593
});