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

'use strict';

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

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable, Disposables } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import product from 'vs/platform/node/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
23
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
24
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
25 26
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, loadExperiments, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
J
Johannes Rieken 已提交
27 28 29
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { IdleMonitor, UserStatus } from 'vs/platform/telemetry/browser/idleMonitor';
J
Joao Moreno 已提交
30
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
31
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
32 33
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
34
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
J
Joao Moreno 已提交
35 36 37 38
import { IWindowIPCService, WindowIPCService } from 'vs/workbench/services/window/electron-browser/windowService';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
39
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
40
import { IRequestService } from 'vs/platform/request/node/request';
41
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { MainThreadService } from 'vs/workbench/services/thread/electron-browser/threadService';
import { MarkerService } from 'vs/platform/markers/common/markerService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServiceImpl';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
import { IntegrityServiceImpl } from 'vs/platform/integrity/node/integrityServiceImpl';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
55
import { MainProcessExtensionService } from 'vs/workbench/api/electron-browser/mainThreadExtensionService';
J
Johannes Rieken 已提交
56 57
import { IOptions } from 'vs/workbench/common/options';
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
58
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
59 60 61
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
62
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
63 64
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
65
import { IMessageService, IChoiceService, Severity } 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
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
76 77
import { ICrashReporterService, NullCrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
import { CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
78
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
79 80
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
81
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
82
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
83 84
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
85 86
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
87 88
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
89 90
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
S
Sandeep Somavarapu 已提交
91
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
92
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
93
import { remote, ipcRenderer as ipc } from 'electron';
A
Alex Dima 已提交
94
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
95
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
96
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
97 98
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
99
import 'vs/platform/opener/browser/opener.contribution';
100 101
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
102
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
103
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
104

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

115 116
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

150 151 152 153
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
E
Erich Gamma 已提交
182 183 184
			}
		});

185 186 187
		// Window
		const activeWindow = this.workbench.getInstantiationService().createInstance(ElectronWindow, currentWindow, this.container);
		this.windowIPCService.registerWindow(activeWindow);
E
Erich Gamma 已提交
188 189

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

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

B
Benjamin Pasero 已提交
222
		// Telemetry: startup metrics
223
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
224 225
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
226
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
227
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
228
		});
B
Benjamin Pasero 已提交
229

230
		// Telemetry: workspace tags
231
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
232
		workspaceStats.reportWorkspaceTags(this.options);
K
kieferrm 已提交
233
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
234 235 236 237

		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 已提交
238 239
	}

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

243 244 245
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
246
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
247
		serviceCollection.set(ITimerService, this.timerService);
248

249
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
250

J
Joao Moreno 已提交
251
		// TODO@joao remove this
252 253
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
254

255
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
256 257
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
258
		const windowsChannel = mainProcessClient.getChannel('windows');
259 260
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
261

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

264 265 266 267 268
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

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

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

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

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

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

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

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

311
		serviceCollection.set(ITelemetryService, this.telemetryService);
312
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
313

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

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

324
		const lifecycleService = instantiationService.createInstance(LifecycleService);
325
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
326
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
327
		serviceCollection.set(ILifecycleService, lifecycleService);
328
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
329
		this.lifecycleService = lifecycleService;
330

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

334 335 336
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
337

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

385
		const backupChannel = mainProcessClient.getChannel('backup');
386
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
387

388
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
389 390
	}

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

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

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

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

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

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

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

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

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

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

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

		// Container
		$(this.container).empty();
	}
478
}
479 480

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

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

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

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

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