shell.ts 27.2 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
import { IWindowIPCService, WindowIPCService } from 'vs/workbench/services/window/electron-browser/windowService';
36
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
37 38
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, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
63 64
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
65
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
66 67 68 69 70
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
71
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
72
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
73
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
74 75
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
76 77
import { ICrashReporterService, NullCrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
import { CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
78
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
79 80
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
81
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
J
Johannes Rieken 已提交
82
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
83 84
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
J
Joao Moreno 已提交
85 86
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
J
Johannes Rieken 已提交
87 88
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
S
Sandeep Somavarapu 已提交
89
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
B
Benjamin Pasero 已提交
90
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
91
import { remote, ipcRenderer as ipc } from 'electron';
92 93
import URI from "vs/base/common/uri";
import { basename } from "path";
A
Alex Dima 已提交
94
import { ITextMateService } from 'vs/editor/node/textMate/textMateService';
A
Alex Dima 已提交
95
import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/TMSyntax';
96
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
97 98
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
99
import 'vs/platform/opener/browser/opener.contribution';
100 101
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
102
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
103
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
104

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

115 116
const currentWindow = remote.getCurrentWindow();

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

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

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

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

151
		this.configuration = configuration;
152 153 154 155
		this.options = options;

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

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

	private createContents(parent: Builder): Builder {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

261
		const mainProcessClient = new ElectronIPCClient(String(`window${currentWindow.id}`));
262 263
		disposables.add(mainProcessClient);

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

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

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

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

B
Benjamin Pasero 已提交
276
		// Storage Sevice
277 278 279 280 281 282 283 284 285 286 287 288 289
		let workspaceIdentifier = this.contextService.getWorkspace();
		if (!workspaceIdentifier && !!this.configuration.backupPath) {
			// if we do not have a workspace open, we need to find another identifier for the window to store
			// workspace UI state. if we have a backup path in the configuration we can use that because this
			// will be a unique identifier per window that is stable between restarts as long as there are
			// dirty files in the workspace.
			// We use basename() to produce a short identifier, we do not need the full path. We use a custom
			// scheme so that we can later distinguish these identifiers from the workspace one.
			workspaceIdentifier = { resource: URI.from({ path: basename(this.configuration.backupPath), scheme: 'empty' }) };
		}
		const disableStorage = !!this.environmentService.extensionTestsPath; // never keep any state when running extension tests!
		const storage = disableStorage ? inMemoryLocalStorageInstance : window.localStorage;
		this.storageService = new StorageService(storage, storage, workspaceIdentifier);
290
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
291

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

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

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

J
Joao Moreno 已提交
310
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
311 312
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
313
			const errorTelemetry = new ErrorTelemetry(telemetryService);
314
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
315

316 317 318 319
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
320
				));
321

322
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
323
		} else {
C
Christof Marti 已提交
324
			NullTelemetryService._experiments = instantiationService.invokeFunction(loadExperiments);
325
			this.telemetryService = NullTelemetryService;
326
		}
E
Erich Gamma 已提交
327

328
		serviceCollection.set(ITelemetryService, this.telemetryService);
329
		disposables.add(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
330

331 332 333 334 335 336
		let crashReporterService = NullCrashReporterService;
		if (product.crashReporter && product.hockeyApp) {
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

402
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
403 404
	}

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

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

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

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

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

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

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

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
});