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

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

103 104
const currentWindow = remote.getCurrentWindow();

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

E
Erich Gamma 已提交
125
	private container: HTMLElement;
126
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
127 128 129 130 131
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

132
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
133 134
	private workbench: Workbench;

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

138
		this.configuration = configuration;
139

B
Benjamin Pasero 已提交
140 141 142 143 144
		this.contextService = coreServices.contextService;
		this.configurationService = coreServices.configurationService;
		this.environmentService = coreServices.environmentService;
		this.timerService = coreServices.timerService;
		this.storageService = coreServices.storageService;
E
Erich Gamma 已提交
145

146 147
		this.mainProcessServices = mainProcessServices;

E
Erich Gamma 已提交
148 149 150 151 152 153
		this.toUnbind = [];
		this.previousErrorTime = 0;
	}

	private createContents(parent: Builder): Builder {

154
		// ARIA
B
Benjamin Pasero 已提交
155
		aria.setARIAContainer(document.body);
156

E
Erich Gamma 已提交
157
		// Workbench Container
158
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
159 160

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

		// Workbench
164
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection, this.lifecycleService);
165
		try {
B
Benjamin Pasero 已提交
166
			this.workbench.startup().done(startupInfos => this.onWorkbenchStarted(startupInfos, instantiationService));
167 168 169 170 171 172 173 174
		} catch (error) {

			// Print out error
			console.error(toErrorMessage(error, true));

			// Rethrow
			throw error;
		}
E
Erich Gamma 已提交
175

176
		// Window
177
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
178 179

		// Handle case where workbench is not starting up properly
180
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
181 182 183
			console.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
		}, 10000);

184
		this.lifecycleService.when(LifecyclePhase.Running).then(() => {
E
Erich Gamma 已提交
185 186 187 188 189 190
			clearTimeout(timeoutHandle);
		});

		return workbenchContainer;
	}

191
	private onWorkbenchStarted(info: IWorkbenchStartedInfo, instantiationService: IInstantiationService): void {
192

193 194 195 196 197 198 199 200 201 202 203 204 205 206
		// Startup Telemetry
		this.logStartupTelemetry(info);

		// Root Warning
		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'."));
		}

		// Set lifecycle phase to `Runnning` so that other contributions can now do something
		this.lifecycleService.phase = LifecyclePhase.Running;

		// Set lifecycle phase to `Runnning For A Bit` after a short delay
		let timeoutHandle = setTimeout(() => {
			timeoutHandle = void 0;
B
Benjamin Pasero 已提交
207
			this.lifecycleService.phase = LifecyclePhase.Eventually;
208 209 210 211 212 213 214 215 216 217 218
		}, 3000);
		this.toUnbind.push({
			dispose: () => {
				if (timeoutHandle) {
					clearTimeout(timeoutHandle);
				}
			}
		});
	}

	private logStartupTelemetry(info: IWorkbenchStartedInfo): void {
B
Benjamin Pasero 已提交
219
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;
K
kieferrm 已提交
220
		/* __GDPR__
K
kieferrm 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
			"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" }
			}
		*/
242 243 244
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
245
			emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY,
246 247 248
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0,
249
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
250
			theme: this.themeService.getColorTheme().id,
251
			language: platform.language,
252
			experiments: this.experimentService.getExperiments(),
253 254
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
255 256
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
257 258
		});

B
Benjamin Pasero 已提交
259
		// Telemetry: startup metrics
260
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
261 262
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
263
		this.extensionService.whenInstalledExtensionsRegistered().done(() => {
K
kieferrm 已提交
264
			/* __GDPR__
K
kieferrm 已提交
265 266 267 268 269 270
				"startupTime" : {
					"${include}": [
						"${IStartupMetrics}"
					]
				}
			*/
B
Benjamin Pasero 已提交
271
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
272
		});
B
Benjamin Pasero 已提交
273 274
	}

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

278 279 280
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
281
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
282
		serviceCollection.set(ITimerService, this.timerService);
283
		serviceCollection.set(IStorageService, this.storageService);
284 285 286
		this.mainProcessServices.forEach((serviceIdentifier, serviceInstance) => {
			serviceCollection.set(serviceIdentifier, serviceInstance);
		});
287

288
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
289

290 291
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
292

293
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id, this.configuration));
J
Joao Moreno 已提交
294

295
		const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
296
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
297 298 299

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

301 302
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
303
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), browser.getZoomLevel()));
304

B
Benjamin Pasero 已提交
305 306 307
		// Hash
		serviceCollection.set(IHashService, new SyncDescriptor(HashService));

308 309 310 311
		// Experiments
		this.experimentService = instantiationService.createInstance(ExperimentService);
		serviceCollection.set(IExperimentService, this.experimentService);

312
		// Telemetry
313
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
314
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
315 316
			const commit = product.commit;
			const version = pkg.version;
317

318
			const config: ITelemetryServiceConfig = {
319
				appender: new TelemetryAppenderClient(channel),
320
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version, this.environmentService.installSource, this.configuration.machineId),
321
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
322
			};
323

J
Joao Moreno 已提交
324
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
325 326
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
327
			const errorTelemetry = new ErrorTelemetry(telemetryService);
328
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
329

330
			const listener = idleMonitor.onStatusChange(status =>
K
kieferrm 已提交
331
				/* __GDPR__
K
kieferrm 已提交
332 333
					"UserIdleStart" : {}
				*/
K
kieferrm 已提交
334
				/* __GDPR__
K
kieferrm 已提交
335 336
					"UserIdleStop" : {}
				*/
337 338 339
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
340
				));
341

J
Johannes Rieken 已提交
342
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
343
		} else {
344
			this.telemetryService = NullTelemetryService;
345
		}
E
Erich Gamma 已提交
346

347
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
348
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
349

350
		let crashReporterService = NullCrashReporterService;
351
		if (!this.environmentService.disableCrashReporter && product.crashReporter && product.hockeyApp) {
352 353 354 355
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

356
		this.messageService = instantiationService.createInstance(MessageService, container);
357
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
358
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
359

360
		const lifecycleService = instantiationService.createInstance(LifecycleService);
J
Johannes Rieken 已提交
361
		this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
362
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
363
		serviceCollection.set(ILifecycleService, lifecycleService);
J
Johannes Rieken 已提交
364
		disposables.push(lifecycleTelemetry(this.telemetryService, lifecycleService));
365
		this.lifecycleService = lifecycleService;
366

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

370 371
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
372
		disposables.push(extensionEnablementService);
373

374
		this.extensionService = instantiationService.createInstance(ExtensionService);
375
		serviceCollection.set(IExtensionService, this.extensionService);
376 377

		this.timerService.beforeExtensionLoad = Date.now();
378
		this.extensionService.whenInstalledExtensionsRegistered().done(() => {
379
			this.timerService.afterExtensionLoad = Date.now();
380
		});
E
Erich Gamma 已提交
381

B
Benjamin Pasero 已提交
382 383 384
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

385
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
386

387 388
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
389

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

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

394
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
395

396
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
397

398 399
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

400
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
401

402
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
403

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

406
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
407

408
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
409

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

412
		return [instantiationService, serviceCollection];
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 443 444
	}

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

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

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

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

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

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

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

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

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

		// Container
		$(this.container).empty();
	}
492
}
493 494

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

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

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

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

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