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

'use strict';

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

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import product from 'vs/platform/node/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
23
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
24
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
25
import { NullTelemetryService, configurationTelemetry, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
26
import { IExperimentService, ExperimentService } from 'vs/platform/telemetry/common/experiments';
J
Johannes Rieken 已提交
27 28 29
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { IdleMonitor, UserStatus } from 'vs/platform/telemetry/browser/idleMonitor';
J
Joao Moreno 已提交
30
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
31
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
32 33
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
34
import { WorkspaceStats } from 'vs/workbench/services/telemetry/node/workspaceStats';
35
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
36
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
37
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
38
import { IRequestService } from 'vs/platform/request/node/request';
39
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
40 41 42 43 44 45 46 47 48 49 50 51
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 { 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';
52
import { ExtensionService } from 'vs/workbench/services/extensions/electron-browser/extensionService';
J
Johannes Rieken 已提交
53
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
54
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
55 56 57
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
S
Sandeep Somavarapu 已提交
58
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
59 60
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
61
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
62 63 64 65
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
66
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
67
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
68
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
69 70
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
71
import { ICrashReporterService, NullCrashReporterService, CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
72
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
73 74 75
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
76 77
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
B
Benjamin Pasero 已提交
78
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
79
import { remote, ipcRenderer as ipc } from 'electron';
80
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
81 82
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
83
import 'vs/platform/opener/browser/opener.contribution';
84 85
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
86 87
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
88
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
89
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
90 91
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
92
import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService';
B
Benjamin Pasero 已提交
93 94
import { HashService } from 'vs/workbench/services/hash/node/hashService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
95

96 97 98 99 100 101
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
102
	environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
103
	timerService: ITimerService;
104
	storageService: IStorageService;
105 106
}

107 108
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
109
/**
B
Benjamin Pasero 已提交
110
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
111 112 113
 * 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 已提交
114
	private storageService: IStorageService;
115
	private messageService: MessageService;
J
Johannes Rieken 已提交
116
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
117
	private contextViewService: ContextViewService;
118 119
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
120
	private telemetryService: ITelemetryService;
121
	private experimentService: IExperimentService;
122
	private extensionService: ExtensionService;
123
	private broadcastService: IBroadcastService;
B
Benjamin Pasero 已提交
124
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
125
	private themeService: WorkbenchThemeService;
126
	private lifecycleService: LifecycleService;
127 128
	private mainProcessServices: ServiceCollection;

E
Erich Gamma 已提交
129
	private container: HTMLElement;
130
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
131 132 133 134 135
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

136
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
137 138
	private workbench: Workbench;

B
Benjamin Pasero 已提交
139
	constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, configuration: IWindowConfiguration) {
E
Erich Gamma 已提交
140 141
		this.container = container;

142
		this.configuration = configuration;
143

B
Benjamin Pasero 已提交
144 145 146 147 148
		this.contextService = coreServices.contextService;
		this.configurationService = coreServices.configurationService;
		this.environmentService = coreServices.environmentService;
		this.timerService = coreServices.timerService;
		this.storageService = coreServices.storageService;
E
Erich Gamma 已提交
149

150 151
		this.mainProcessServices = mainProcessServices;

E
Erich Gamma 已提交
152 153 154 155 156 157
		this.toUnbind = [];
		this.previousErrorTime = 0;
	}

	private createContents(parent: Builder): Builder {

158
		// ARIA
B
Benjamin Pasero 已提交
159
		aria.setARIAContainer(document.body);
160

E
Erich Gamma 已提交
161
		// Workbench Container
162
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
163 164

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

		// Workbench
B
Benjamin Pasero 已提交
168
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection);
E
Erich Gamma 已提交
169
		this.workbench.startup({
170
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
171 172

				// run workbench started logic
B
Benjamin Pasero 已提交
173
				this.onWorkbenchStarted(info);
174 175 176

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
177 178 179 180

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

184
		// Window
185
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
186 187

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

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
202
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;
K
kieferrm 已提交
203
		/* __GDPR__
K
kieferrm 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
			"workspaceLoad" : {
				"userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" },
				"experiments": { "${inline}": [ "${IExperiments}" ] },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
			}
		*/
225 226 227
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
228
			emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY,
229 230 231
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0,
232
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
233
			theme: this.themeService.getColorTheme().id,
234
			language: platform.language,
235
			experiments: this.experimentService.getExperiments(),
236 237
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
238 239
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
240 241
		});

B
Benjamin Pasero 已提交
242
		// Telemetry: startup metrics
243
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
244 245
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
246
		this.extensionService.onReady().done(() => {
K
kieferrm 已提交
247
			/* __GDPR__
K
kieferrm 已提交
248 249 250 251 252 253
				"startupTime" : {
					"${include}": [
						"${IStartupMetrics}"
					]
				}
			*/
B
Benjamin Pasero 已提交
254
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
255
		});
B
Benjamin Pasero 已提交
256

257
		// Telemetry: workspace tags
258
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
B
Benjamin Pasero 已提交
259
		workspaceStats.reportWorkspaceTags(this.configuration);
K
kieferrm 已提交
260
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
261 262 263 264

		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 已提交
265 266
	}

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

270 271 272
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
273
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
274
		serviceCollection.set(ITimerService, this.timerService);
275
		serviceCollection.set(IStorageService, this.storageService);
276 277 278
		this.mainProcessServices.forEach((serviceIdentifier, serviceInstance) => {
			serviceCollection.set(serviceIdentifier, serviceInstance);
		});
279

280
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
281

282 283
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
284

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

287
		const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
288
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
289 290 291

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

293 294 295 296
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

B
Benjamin Pasero 已提交
297 298 299
		// Hash
		serviceCollection.set(IHashService, new SyncDescriptor(HashService));

300 301 302 303
		// Experiments
		this.experimentService = instantiationService.createInstance(ExperimentService);
		serviceCollection.set(IExperimentService, this.experimentService);

304
		// Telemetry
C
Christof Marti 已提交
305
		this.sendMachineIdToMain(this.storageService);
306
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
307
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
308 309
			const commit = product.commit;
			const version = pkg.version;
310

311
			const config: ITelemetryServiceConfig = {
312
				appender: new TelemetryAppenderClient(channel),
313
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version, this.environmentService.installSource),
314
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
315
			};
316

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

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

323
			const listener = idleMonitor.onStatusChange(status =>
K
kieferrm 已提交
324
				/* __GDPR__
K
kieferrm 已提交
325 326
					"UserIdleStart" : {}
				*/
K
kieferrm 已提交
327
				/* __GDPR__
K
kieferrm 已提交
328 329
					"UserIdleStop" : {}
				*/
330 331 332
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
333
				));
334

J
Johannes Rieken 已提交
335
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
336
		} else {
337
			this.telemetryService = NullTelemetryService;
338
		}
E
Erich Gamma 已提交
339

340
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
341
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
342

343
		let crashReporterService = NullCrashReporterService;
344
		if (!this.environmentService.disableCrashReporter && product.crashReporter && product.hockeyApp) {
345 346 347 348
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

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

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

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

363 364
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
365
		disposables.push(extensionEnablementService);
366

367
		this.extensionService = instantiationService.createInstance(ExtensionService);
368
		serviceCollection.set(IExtensionService, this.extensionService);
369 370

		this.timerService.beforeExtensionLoad = Date.now();
371
		this.extensionService.onReady().done(() => {
372
			this.timerService.afterExtensionLoad = Date.now();
373
		});
E
Erich Gamma 已提交
374

B
Benjamin Pasero 已提交
375 376 377
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

378
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
379

380 381
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
382

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

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

387
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
388

389
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
390

391 392
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

393
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
394

395
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
396

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

399
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
400

401
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
402

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

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

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

E
Erich Gamma 已提交
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 443
	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 {
444
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
445 446 447 448
		if (!errorMsg) {
			return;
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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