shell.ts 26.7 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 76
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { CrashReporter } from 'vs/workbench/electron-browser/crashReporter';
77
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
78 79
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
80
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
81
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
82 83
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
84 85
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
86 87
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
88 89
import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc';
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';
A
Alex Dima 已提交
93
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
94
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
95
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
96 97
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
98
import 'vs/platform/opener/browser/opener.contribution';
99 100
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
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 105 106 107 108 109
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
110
	environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
111
	timerService: ITimerService;
112 113
}

114 115
const currentWindow = remote.getCurrentWindow();

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

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

	private options: IOptions;
	private workbench: Workbench;

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

149 150 151 152
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

			if (platform.isWindows) {
J
Joao Moreno 已提交
176
				submitURL = product.hockeyApp[`win32-${process.arch}`];
J
Joao Moreno 已提交
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
			} else if (platform.isMacintosh) {
				submitURL = product.hockeyApp.darwin;
			} else if (platform.isLinux) {
				submitURL = product.hockeyApp[`linux-${process.arch}`];
			}

			if (submitURL) {
				const opts: Electron.CrashReporterStartOptions = {
					companyName: product.crashReporter.companyName,
					productName: product.crashReporter.productName,
					submitURL
				};

				instantiationService.createInstance(CrashReporter, opts);
			}
E
Erich Gamma 已提交
192 193 194
		}

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

				// run workbench started logic
B
Benjamin Pasero 已提交
200
				this.onWorkbenchStarted(info);
201 202 203

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

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

		// Handle case where workbench is not starting up properly
212
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
213 214 215 216 217 218 219 220 221 222
			console.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
		}, 10000);

		this.workbench.joinCreation().then(() => {
			clearTimeout(timeoutHandle);
		});

		return workbenchContainer;
	}

B
Benjamin Pasero 已提交
223
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
224 225

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

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

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

		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 已提交
260 261
	}

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

265 266 267
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
268
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
269
		serviceCollection.set(ITimerService, this.timerService);
270

271
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
272

J
Joao Moreno 已提交
273
		// TODO@joao remove this
274 275
		this.windowIPCService = instantiationService.createInstance<IWindowIPCService>(WindowIPCService);
		serviceCollection.set(IWindowIPCService, this.windowIPCService);
276

277
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
278 279
		disposables.add(mainProcessClient);

J
Joao Moreno 已提交
280
		const windowsChannel = mainProcessClient.getChannel('windows');
281 282
		this.windowsService = new WindowsChannelClient(windowsChannel);
		serviceCollection.set(IWindowsService, this.windowsService);
J
Joao Moreno 已提交
283

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

286 287 288 289 290
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowIPCService.getWindowId()}`));

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

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

297 298 299 300
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

301
		// Telemetry
C
Christof Marti 已提交
302
		this.sendMachineIdToMain(this.storageService);
303
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
304
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
305 306
			const commit = product.commit;
			const version = pkg.version;
307

308
			const config: ITelemetryServiceConfig = {
309
				appender: new TelemetryAppenderClient(channel),
310
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
311
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
C
Christof Marti 已提交
312
				experiments: instantiationService.invokeFunction(loadExperiments)
313
			};
314

J
Joao Moreno 已提交
315
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
316 317
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
318
			const errorTelemetry = new ErrorTelemetry(telemetryService);
319
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
320

321 322 323 324
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
325
				));
326

327
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
328
		} else {
C
Christof Marti 已提交
329
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
330
			this.telemetryService = NullTelemetryService;
331
		}
E
Erich Gamma 已提交
332

333
		serviceCollection.set(ITelemetryService, this.telemetryService);
334
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
335

336
		this.messageService = instantiationService.createInstance(MessageService, container);
337
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
338
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
339

340
		const lifecycleService = instantiationService.createInstance(LifecycleService);
341
		this.toUnbind.push(lifecycleService.onShutdown(reason => disposables.dispose()));
342
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
343
		serviceCollection.set(ILifecycleService, lifecycleService);
344
		disposables.add(lifecycleTelemetry(this.telemetryService, lifecycleService));
345
		this.lifecycleService = lifecycleService;
346

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

350 351 352
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
		disposables.add(extensionEnablementService);
353

354
		const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
355
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
356
		serviceCollection.set(IThreadService, this.threadService);
357

358
		this.timerService.beforeExtensionLoad = Date.now();
359

J
Joao Moreno 已提交
360
		this.extensionService = instantiationService.createInstance(MainProcessExtensionService);
361 362 363
		serviceCollection.set(IExtensionService, this.extensionService);
		extensionHostProcessWorker.start(this.extensionService);
		this.extensionService.onReady().done(() => {
364
			this.timerService.afterExtensionLoad = Date.now();
365
		});
E
Erich Gamma 已提交
366

B
Benjamin Pasero 已提交
367 368 369
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

370
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
371

372 373
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
374

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

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

379
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
380

381
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
382

383
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
384

385
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
386

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

389
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
390

391
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
392

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

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

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

401
		const backupChannel = mainProcessClient.getChannel('backup');
402
		serviceCollection.set(IBackupService, new SyncDescriptor(BackupChannelClient, backupChannel));
403

404
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
405 406
	}

C
Christof Marti 已提交
407 408 409 410 411 412
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
	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 {
443
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
444 445 446 447
		if (!errorMsg) {
			return;
		}

448
		const now = Date.now();
E
Erich Gamma 已提交
449 450 451 452 453 454 455 456 457 458 459
		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
460
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
461
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
462 463 464
		}
	}

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

468
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
469 470
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
471
		this.contextViewService.layout();
E
Erich Gamma 已提交
472 473 474 475 476 477 478
		this.workbench.layout();
	}

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

B
Benjamin Pasero 已提交
479
	public dispose(): void {
E
Erich Gamma 已提交
480 481 482

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
483
			this.workbench.dispose();
E
Erich Gamma 已提交
484 485
		}

B
Benjamin Pasero 已提交
486
		this.contextViewService.dispose();
E
Erich Gamma 已提交
487 488

		// Listeners
J
Joao Moreno 已提交
489
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
490 491 492 493

		// Container
		$(this.container).empty();
	}
494
}
495 496

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

	// Foreground
B
Benjamin Pasero 已提交
499
	const windowForeground = theme.getColor(foreground);
500 501 502
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
503

504 505 506 507 508 509
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

510 511 512 513 514 515 516
	// 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}; }`);
	}

517 518 519 520 521 522 523 524 525 526 527
	// 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 已提交
528
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
529 530 531 532 533 534 535 536 537 538 539 540 541
	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 已提交
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 576 577 578 579 580 581 582 583 584 585 586 587
	// 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
588
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
589 590 591 592 593 594 595 596
	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 已提交
597
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
598 599 600 601 602 603 604
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
605
});