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

'use strict';

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

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable, Disposables } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19 20
import product from 'vs/platform/product';
import pkg from 'vs/platform/package';
J
Johannes Rieken 已提交
21
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
E
Erich Gamma 已提交
22
import timer = require('vs/base/common/timer');
J
Johannes Rieken 已提交
23
import { Workbench } from 'vs/workbench/electron-browser/workbench';
S
Sandeep Somavarapu 已提交
24
import { Storage, inMemoryLocalStorageInstance } from 'vs/workbench/common/storage';
J
Johannes Rieken 已提交
25 26 27 28
import { ITelemetryService, NullTelemetryService, loadExperiments } from 'vs/platform/telemetry/common/telemetry';
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';
J
Johannes Rieken 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { ElectronIntegration } from 'vs/workbench/electron-browser/integration';
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
import { IWindowService, WindowService } from 'vs/workbench/services/window/electron-browser/windowService';
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
import { IRequestService } from 'vs/platform/request/common/request';
import { RequestService } from 'vs/platform/request/node/requestService';
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';
import { MainProcessExtensionService } from 'vs/workbench/api/node/mainThreadExtensionService';
import { IOptions } from 'vs/workbench/common/options';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IEventService } from 'vs/platform/event/common/event';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
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';
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
67
import { IExtensionService, IExtensionsRuntimeService } from 'vs/platform/extensions/common/extensions';
J
Johannes Rieken 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
import { MainThreadModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { CrashReporter } from 'vs/workbench/electron-browser/crashReporter';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ThemeService } from 'vs/workbench/services/themes/electron-browser/themeService';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/common/ipc.electron';
import { ipcRenderer } from 'electron';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configurationService';
84 85
import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost';
import { ExtensionsRuntimeService } from 'vs/workbench/services/extensions/electron-browser/extensions';
86 87

// self registering services
88
import 'vs/platform/opener/browser/opener.contribution';
89

90 91 92 93 94 95 96
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	eventService: IEventService;
	configurationService: IConfigurationService;
97
	environmentService: IEnvironmentService;
98 99
}

E
Erich Gamma 已提交
100
/**
B
Benjamin Pasero 已提交
101
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
102 103 104
 * 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 已提交
105
	private storageService: IStorageService;
106
	private messageService: MessageService;
107
	private eventService: IEventService;
J
Johannes Rieken 已提交
108
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
109 110 111
	private contextViewService: ContextViewService;
	private windowService: IWindowService;
	private threadService: MainThreadService;
112
	private configurationService: IConfigurationService;
M
Martin Aeschlimann 已提交
113
	private themeService: ThemeService;
114
	private contextService: IWorkspaceContextService;
115
	private telemetryService: ITelemetryService;
E
Erich Gamma 已提交
116 117

	private container: HTMLElement;
118
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
119 120 121 122 123 124 125 126 127
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

	private workspace: IWorkspace;
	private options: IOptions;
	private workbench: Workbench;

128
	constructor(container: HTMLElement, workspace: IWorkspace, services: ICoreServices, options: IOptions) {
E
Erich Gamma 已提交
129 130 131
		this.container = container;

		this.workspace = workspace;
132 133 134 135 136
		this.options = options;

		this.contextService = services.contextService;
		this.eventService = services.eventService;
		this.configurationService = services.configurationService;
137
		this.environmentService = services.environmentService;
E
Erich Gamma 已提交
138 139 140 141 142 143 144

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

	private createContents(parent: Builder): Builder {

145
		// ARIA
B
Benjamin Pasero 已提交
146
		aria.setARIAContainer(document.body);
147

E
Erich Gamma 已提交
148
		// Workbench Container
149
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
150 151

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

		//crash reporting
155 156 157
		if (!!product.crashReporter) {
			const crashReporter = instantiationService.createInstance(CrashReporter, pkg.version, product.commit);
			crashReporter.start(product.crashReporter);
E
Erich Gamma 已提交
158 159 160
		}

		// Workbench
161
		this.workbench = instantiationService.createInstance(Workbench, workbenchContainer.getHTMLElement(), this.workspace, this.options, serviceCollection);
E
Erich Gamma 已提交
162
		this.workbench.startup({
163 164
			onWorkbenchStarted: (customKeybindingsCount) => {
				this.onWorkbenchStarted(customKeybindingsCount);
E
Erich Gamma 已提交
165 166 167 168 169 170 171
			}
		});

		// Electron integration
		this.workbench.getInstantiationService().createInstance(ElectronIntegration).integrate(this.container);

		// Handle case where workbench is not starting up properly
172
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
173 174 175 176 177 178 179 180 181 182
			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;
	}

183
	private onWorkbenchStarted(customKeybindingsCount: number): void {
B
Benjamin Pasero 已提交
184 185

		// Log to telemetry service
186
		const windowSize = {
B
Benjamin Pasero 已提交
187 188 189 190 191 192 193 194 195 196 197
			innerHeight: window.innerHeight,
			innerWidth: window.innerWidth,
			outerHeight: window.outerHeight,
			outerWidth: window.outerWidth
		};

		this.telemetryService.publicLog('workspaceLoad',
			{
				userAgent: navigator.userAgent,
				windowSize: windowSize,
				emptyWorkbench: !this.contextService.getWorkspace(),
198
				customKeybindingsCount,
M
Martin Aeschlimann 已提交
199
				theme: this.themeService.getColorTheme(),
200 201
				language: platform.language,
				experiments: this.telemetryService.getExperiments()
B
Benjamin Pasero 已提交
202 203
			});

204
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
B
Benjamin Pasero 已提交
205
		workspaceStats.reportWorkspaceTags();
J
Joao Moreno 已提交
206 207 208 209

		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 已提交
210 211
	}

212
	private initServiceCollection(container: HTMLElement): [InstantiationService, ServiceCollection] {
J
Joao Moreno 已提交
213 214
		const disposables = new Disposables();

J
Joao Moreno 已提交
215
		const mainProcessClient = new ElectronIPCClient(ipcRenderer);
J
Joao Moreno 已提交
216
		disposables.add(mainProcessClient);
J
Joao Moreno 已提交
217

218 219 220 221
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IEventService, this.eventService);
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
222
		serviceCollection.set(IEnvironmentService, this.environmentService);
223

224
		const instantiationService = new InstantiationService(serviceCollection, true);
225

226 227 228
		this.windowService = instantiationService.createInstance(WindowService);
		serviceCollection.set(IWindowService, this.windowService);

J
Johannes Rieken 已提交
229
		const sharedProcess = connectNet(this.environmentService.sharedIPCHandle, `window:${this.windowService.getWindowId()}`);
230
		sharedProcess.done(client => {
S
Sandeep Somavarapu 已提交
231 232 233

			client.registerChannel('choice', new ChoiceChannel(this.messageService));

234 235 236 237 238 239 240 241
			client.onClose(() => {
				this.messageService.show(Severity.Error, {
					message: nls.localize('sharedProcessCrashed', "The shared process terminated unexpectedly. Please reload the window to recover."),
					actions: [instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL)]
				});
			});
		}, errors.onUnexpectedError);

242
		// Storage
243
		const disableWorkspaceStorage = this.environmentService.extensionTestsPath || (!this.workspace && !this.environmentService.extensionDevelopmentPath); // without workspace or in any extension test, we use inMemory storage unless we develop an extension where we want to preserve state
244 245
		this.storageService = instantiationService.createInstance(Storage, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage);
		serviceCollection.set(IStorageService, this.storageService);
E
Erich Gamma 已提交
246

247
		// Telemetry
248
		if (this.environmentService.isBuilt && !this.environmentService.extensionDevelopmentPath && !!product.enableTelemetry) {
249
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
250 251
			const commit = product.commit;
			const version = pkg.version;
252

253
			const config: ITelemetryServiceConfig = {
254
				appender: new TelemetryAppenderClient(channel),
255
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
256
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath],
257
				experiments: loadExperiments(this.storageService, this.configurationService)
258
			};
259

J
Joao Moreno 已提交
260
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
261 262
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
263
			const errorTelemetry = new ErrorTelemetry(telemetryService);
264
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
265

266 267 268 269
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
270
				));
271

272
			disposables.add(telemetryService, errorTelemetry, listener, idleMonitor);
273
		} else {
274
			NullTelemetryService._experiments = loadExperiments(this.storageService, this.configurationService);
275
			this.telemetryService = NullTelemetryService;
276
		}
E
Erich Gamma 已提交
277

278
		serviceCollection.set(ITelemetryService, this.telemetryService);
279 280 281
		if (this.configurationService instanceof WorkspaceConfigurationService) {
			this.configurationService.telemetryService = this.telemetryService;
		}
E
Erich Gamma 已提交
282

283
		this.messageService = instantiationService.createInstance(MessageService, container);
284
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
285
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
286

287
		const lifecycleService = instantiationService.createInstance(LifecycleService);
288 289
		this.toUnbind.push(lifecycleService.onShutdown(() => disposables.dispose()));
		serviceCollection.set(ILifecycleService, lifecycleService);
290 291 292

		const extensionsRuntimeService = instantiationService.createInstance(ExtensionsRuntimeService);
		serviceCollection.set(IExtensionsRuntimeService, extensionsRuntimeService);
293

294 295
		const extensionHostProcessWorker = this.startExtensionHost(instantiationService);
		this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);
296
		serviceCollection.set(IThreadService, this.threadService);
297

298
		const extensionService = instantiationService.createInstance(MainProcessExtensionService);
299
		serviceCollection.set(IExtensionService, extensionService);
E
Erich Gamma 已提交
300

301 302
		serviceCollection.set(ICommandService, new CommandService(instantiationService, extensionService));

303 304
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
305

J
Joao Moreno 已提交
306
		const requestService = instantiationService.createInstance(RequestService);
307
		serviceCollection.set(IRequestService, requestService);
E
Erich Gamma 已提交
308

309
		const markerService = instantiationService.createInstance(MarkerService);
310
		serviceCollection.set(IMarkerService, markerService);
E
Erich Gamma 已提交
311

312
		const modeService = instantiationService.createInstance(MainThreadModeServiceImpl);
313
		serviceCollection.set(IModeService, modeService);
314

315
		const modelService = instantiationService.createInstance(ModelServiceImpl);
316
		serviceCollection.set(IModelService, modelService);
317

318
		const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
319
		serviceCollection.set(IEditorWorkerService, editorWorkerService);
320

321
		const untitledEditorService = instantiationService.createInstance(UntitledEditorService);
322 323 324
		serviceCollection.set(IUntitledEditorService, untitledEditorService);

		this.themeService = instantiationService.createInstance(ThemeService);
325
		serviceCollection.set(IThemeService, this.themeService);
326

327
		const searchService = instantiationService.createInstance(SearchService);
328 329
		serviceCollection.set(ISearchService, searchService);

330
		const codeEditorService = instantiationService.createInstance(CodeEditorServiceImpl);
331 332
		serviceCollection.set(ICodeEditorService, codeEditorService);

A
Alex Dima 已提交
333 334 335
		const integrityService = instantiationService.createInstance(IntegrityServiceImpl);
		serviceCollection.set(IIntegrityService, integrityService);

336
		const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
J
Joao Moreno 已提交
337
		const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
338
		serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);
339

J
Joao Moreno 已提交
340
		const urlChannel = mainProcessClient.getChannel('url');
J
Joao Moreno 已提交
341
		const urlChannelClient = new URLChannelClient(urlChannel, this.windowService.getWindowId());
J
Joao Moreno 已提交
342 343
		serviceCollection.set(IURLService, urlChannelClient);

344
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	}

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

		// Handle Load Performance Timers
		this.writeTimers();

		// Create Contents
		this.contentsContainer = this.createContents($(this.content));

		// Layout
		this.layout();

		// Listeners
		this.registerListeners();

		// Enable theme support
M
Martin Aeschlimann 已提交
373
		this.themeService.initialize(this.container).then(null, error => {
374 375
			errors.onUnexpectedError(error);
		});
E
Erich Gamma 已提交
376 377 378 379 380 381 382 383 384
	}

	private registerListeners(): void {

		// Resize
		$(window).on(dom.EventType.RESIZE, () => this.layout(), this.toUnbind);
	}

	private writeTimers(): void {
385
		const timers = (<any>window).MonacoEnvironment.timers;
E
Erich Gamma 已提交
386
		if (timers) {
387
			const events: timer.IExistingTimerEvent[] = [];
E
Erich Gamma 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423

			// Window
			if (timers.vscodeStart) {
				events.push({
					startTime: timers.vscodeStart,
					stopTime: timers.beforeLoad,
					topic: 'Startup',
					name: 'VSCode Startup',
					description: 'Time it takes to create a window and startup VSCode'
				});
			}

			// Load
			events.push({
				startTime: timers.beforeLoad,
				stopTime: timers.afterLoad,
				topic: 'Startup',
				name: 'Load Modules',
				description: 'Time it takes to load VSCodes main modules'
			});

			// Ready
			events.push({
				startTime: timers.beforeReady,
				stopTime: timers.afterReady,
				topic: 'Startup',
				name: 'Event DOMContentLoaded',
				description: 'Time it takes for the DOM to emit DOMContentLoaded event'
			});

			// Write to Timer
			timer.getTimeKeeper().setInitialCollectedEvents(events, timers.start);
		}
	}

	public onUnexpectedError(error: any): void {
424
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
425 426 427 428
		if (!errorMsg) {
			return;
		}

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

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

449
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
450 451
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
452
		this.contextViewService.layout();
E
Erich Gamma 已提交
453 454 455
		this.workbench.layout();
	}

456 457 458 459 460 461
	private startExtensionHost(instantiationService: InstantiationService): ExtensionHostProcessWorker {
		const extensionHostProcessWorker: ExtensionHostProcessWorker = <ExtensionHostProcessWorker>instantiationService.createInstance(ExtensionHostProcessWorker);
		extensionHostProcessWorker.start();
		return extensionHostProcessWorker;
	}

E
Erich Gamma 已提交
462 463 464 465
	public joinCreation(): TPromise<boolean> {
		return this.workbench.joinCreation();
	}

B
Benjamin Pasero 已提交
466
	public dispose(): void {
E
Erich Gamma 已提交
467 468 469

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
470
			this.workbench.dispose();
E
Erich Gamma 已提交
471 472
		}

B
Benjamin Pasero 已提交
473
		this.contextViewService.dispose();
E
Erich Gamma 已提交
474 475

		// Listeners
J
Joao Moreno 已提交
476
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
477 478 479 480 481

		// Container
		$(this.container).empty();
	}
}