shell.ts 26.1 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 25
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
26 27 28
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 已提交
29
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
30
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
31 32
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
33
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
34
import { IWindowIPCService, WindowIPCService } from 'vs/workbench/services/window/electron-browser/windowService';
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';
J
Johannes Rieken 已提交
55 56
import { IOptions } from 'vs/workbench/common/options';
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
57
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
58 59 60
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
61
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
62 63
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
64
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
65 66 67 68 69
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';
70
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
71
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
72
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
73 74
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
75 76
import { ICrashReporterService, NullCrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
import { CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
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';
S
Sandeep Somavarapu 已提交
88
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
89
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
90
import { remote, ipcRenderer as ipc } from 'electron';
91
import { ITextMateService } from 'vs/workbench/parts/codeEditor/electron-browser/textMate/textMateService';
92
import { MainProcessTextMateSyntax } from 'vs/workbench/parts/codeEditor/electron-browser/textMate/TMSyntax';
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
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
100
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
101

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

113 114
const currentWindow = remote.getCurrentWindow();

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

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

142
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
143 144 145
	private options: IOptions;
	private workbench: Workbench;

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

149
		this.configuration = configuration;
150 151 152 153
		this.options = options;

		this.contextService = services.contextService;
		this.configurationService = services.configurationService;
154
		this.environmentService = services.environmentService;
B
Benjamin Pasero 已提交
155
		this.timerService = services.timerService;
156
		this.storageService = services.storageService;
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

		// Workbench
174
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, this.options, serviceCollection);
E
Erich Gamma 已提交
175
		this.workbench.startup({
176
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
177 178

				// run workbench started logic
B
Benjamin Pasero 已提交
179
				this.onWorkbenchStarted(info);
180 181 182

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
183 184 185 186

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

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

		// Handle case where workbench is not starting up properly
195
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
196 197 198 199 200 201 202 203 204 205
			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 已提交
206
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
207 208

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

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

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

		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 已提交
243 244
	}

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

248 249 250
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
251
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
252
		serviceCollection.set(ITimerService, this.timerService);
253
		serviceCollection.set(IStorageService, this.storageService);
254

255
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
256

J
Joao Moreno 已提交
257
		// TODO@joao remove this
258 259
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
260

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

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

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

270 271 272 273 274
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

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

287
			const config: ITelemetryServiceConfig = {
288
				appender: new TelemetryAppenderClient(channel),
289
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
290
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
C
Christof Marti 已提交
291
				experiments: instantiationService.invokeFunction(loadExperiments)
292
			};
293

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

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

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

J
Johannes Rieken 已提交
306
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
307
		} else {
C
Christof Marti 已提交
308
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
309
			this.telemetryService = NullTelemetryService;
310
		}
E
Erich Gamma 已提交
311

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

368
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
369

370
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
371

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

374
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
375

376
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
377

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

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

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

386
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
387 388
	}

C
Christof Marti 已提交
389 390 391 392 393 394
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

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

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

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

450
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
451 452
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
453
		this.contextViewService.layout();
E
Erich Gamma 已提交
454 455 456 457 458 459 460
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
461
	public dispose(): void {
E
Erich Gamma 已提交
462 463 464

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
465
			this.workbench.dispose();
E
Erich Gamma 已提交
466 467
		}

B
Benjamin Pasero 已提交
468
		this.contextViewService.dispose();
E
Erich Gamma 已提交
469 470

		// Listeners
J
Joao Moreno 已提交
471
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
472 473 474 475

		// Container
		$(this.container).empty();
	}
476
}
477 478

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

	// Foreground
B
Benjamin Pasero 已提交
481
	const windowForeground = theme.getColor(foreground);
482 483 484
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
485

486 487 488 489 490 491
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

492 493 494 495 496 497 498
	// 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}; }`);
	}

499 500 501 502 503 504 505 506 507 508 509
	// 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 已提交
510
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
511 512 513 514 515 516 517 518 519 520 521 522 523
	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 已提交
524 525 526 527 528 529 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
	// 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
570
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
571 572 573 574 575 576 577 578
	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 已提交
579
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
580 581 582 583 584 585 586
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
587
});