electron 5 - bootstrap a nodeless configuration (#68302)

This commit is contained in:
Benjamin Pasero
2019-03-11 09:01:45 +01:00
parent 65ede5e23c
commit 76c330c3cd
55 changed files with 3650 additions and 983 deletions
+1 -1
View File
@@ -406,10 +406,10 @@
"./vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts",
"./vs/workbench/services/extensions/electron-browser/extensionHost.ts",
"./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts",
"./vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts",
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
"./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts",
"./vs/workbench/services/extensions/node/extensionHostProtocol.ts",
"./vs/workbench/services/extensions/node/extensionManagementServerService.ts",
"./vs/workbench/services/extensions/node/extensionPoints.ts",
"./vs/workbench/services/extensions/node/lazyPromise.ts",
"./vs/workbench/services/extensions/node/proxyIdentifier.ts",
+344 -1
View File
@@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isString } from 'vs/base/common/types';
/**
* Return a hash value for an object.
*/
@@ -69,4 +71,345 @@ export class Hasher {
this._value = hash(obj, this._value);
return this._value;
}
}
}
//#region SHA1
export function computeSHA1Hash(value: string): string {
const data = encodeToArrayBuffer(value);
const hash = new SHA1();
if (data.byteLength) {
hash.update(data);
}
return hash.digest();
}
class SHA1 {
// Reference: http://en.wikipedia.org/wiki/SHA-1
private static BLOCK_SIZE = 64; // 512 / 8
private length: number;
private buffer: Uint8Array | null;
private bufferDV: DataView | null;
private bufferLength: number;
private bigBlock32: DataView;
private h0 = 0x67452301;
private h1 = 0xEFCDAB89;
private h2 = 0x98BADCFE;
private h3 = 0x10325476;
private h4 = 0xC3D2E1F0;
static digest(data: string): string;
static digest(data: Uint8Array): string;
static digest(data: ArrayBuffer): string;
static digest(data: DataView): string;
static digest(data: any): string {
let sha = new SHA1();
sha.update(data);
return sha.digest();
}
constructor() {
this.length = 0;
this.buffer = new Uint8Array(SHA1.BLOCK_SIZE);
this.bufferDV = new DataView(this.buffer.buffer);
this.bufferLength = 0;
this.bigBlock32 = new DataView(new ArrayBuffer(320)); // 80 * 4 = 320;
}
update(data: string): void;
update(data: Uint8Array): void;
update(data: ArrayBuffer): void;
update(data: DataView): void;
update(arg: any): void {
if (!this.buffer || !this.bufferDV) {
throw new Error('Digest already computed.');
}
let data: Uint8Array;
if (isString(arg)) {
data = new Uint8Array(encodeToArrayBuffer(<string>arg));
} else if (arg instanceof ArrayBuffer) {
data = new Uint8Array(arg);
} else if (arg instanceof DataView) {
data = new Uint8Array((<DataView>arg).buffer);
} else {
data = <Uint8Array>arg;
}
let bytesRead = 0, totalBytesRead = 0;
while (totalBytesRead < data.byteLength) {
bytesRead = copy(this.buffer, this.bufferLength, data, totalBytesRead, data.byteLength);
this.bufferLength += bytesRead;
totalBytesRead += bytesRead;
if (this.bufferLength === SHA1.BLOCK_SIZE) {
this.step(this.bufferDV);
this.bufferLength = 0;
}
}
this.length += totalBytesRead;
}
digest(): string {
if (this.buffer) {
this.wrapUp();
}
return toHexString(this.h0) + toHexString(this.h1) + toHexString(this.h2) + toHexString(this.h3) + toHexString(this.h4);
}
private wrapUp(): void {
if (!this.buffer || !this.bufferDV) {
return; // already wrapped up
}
this.buffer[this.bufferLength++] = 0x80;
fill(this.buffer, this.bufferLength);
if (this.bufferLength > 56) {
this.step(this.bufferDV);
fill(this.buffer);
}
let ml = multiply64(8, this.length);
this.bufferDV.setUint32(56, ml[0], false);
this.bufferDV.setUint32(60, ml[1], false);
this.step(this.bufferDV);
this.buffer = null;
this.bufferDV = null;
this.bufferLength = -1;
}
private step(data: DataView): void {
for (let j = 0; j < 64 /* 16*4 */; j += 4) {
this.bigBlock32.setUint32(j, data.getUint32(j, false), false);
}
for (let j = 64; j < 320 /* 80*4 */; j += 4) {
this.bigBlock32.setUint32(j, leftRotate((this.bigBlock32.getUint32(j - 12, false) ^ this.bigBlock32.getUint32(j - 32, false) ^ this.bigBlock32.getUint32(j - 56, false) ^ this.bigBlock32.getUint32(j - 64, false)), 1), false);
}
let a = this.h0;
let b = this.h1;
let c = this.h2;
let d = this.h3;
let e = this.h4;
let f: number, k: number;
let temp: number;
for (let j = 0; j < 80; j++) {
if (j < 20) {
f = (b & c) | ((~b) & d);
k = 0x5A827999;
} else if (j < 40) {
f = b ^ c ^ d;
k = 0x6ED9EBA1;
} else if (j < 60) {
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
} else {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
temp = (leftRotate(a, 5) + f + e + k + this.bigBlock32.getUint32(j * 4, false)) & 0xFFFFFFFF;
e = d;
d = c;
c = leftRotate(b, 30);
b = a;
a = temp;
}
this.h0 = (this.h0 + a) & 0xFFFFFFFF;
this.h1 = (this.h1 + b) & 0xFFFFFFFF;
this.h2 = (this.h2 + c) & 0xFFFFFFFF;
this.h3 = (this.h3 + d) & 0xFFFFFFFF;
this.h4 = (this.h4 + e) & 0xFFFFFFFF;
}
}
function leftPad(value: string, length: number, char: string = '0'): string {
return new Array(length - value.length + 1).join(char) + value;
}
function toHexString(value: number, bitsize: number = 32): string {
return leftPad((value >>> 0).toString(16), bitsize / 4);
}
function leftRotate(value: number, bits: number, totalBits: number = 32): number {
// delta + bits = totalBits
let delta = totalBits - bits;
// All ones, expect `delta` zeros aligned to the right
let mask = ~((1 << delta) - 1);
// Join (value left-shifted `bits` bits) with (masked value right-shifted `delta` bits)
return ((value << bits) | ((mask & value) >>> delta)) >>> 0;
}
function multiply64(a: number, b: number): number[] {
/* A1 A0 => A
* B1 B0 => B
* B0 * A1 B0 * A0
* B1 * A1 B1 * A0
* C3 C2 C1 C0 => C
*/
let a0 = a & 0xFFFF, a1 = a >>> 16;
let b0 = b & 0xFFFF, b1 = b >>> 16;
let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
let x = b0 * a0;
c0 += x & 0xFFFF;
c1 += x >>> 16;
x = b0 * a1;
c1 += x & 0xFFFF;
c2 += x >>> 16;
x = b1 * a0;
c1 += x & 0xFFFF;
c2 += x >>> 16;
c2 += c1 >>> 16;
c1 = c1 & 0xFFFF;
x = b1 * a1;
c2 += x & 0xFFFF;
c3 += x >>> 16;
c3 += c2 >>> 16;
c2 = c2 & 0xFFFF;
return [(c3 << 16 | c2) >>> 0, (c1 << 16 | c0) >>> 0];
}
function encodeToArrayBuffer(str: string): ArrayBuffer {
let i: number, len: number, length = 0, charCode = 0, trailCharCode = 0, codepoint = 0;
// First pass, for the size
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
// Surrogate pair
if (charCode >= 0xD800 && charCode < 0xDC00) {
trailCharCode = str.charCodeAt(++i);
if (!(trailCharCode >= 0xDC00 && trailCharCode < 0xE000)) {
throw new Error('Invalid char code');
}
// Code point can be obtained by subtracting 0xD800 and 0xDC00 from both char codes respectively
// and joining the 10 least significant bits from each, finally adding 0x10000.
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
} else {
codepoint = charCode;
}
length += byteSizeInUTF8(codepoint);
}
let result = new ArrayBuffer(length);
let view = new Uint8Array(result);
let pos = 0;
// Second pass, for the data
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
if (charCode >= 0xD800 && charCode < 0xDC00) {
trailCharCode = str.charCodeAt(++i);
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
} else {
codepoint = charCode;
}
pos += writeUTF8(codepoint, view, pos);
}
return result;
}
function byteSizeInUTF8(codePoint: number): number {
codePoint = codePoint >>> 0;
if (codePoint < 0x80) {
return 1;
} else if (codePoint < 0x800) {
return 2;
} else if (codePoint < 0x10000) {
return 3;
} else if (codePoint < 0x200000) {
return 4;
} else if (codePoint < 0x4000000) {
return 5;
} else if (codePoint < 0x80000000) {
return 6;
} else {
throw new Error('Code point 0x' + toHexString(codePoint) + ' not encodable in UTF8.');
}
}
function writeUTF8(codePoint: number, buffer: Uint8Array, pos: number): number {
// How many bits needed for codePoint
let byteSize = byteSizeInUTF8(codePoint);
// 0xxxxxxx
if (byteSize === 1) {
buffer[pos] = codePoint;
return 1;
}
// 110xxxxx 10xxxxxx
// 1110xxxx 10xxxxxx 10xxxxxx
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// first byte
buffer[pos] = ((0xFC << (6 - byteSize)) | (codePoint >>> (6 * (byteSize - 1)))) & 0xFF;
// successive bytes
for (let i = 1; i < byteSize; i++) {
buffer[pos + i] = (0x80 | (0x3F & (codePoint >>> (6 * (byteSize - i - 1))))) & 0xFF;
}
return byteSize;
}
function copy(dest: Uint8Array, destIndex: number, src: Uint8Array, srcIndex: number, count: number): number {
const len = Math.min(dest.byteLength - destIndex, src.byteLength - srcIndex, count);
for (let i = 0; i < len; i++) {
dest[destIndex + i] = src[srcIndex + i];
}
return len;
}
function fill(dest: Uint8Array, index: number = 0, count: number = dest.byteLength, value: number = 0): void {
for (let i = 0; i < count; i++) {
dest[index + i] = value;
}
}
//#endregion
+9 -1
View File
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { hash } from 'vs/base/common/hash';
import { hash, computeSHA1Hash } from 'vs/base/common/hash';
suite('Hash', () => {
test('string', () => {
@@ -43,4 +43,12 @@ suite('Hash', () => {
assert.notEqual(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar2' }));
assert.notEqual(hash({}), hash([]));
});
test('computeSHA1Hash', () => {
assert.equal(computeSHA1Hash(''), 'da39a3ee5e6b4b0d3255bfef95601890afd80709');
assert.equal(computeSHA1Hash('hello world'), '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed');
assert.equal(computeSHA1Hash('da39a3ee5e6b4b0d3255bfef95601890afd80709'), '10a34637ad661d98ba3344717656fcc76209c2f8');
assert.equal(computeSHA1Hash('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'), 'd6b0d82cea4269b51572b8fab43adcee9fc3cf9a');
assert.equal(computeSHA1Hash('öäü_?ß()<>ÖÄÜ'), 'b64beaeff9e317b0193c8e40a2431b210388eba9');
});
});
@@ -16,7 +16,6 @@ import * as os from 'os';
import { debounce } from 'vs/base/common/decorators';
import * as platform from 'vs/base/common/platform';
import { Disposable } from 'vs/base/common/lifecycle';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -28,7 +27,8 @@ import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService';
import { MainProcessService, IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
import { IssueReporterData, IssueReporterStyles, IssueType, ISettingsSearchIssueReporterData, IssueReporterFeatures, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
@@ -273,14 +273,14 @@ export class IssueReporter extends Disposable {
private initServices(configuration: IWindowConfiguration): void {
const serviceCollection = new ServiceCollection();
const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`));
const mainProcessService = new MainProcessService(configuration.windowId);
serviceCollection.set(IMainProcessService, mainProcessService);
const windowsChannel = mainProcessClient.getChannel('windows');
serviceCollection.set(IWindowsService, new WindowsChannelClient(windowsChannel));
serviceCollection.set(IWindowsService, new WindowsService(mainProcessService));
this.environmentService = new EnvironmentService(configuration, configuration.execPath);
const logService = createSpdLogService(`issuereporter${configuration.windowId}`, getLogLevel(this.environmentService), this.environmentService.logsPath);
const logLevelClient = new LogLevelSetterChannelClient(mainProcessClient.getChannel('loglevel'));
const logLevelClient = new LogLevelSetterChannelClient(mainProcessService.getChannel('loglevel'));
this.logService = new FollowerLogService(logLevelClient, logService);
const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
@@ -28,7 +28,7 @@ import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIp
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
import { IWindowsService, ActiveWindowManager } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService';
import { ipcRenderer } from 'electron';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
@@ -41,11 +41,13 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IDisposable, dispose, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { DownloadService } from 'vs/platform/download/node/downloadService';
import { IDownloadService } from 'vs/platform/download/common/download';
import { StaticRouter } from 'vs/base/parts/ipc/node/ipc';
import { StaticRouter, IServerChannel, IChannel } from 'vs/base/parts/ipc/node/ipc';
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner';
import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner';
import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export interface ISharedProcessConfiguration {
readonly machineId: string;
@@ -63,6 +65,20 @@ interface ISharedProcessInitData {
const eventPrefix = 'monacoworkbench';
class MainProcessService implements IMainProcessService {
constructor(private server: Server, private mainRouter: StaticRouter) { }
_serviceBrand: ServiceIdentifier<any>;
getChannel(channelName: string): IChannel {
return this.server.getChannel(channelName, this.mainRouter);
}
registerChannel(channelName: string, channel: IServerChannel<string>): void {
this.server.registerChannel(channelName, channel);
}
}
function main(server: Server, initData: ISharedProcessInitData, configuration: ISharedProcessConfiguration): void {
const services = new ServiceCollection();
@@ -89,8 +105,10 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
services.set(IRequestService, new SyncDescriptor(RequestService));
services.set(IDownloadService, new SyncDescriptor(DownloadService));
const windowsChannel = server.getChannel('windows', mainRouter);
const windowsService = new WindowsChannelClient(windowsChannel);
const mainProcessService = new MainProcessService(server, mainRouter);
services.set(IMainProcessService, mainProcessService);
const windowsService = new WindowsService(mainProcessService);
services.set(IWindowsService, windowsService);
const activeWindowManager = new ActiveWindowManager(windowsService);
@@ -0,0 +1,12 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body class="monaco-shell vs-dark" aria-label="">
</body>
<!-- Startup via workbench.nodeless.js -->
<script src="workbench.nodeless.js"></script>
</html>
@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
(function () {
function loadScript(path, callback) {
let script = document.createElement('script');
script.onload = callback;
script.async = true;
script.type = 'text/javascript';
script.src = path;
document.head.appendChild(script);
}
loadScript('../../../../../src/vs/loader.js', function () {
// @ts-ignore
require.config({
baseUrl: 'file:../../../../../out'
});
// @ts-ignore
require([
'vs/workbench/workbench.nodeless.main',
'vs/nls!vs/workbench/workbench.nodeless.main',
'vs/css!vs/workbench/workbench.nodeless.main'
], function () {
// @ts-ignore
require('vs/workbench/browser/nodeless.main').main().then(undefined, console.error);
});
});
})();
+20 -4
View File
@@ -78,6 +78,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private readonly touchBarGroups: Electron.TouchBarSegmentedControl[];
private nodeless: boolean;
constructor(
config: IWindowCreationOptions,
@ILogService private readonly logService: ILogService,
@@ -94,6 +96,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this._readyState = ReadyState.NONE;
this.whenReadyCallbacks = [];
this.nodeless = !!(environmentService.args.nodeless && !environmentService.isBuilt);
// create browser window
this.createBrowserWindow(config);
@@ -123,7 +127,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
height: this.windowState.height,
x: this.windowState.x,
y: this.windowState.y,
backgroundColor: getBackgroundColor(this.stateService),
backgroundColor: this.nodeless ? undefined : getBackgroundColor(this.stateService),
minWidth: CodeWindow.MIN_WIDTH,
minHeight: CodeWindow.MIN_HEIGHT,
show: !isFullscreenOrMaximized,
@@ -133,10 +137,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// want to enforce that Code stays in the foreground. This triggers a disable_hidden_
// flag that Electron provides via patch:
// https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch
'backgroundThrottling': false
backgroundThrottling: false
}
};
if (this.nodeless) {
options.webPreferences!.nodeIntegration = false; // simulate Electron 5 behaviour
}
if (isLinux) {
options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s)
}
@@ -188,6 +196,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
}
if (this.nodeless) {
this._win.webContents.toggleDevTools();
}
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
}
@@ -387,7 +399,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
// Window (Un)Maximize
this._win.on('maximize', e => {
this._win.on('maximize', (e: Event) => {
if (this.currentConfig) {
this.currentConfig.maximized = true;
}
@@ -395,7 +407,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
app.emit('browser-window-maximize', e, this._win);
});
this._win.on('unmaximize', e => {
this._win.on('unmaximize', (e: Event) => {
if (this.currentConfig) {
this.currentConfig.maximized = false;
}
@@ -618,6 +630,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
private doGetUrl(config: object): string {
if (this.nodeless) {
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.nodeless.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
@@ -42,7 +42,6 @@ import { IProgressRunner, IProgressService } from 'vs/platform/progress/common/p
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { ILayoutService, IDimension } from 'vs/platform/layout/browser/layoutService';
export class SimpleModel implements IResolvedTextEditorModel {
@@ -218,31 +217,6 @@ export class SimpleNotificationService implements INotificationService {
}
}
export class BrowserAccessibilityService implements IAccessibilityService {
_serviceBrand: any;
private _accessibilitySupport = AccessibilitySupport.Unknown;
private readonly _onDidChangeAccessibilitySupport = new Emitter<void>();
readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
alwaysUnderlineAccessKeys(): Promise<boolean> {
return Promise.resolve(false);
}
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void {
if (this._accessibilitySupport === accessibilitySupport) {
return;
}
this._accessibilitySupport = accessibilitySupport;
this._onDidChangeAccessibilitySupport.fire();
}
getAccessibilitySupport(): AccessibilitySupport {
return this._accessibilitySupport;
}
}
export class StandaloneCommandService implements ICommandService {
_serviceBrand: any;
@@ -13,7 +13,7 @@ import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, BrowserAccessibilityService, SimpleLayoutService } from 'vs/editor/standalone/browser/simpleServices';
import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, SimpleLayoutService } from 'vs/editor/standalone/browser/simpleServices';
import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl';
import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl';
import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
@@ -46,6 +46,7 @@ import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDeco
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl';
import { ISuggestMemoryService, SuggestMemoryService } from 'vs/editor/contrib/suggest/suggestMemory';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { BrowserAccessibilityService } from 'vs/platform/accessibility/common/accessibilityService';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export interface IEditorOverrideServices {
@@ -201,7 +202,7 @@ export class DynamicStandaloneServices extends Disposable {
let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(layoutService)));
ensure(IContextMenuService, () => this._register(new ContextMenuService(domElement, telemetryService, notificationService, contextViewService, keybindingService, themeService)));
ensure(IContextMenuService, () => this._register(new ContextMenuService(layoutService, telemetryService, notificationService, contextViewService, keybindingService, themeService)));
ensure(IMenuService, () => new MenuService(commandService));
@@ -0,0 +1,34 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { Disposable } from 'vs/base/common/lifecycle';
export class BrowserAccessibilityService extends Disposable implements IAccessibilityService {
_serviceBrand: any;
private _accessibilitySupport = AccessibilitySupport.Unknown;
private readonly _onDidChangeAccessibilitySupport = new Emitter<void>();
readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
alwaysUnderlineAccessKeys(): Promise<boolean> {
return Promise.resolve(false);
}
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void {
if (this._accessibilitySupport === accessibilitySupport) {
return;
}
this._accessibilitySupport = accessibilitySupport;
this._onDidChangeAccessibilitySupport.fire();
}
getAccessibilitySupport(): AccessibilitySupport {
return this._accessibilitySupport;
}
}
@@ -12,6 +12,7 @@ import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Disposable } from 'vs/base/common/lifecycle';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export class ContextMenuService extends Disposable implements IContextMenuService {
_serviceBrand: any;
@@ -22,7 +23,7 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
private contextMenuHandler: ContextMenuHandler;
constructor(
container: HTMLElement | null,
@ILayoutService layoutService: ILayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService,
@IContextViewService contextViewService: IContextViewService,
@@ -31,7 +32,7 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
) {
super();
this.contextMenuHandler = this._register(new ContextMenuHandler(container, contextViewService, telemetryService, notificationService, keybindingService, themeService));
this.contextMenuHandler = this._register(new ContextMenuHandler(layoutService.container, contextViewService, telemetryService, notificationService, keybindingService, themeService));
}
dispose(): void {
+3 -42
View File
@@ -4,19 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import * as path from 'vs/base/common/path';
import * as fs from 'fs';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { IDownloadService } from 'vs/platform/download/common/download';
import { mkdirp } from 'vs/base/node/pfs';
import { IURITransformer } from 'vs/base/common/uriIpc';
import { tmpdir } from 'os';
import { generateUuid } from 'vs/base/common/uuid';
export type UploadResponse = Buffer | string | undefined;
type UploadResponse = Buffer | string | undefined;
export function upload(uri: URI): Event<UploadResponse> {
function upload(uri: URI): Event<UploadResponse> {
const stream = new Emitter<UploadResponse>();
const readstream = fs.createReadStream(uri.fsPath);
readstream.on('data', data => stream.fire(data));
@@ -41,36 +35,3 @@ export class DownloadServiceChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class DownloadServiceChannelClient implements IDownloadService {
_serviceBrand: any;
constructor(private channel: IChannel, private getUriTransformer: () => IURITransformer) { }
download(from: URI, to: string = path.join(tmpdir(), generateUuid())): Promise<string> {
from = this.getUriTransformer().transformOutgoingURI(from);
const dirName = path.dirname(to);
let out: fs.WriteStream;
return new Promise<string>((c, e) => {
return mkdirp(dirName)
.then(() => {
out = fs.createWriteStream(to);
out.once('close', () => c(to));
out.once('error', e);
const uploadStream = this.channel.listen<UploadResponse>('upload', from);
const disposable = uploadStream(result => {
if (result === undefined) {
disposable.dispose();
out.end(() => c(to));
} else if (Buffer.isBuffer(result)) {
out.write(result);
} else if (typeof result === 'string') {
disposable.dispose();
out.end(() => e(result));
}
});
});
});
}
}
@@ -3,10 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/node/driver';
import { IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { getTopLeftOffset, getClientArea } from 'vs/base/browser/dom';
import * as electron from 'electron';
import { IWindowService } from 'vs/platform/windows/common/windows';
@@ -214,25 +214,24 @@ class WindowDriver implements IWindowDriver {
}
}
export async function registerWindowDriver(
client: IPCClient,
windowId: number,
instantiationService: IInstantiationService
): Promise<IDisposable> {
export async function registerWindowDriver(accessor: ServicesAccessor): Promise<IDisposable> {
const instantiationService = accessor.get(IInstantiationService);
const mainProcessService = accessor.get(IMainProcessService);
const windowService = accessor.get(IWindowService);
const windowDriver = instantiationService.createInstance(WindowDriver);
const windowDriverChannel = new WindowDriverChannel(windowDriver);
client.registerChannel('windowDriver', windowDriverChannel);
mainProcessService.registerChannel('windowDriver', windowDriverChannel);
const windowDriverRegistryChannel = client.getChannel('windowDriverRegistry');
const windowDriverRegistryChannel = mainProcessService.getChannel('windowDriverRegistry');
const windowDriverRegistry = new WindowDriverRegistryChannelClient(windowDriverRegistryChannel);
await windowDriverRegistry.registerWindowDriver(windowId);
await windowDriverRegistry.registerWindowDriver(windowService.getCurrentWindowId());
// const options = await windowDriverRegistry.registerWindowDriver(windowId);
// if (options.verbose) {
// windowDriver.openDevTools();
// }
const disposable = toDisposable(() => windowDriverRegistry.reloadWindowDriver(windowId));
return combinedDisposable([disposable, client]);
return toDisposable(() => windowDriverRegistry.reloadWindowDriver(windowService.getCurrentWindowId()));
}
@@ -69,6 +69,7 @@ export interface ParsedArgs {
'driver'?: string;
'driver-verbose'?: boolean;
remote?: string;
'nodeless'?: boolean; // TODO@ben revisit electron5 nodeless support
}
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');
+2 -1
View File
@@ -91,7 +91,8 @@ export const options: Option[] = [
{ id: 'force', type: 'boolean' },
{ id: 'trace-category-filter', type: 'string' },
{ id: 'trace-options', type: 'string' },
{ id: 'prof-code-loading', type: 'boolean' }
{ id: 'prof-code-loading', type: 'boolean' },
{ id: 'nodeless', type: 'boolean' } // TODO@ben revisit electron5 nodeless support
];
export function parseArgs(args: string[], isOptionSupported = (_: Option) => true): ParsedArgs {
@@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Client } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { Disposable } from 'vs/base/common/lifecycle';
export const IMainProcessService = createDecorator<IMainProcessService>('mainProcessService');
export interface IMainProcessService {
_serviceBrand: ServiceIdentifier<any>;
getChannel(channelName: string): IChannel;
registerChannel(channelName: string, channel: IServerChannel<string>): void;
}
export class MainProcessService extends Disposable implements IMainProcessService {
_serviceBrand: ServiceIdentifier<any>;
private mainProcessConnection: Client;
constructor(
windowId: number
) {
super();
this.mainProcessConnection = this._register(new Client(`window:${windowId}`));
}
getChannel(channelName: string): IChannel {
return this.mainProcessConnection.getChannel(channelName);
}
registerChannel(channelName: string, channel: IServerChannel<string>): void {
this.mainProcessConnection.registerChannel(channelName, channel);
}
}
@@ -32,7 +32,7 @@ export class SharedProcessService implements ISharedProcessService {
@IEnvironmentService environmentService: IEnvironmentService
) {
this.withSharedProcessConnection = windowsService.whenSharedProcessReady()
.then(() => connect(environmentService.sharedIPCHandle, `window:${windowService.getConfiguration().windowId}`));
.then(() => connect(environmentService.sharedIPCHandle, `window:${windowService.getCurrentWindowId()}`));
}
getChannel(channelName: string): IChannel {
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IIssueService, IssueReporterData, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class IssueService implements IIssueService {
_serviceBrand: ServiceIdentifier<any>;
private channel: IChannel;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
this.channel = mainProcessService.getChannel('issue');
}
openReporter(data: IssueReporterData): Promise<void> {
return this.channel.call('openIssueReporter', data);
}
openProcessExplorer(data: ProcessExplorerData): Promise<void> {
return this.channel.call('openProcessExplorer', data);
}
}
+2 -17
View File
@@ -3,9 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IIssueService, IssueReporterData, ProcessExplorerData } from '../common/issue';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event } from 'vs/base/common/event';
import { IIssueService } from 'vs/platform/issue/common/issue';
export class IssueChannel implements IServerChannel {
@@ -25,19 +25,4 @@ export class IssueChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class IssueChannelClient implements IIssueService {
_serviceBrand: any;
constructor(private channel: IChannel) { }
openReporter(data: IssueReporterData): Promise<void> {
return this.channel.call('openIssueReporter', data);
}
openProcessExplorer(data: ProcessExplorerData): Promise<void> {
return this.channel.call('openProcessExplorer', data);
}
}
@@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { Barrier } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import { ILifecycleService, BeforeShutdownEvent, WillShutdownEvent, StartupKind, LifecyclePhase, LifecyclePhaseToString } from 'vs/platform/lifecycle/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log';
import { mark } from 'vs/base/common/performance';
export abstract class AbstractLifecycleService extends Disposable implements ILifecycleService {
_serviceBrand: any;
protected readonly _onBeforeShutdown = this._register(new Emitter<BeforeShutdownEvent>());
get onBeforeShutdown(): Event<BeforeShutdownEvent> { return this._onBeforeShutdown.event; }
protected readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
protected readonly _onShutdown = this._register(new Emitter<void>());
get onShutdown(): Event<void> { return this._onShutdown.event; }
protected _startupKind: StartupKind;
get startupKind(): StartupKind { return this._startupKind; }
private _phase: LifecyclePhase = LifecyclePhase.Starting;
get phase(): LifecyclePhase { return this._phase; }
private phaseWhen = new Map<LifecyclePhase, Barrier>();
constructor(
@ILogService protected readonly logService: ILogService
) {
super();
}
set phase(value: LifecyclePhase) {
if (value < this.phase) {
throw new Error('Lifecycle cannot go backwards');
}
if (this._phase === value) {
return;
}
this.logService.trace(`lifecycle: phase changed (value: ${value})`);
this._phase = value;
mark(`LifecyclePhase/${LifecyclePhaseToString(value)}`);
const barrier = this.phaseWhen.get(this._phase);
if (barrier) {
barrier.open();
this.phaseWhen.delete(this._phase);
}
}
when(phase: LifecyclePhase): Promise<any> {
if (phase <= this._phase) {
return Promise.resolve();
}
let barrier = this.phaseWhen.get(phase);
if (!barrier) {
barrier = new Barrier();
this.phaseWhen.set(phase, barrier);
}
return barrier.wait();
}
}
@@ -4,50 +4,30 @@
*--------------------------------------------------------------------------------------------*/
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ILifecycleService, BeforeShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase, handleVetos, LifecyclePhaseToString, WillShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle';
import { ShutdownReason, StartupKind, handleVetos } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ipcRenderer as ipc } from 'electron';
import { Event, Emitter } from 'vs/base/common/event';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { mark } from 'vs/base/common/performance';
import { Barrier } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Disposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService';
export class LifecycleService extends Disposable implements ILifecycleService {
export class LifecycleService extends AbstractLifecycleService {
private static readonly LAST_SHUTDOWN_REASON_KEY = 'lifecyle.lastShutdownReason';
_serviceBrand: any;
private readonly _onBeforeShutdown = this._register(new Emitter<BeforeShutdownEvent>());
get onBeforeShutdown(): Event<BeforeShutdownEvent> { return this._onBeforeShutdown.event; }
private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
private readonly _onShutdown = this._register(new Emitter<void>());
get onShutdown(): Event<void> { return this._onShutdown.event; }
private readonly _startupKind: StartupKind;
get startupKind(): StartupKind { return this._startupKind; }
private _phase: LifecyclePhase = LifecyclePhase.Starting;
get phase(): LifecyclePhase { return this._phase; }
private phaseWhen = new Map<LifecyclePhase, Barrier>();
private shutdownReason: ShutdownReason;
constructor(
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IStorageService private readonly storageService: IStorageService,
@ILogService private readonly logService: ILogService
@IStorageService readonly storageService: IStorageService,
@ILogService readonly logService: ILogService
) {
super();
super(logService);
this._startupKind = this.resolveStartupKind();
@@ -148,39 +128,4 @@ export class LifecycleService extends Disposable implements ILifecycleService {
onUnexpectedError(err);
});
}
set phase(value: LifecyclePhase) {
if (value < this.phase) {
throw new Error('Lifecycle cannot go backwards');
}
if (this._phase === value) {
return;
}
this.logService.trace(`lifecycle: phase changed (value: ${value})`);
this._phase = value;
mark(`LifecyclePhase/${LifecyclePhaseToString(value)}`);
const barrier = this.phaseWhen.get(this._phase);
if (barrier) {
barrier.open();
this.phaseWhen.delete(this._phase);
}
}
when(phase: LifecyclePhase): Promise<any> {
if (phase <= this._phase) {
return Promise.resolve();
}
let barrier = this.phaseWhen.get(phase);
if (!barrier) {
barrier = new Barrier();
this.phaseWhen.set(phase, barrier);
}
return barrier.wait();
}
}
@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event } from 'vs/base/common/event';
import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class LocalizationsService implements ILocalizationsService {
_serviceBrand: ServiceIdentifier<any>;
private channel: IChannel;
constructor(@ISharedProcessService sharedProcessService: ISharedProcessService) {
this.channel = sharedProcessService.getChannel('localizations');
}
get onDidLanguagesChange(): Event<void> { return this.channel.listen('onDidLanguagesChange'); }
getLanguageIds(type?: LanguageType): Promise<string[]> {
return this.channel.call('getLanguageIds', type);
}
}
@@ -3,10 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event } from 'vs/base/common/event';
import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
export class LocalizationsChannel implements IServerChannel {
@@ -32,20 +31,3 @@ export class LocalizationsChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class LocalizationsChannelClient implements ILocalizationsService {
_serviceBrand: any;
private channel: IChannel;
constructor(@ISharedProcessService sharedProcessService: ISharedProcessService) {
this.channel = sharedProcessService.getChannel('localizations');
}
get onDidLanguagesChange(): Event<void> { return this.channel.listen('onDidLanguagesChange'); }
getLanguageIds(type?: LanguageType): Promise<string[]> {
return this.channel.call('getLanguageIds', type);
}
}
@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class MenubarService implements IMenubarService {
_serviceBrand: ServiceIdentifier<any>;
private channel: IChannel;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
this.channel = mainProcessService.getChannel('menubar');
}
updateMenubar(windowId: number, menuData: IMenubarData): Promise<void> {
return this.channel.call('updateMenubar', [windowId, menuData]);
}
}
+4 -14
View File
@@ -2,8 +2,9 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { Event } from 'vs/base/common/event';
export class MenubarChannel implements IServerChannel {
@@ -21,15 +22,4 @@ export class MenubarChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class MenubarChannelClient implements IMenubarService {
_serviceBrand: any;
constructor(private channel: IChannel) { }
updateMenubar(windowId: number, menuData: IMenubarData): Promise<void> {
return this.channel.call('updateMenubar', [windowId, menuData]);
}
}
}
@@ -9,7 +9,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { Disposable } from 'vs/base/common/lifecycle';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IProductService } from 'vs/platform/product/common/product';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { ILogService } from 'vs/platform/log/common/log';
import { IStorageService } from 'vs/platform/storage/common/storage';
@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { IUpdateService, State } from 'vs/platform/update/common/update';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class UpdateService implements IUpdateService {
_serviceBrand: ServiceIdentifier<any>;
private _onStateChange = new Emitter<State>();
get onStateChange(): Event<State> { return this._onStateChange.event; }
private _state: State = State.Uninitialized;
get state(): State { return this._state; }
private channel: IChannel;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
this.channel = mainProcessService.getChannel('update');
// always set this._state as the state changes
this.onStateChange(state => this._state = state);
this.channel.call<State>('_getInitialState').then(state => {
// fire initial state
this._onStateChange.fire(state);
// fire subsequent states as they come in from remote
this.channel.listen<State>('onStateChange')(state => this._onStateChange.fire(state));
});
}
checkForUpdates(context: any): Promise<void> {
return this.channel.call('checkForUpdates', context);
}
downloadUpdate(): Promise<void> {
return this.channel.call('downloadUpdate');
}
applyUpdate(): Promise<void> {
return this.channel.call('applyUpdate');
}
quitAndInstall(): Promise<void> {
return this.channel.call('quitAndInstall');
}
isLatestVersion(): Promise<boolean> {
return this.channel.call('isLatestVersion');
}
}
+4 -49
View File
@@ -3,9 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { IUpdateService, State } from 'vs/platform/update/common/update';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event } from 'vs/base/common/event';
import { IUpdateService } from 'vs/platform/update/common/update';
export class UpdateChannel implements IServerChannel {
@@ -31,49 +31,4 @@ export class UpdateChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class UpdateChannelClient implements IUpdateService {
_serviceBrand: any;
private _onStateChange = new Emitter<State>();
get onStateChange(): Event<State> { return this._onStateChange.event; }
private _state: State = State.Uninitialized;
get state(): State { return this._state; }
constructor(private channel: IChannel) {
// always set this._state as the state changes
this.onStateChange(state => this._state = state);
channel.call<State>('_getInitialState').then(state => {
// fire initial state
this._onStateChange.fire(state);
// fire subsequent states as they come in from remote
this.channel.listen<State>('onStateChange')(state => this._onStateChange.fire(state));
});
}
checkForUpdates(context: any): Promise<void> {
return this.channel.call('checkForUpdates', context);
}
downloadUpdate(): Promise<void> {
return this.channel.call('downloadUpdate');
}
applyUpdate(): Promise<void> {
return this.channel.call('applyUpdate');
}
quitAndInstall(): Promise<void> {
return this.channel.call('quitAndInstall');
}
isLatestVersion(): Promise<boolean> {
return this.channel.call('isLatestVersion');
}
}
}
+2 -16
View File
@@ -8,10 +8,11 @@ import { URI } from 'vs/base/common/uri';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { first } from 'vs/base/common/async';
import { values } from 'vs/base/common/map';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class URLService implements IURLService {
_serviceBrand: any;
_serviceBrand: ServiceIdentifier<any>;
private handlers = new Set<IURLHandler>();
@@ -25,18 +26,3 @@ export class URLService implements IURLService {
return toDisposable(() => this.handlers.delete(handler));
}
}
export class RelayURLService extends URLService implements IURLHandler {
constructor(private urlService: IURLService) {
super();
}
open(uri: URI): Promise<boolean> {
return this.urlService.open(uri);
}
handleURL(uri: URI): Promise<boolean> {
return super.open(uri);
}
}
@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
import { URI } from 'vs/base/common/uri';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { URLServiceChannelClient, URLHandlerChannel } from 'vs/platform/url/node/urlIpc';
import { URLService } from 'vs/platform/url/common/urlService';
export class RelayURLService extends URLService implements IURLHandler {
private urlService: IURLService;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
super();
this.urlService = new URLServiceChannelClient(mainProcessService.getChannel('url'));
mainProcessService.registerChannel('urlHandler', new URLHandlerChannel(this));
}
open(uri: URI): Promise<boolean> {
return this.urlService.open(uri);
}
handleURL(uri: URI): Promise<boolean> {
return super.open(uri);
}
}
@@ -0,0 +1,250 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions, INewWindowOptions, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened, IRecent, isRecentWorkspace } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { URI } from 'vs/base/common/uri';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
export class WindowsService implements IWindowsService {
_serviceBrand: any;
private channel: IChannel;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
this.channel = mainProcessService.getChannel('windows');
}
get onWindowOpen(): Event<number> { return this.channel.listen('onWindowOpen'); }
get onWindowFocus(): Event<number> { return this.channel.listen('onWindowFocus'); }
get onWindowBlur(): Event<number> { return this.channel.listen('onWindowBlur'); }
get onWindowMaximize(): Event<number> { return this.channel.listen('onWindowMaximize'); }
get onWindowUnmaximize(): Event<number> { return this.channel.listen('onWindowUnmaximize'); }
get onRecentlyOpenedChange(): Event<void> { return this.channel.listen('onRecentlyOpenedChange'); }
pickFileFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFileFolderAndOpen', options);
}
pickFileAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFileAndOpen', options);
}
pickFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFolderAndOpen', options);
}
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickWorkspaceAndOpen', options);
}
showMessageBox(windowId: number, options: MessageBoxOptions): Promise<IMessageBoxResult> {
return this.channel.call('showMessageBox', [windowId, options]);
}
showSaveDialog(windowId: number, options: SaveDialogOptions): Promise<string> {
return this.channel.call('showSaveDialog', [windowId, options]);
}
showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<string[]> {
return this.channel.call('showOpenDialog', [windowId, options]);
}
reloadWindow(windowId: number, args?: ParsedArgs): Promise<void> {
return this.channel.call('reloadWindow', [windowId, args]);
}
openDevTools(windowId: number, options?: IDevToolsOptions): Promise<void> {
return this.channel.call('openDevTools', [windowId, options]);
}
toggleDevTools(windowId: number): Promise<void> {
return this.channel.call('toggleDevTools', windowId);
}
closeWorkspace(windowId: number): Promise<void> {
return this.channel.call('closeWorkspace', windowId);
}
enterWorkspace(windowId: number, path: URI): Promise<IEnterWorkspaceResult> {
return this.channel.call('enterWorkspace', [windowId, path]).then((result: IEnterWorkspaceResult) => {
result.workspace = reviveWorkspaceIdentifier(result.workspace);
return result;
});
}
toggleFullScreen(windowId: number): Promise<void> {
return this.channel.call('toggleFullScreen', windowId);
}
setRepresentedFilename(windowId: number, fileName: string): Promise<void> {
return this.channel.call('setRepresentedFilename', [windowId, fileName]);
}
addRecentlyOpened(recent: IRecent[]): Promise<void> {
return this.channel.call('addRecentlyOpened', recent);
}
removeFromRecentlyOpened(paths: Array<URI>): Promise<void> {
return this.channel.call('removeFromRecentlyOpened', paths);
}
clearRecentlyOpened(): Promise<void> {
return this.channel.call('clearRecentlyOpened');
}
getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
return this.channel.call('getRecentlyOpened', windowId)
.then((recentlyOpened: IRecentlyOpened) => {
recentlyOpened.workspaces.forEach(recent => isRecentWorkspace(recent) ? recent.workspace = reviveWorkspaceIdentifier(recent.workspace) : recent.folderUri = URI.revive(recent.folderUri));
recentlyOpened.files.forEach(recent => recent.fileUri = URI.revive(recent.fileUri));
return recentlyOpened;
});
}
newWindowTab(): Promise<void> {
return this.channel.call('newWindowTab');
}
showPreviousWindowTab(): Promise<void> {
return this.channel.call('showPreviousWindowTab');
}
showNextWindowTab(): Promise<void> {
return this.channel.call('showNextWindowTab');
}
moveWindowTabToNewWindow(): Promise<void> {
return this.channel.call('moveWindowTabToNewWindow');
}
mergeAllWindowTabs(): Promise<void> {
return this.channel.call('mergeAllWindowTabs');
}
toggleWindowTabsBar(): Promise<void> {
return this.channel.call('toggleWindowTabsBar');
}
focusWindow(windowId: number): Promise<void> {
return this.channel.call('focusWindow', windowId);
}
closeWindow(windowId: number): Promise<void> {
return this.channel.call('closeWindow', windowId);
}
isFocused(windowId: number): Promise<boolean> {
return this.channel.call('isFocused', windowId);
}
isMaximized(windowId: number): Promise<boolean> {
return this.channel.call('isMaximized', windowId);
}
maximizeWindow(windowId: number): Promise<void> {
return this.channel.call('maximizeWindow', windowId);
}
unmaximizeWindow(windowId: number): Promise<void> {
return this.channel.call('unmaximizeWindow', windowId);
}
minimizeWindow(windowId: number): Promise<void> {
return this.channel.call('minimizeWindow', windowId);
}
onWindowTitleDoubleClick(windowId: number): Promise<void> {
return this.channel.call('onWindowTitleDoubleClick', windowId);
}
setDocumentEdited(windowId: number, flag: boolean): Promise<void> {
return this.channel.call('setDocumentEdited', [windowId, flag]);
}
quit(): Promise<void> {
return this.channel.call('quit');
}
relaunch(options: { addArgs?: string[], removeArgs?: string[] }): Promise<void> {
return this.channel.call('relaunch', [options]);
}
whenSharedProcessReady(): Promise<void> {
return this.channel.call('whenSharedProcessReady');
}
toggleSharedProcess(): Promise<void> {
return this.channel.call('toggleSharedProcess');
}
openWindow(windowId: number, uris: IURIToOpen[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }): Promise<void> {
return this.channel.call('openWindow', [windowId, uris, options]);
}
openNewWindow(options?: INewWindowOptions): Promise<void> {
return this.channel.call('openNewWindow', options);
}
showWindow(windowId: number): Promise<void> {
return this.channel.call('showWindow', windowId);
}
getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
return this.channel.call<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>('getWindows').then(result => {
for (const win of result) {
if (win.folderUri) {
win.folderUri = URI.revive(win.folderUri);
}
if (win.workspace) {
win.workspace = reviveWorkspaceIdentifier(win.workspace);
}
}
return result;
});
}
getWindowCount(): Promise<number> {
return this.channel.call('getWindowCount');
}
log(severity: string, ...messages: string[]): Promise<void> {
return this.channel.call('log', [severity, messages]);
}
showItemInFolder(path: URI): Promise<void> {
return this.channel.call('showItemInFolder', path);
}
getActiveWindowId(): Promise<number | undefined> {
return this.channel.call('getActiveWindowId');
}
openExternal(url: string): Promise<boolean> {
return this.channel.call('openExternal', url);
}
startCrashReporter(config: CrashReporterStartOptions): Promise<void> {
return this.channel.call('startCrashReporter', config);
}
updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): Promise<void> {
return this.channel.call('updateTouchBar', [windowId, items]);
}
openAboutDialog(): Promise<void> {
return this.channel.call('openAboutDialog');
}
resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return Promise.resolve(this.channel.call('resolveProxy', [windowId, url]));
}
}
+4 -238
View File
@@ -4,13 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions, INewWindowOptions, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened, isRecentFile, isRecentFolder, IRecent, isRecentWorkspace } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWindowsService, IURIToOpen } from 'vs/platform/windows/common/windows';
import { reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { IRecent, isRecentFile, isRecentFolder } from 'vs/platform/history/common/history';
export class WindowsChannel implements IServerChannel {
@@ -108,236 +106,4 @@ export class WindowsChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class WindowsChannelClient implements IWindowsService {
_serviceBrand: any;
constructor(private channel: IChannel) { }
get onWindowOpen(): Event<number> { return this.channel.listen('onWindowOpen'); }
get onWindowFocus(): Event<number> { return this.channel.listen('onWindowFocus'); }
get onWindowBlur(): Event<number> { return this.channel.listen('onWindowBlur'); }
get onWindowMaximize(): Event<number> { return this.channel.listen('onWindowMaximize'); }
get onWindowUnmaximize(): Event<number> { return this.channel.listen('onWindowUnmaximize'); }
get onRecentlyOpenedChange(): Event<void> { return this.channel.listen('onRecentlyOpenedChange'); }
pickFileFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFileFolderAndOpen', options);
}
pickFileAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFileAndOpen', options);
}
pickFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickFolderAndOpen', options);
}
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): Promise<void> {
return this.channel.call('pickWorkspaceAndOpen', options);
}
showMessageBox(windowId: number, options: MessageBoxOptions): Promise<IMessageBoxResult> {
return this.channel.call('showMessageBox', [windowId, options]);
}
showSaveDialog(windowId: number, options: SaveDialogOptions): Promise<string> {
return this.channel.call('showSaveDialog', [windowId, options]);
}
showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<string[]> {
return this.channel.call('showOpenDialog', [windowId, options]);
}
reloadWindow(windowId: number, args?: ParsedArgs): Promise<void> {
return this.channel.call('reloadWindow', [windowId, args]);
}
openDevTools(windowId: number, options?: IDevToolsOptions): Promise<void> {
return this.channel.call('openDevTools', [windowId, options]);
}
toggleDevTools(windowId: number): Promise<void> {
return this.channel.call('toggleDevTools', windowId);
}
closeWorkspace(windowId: number): Promise<void> {
return this.channel.call('closeWorkspace', windowId);
}
enterWorkspace(windowId: number, path: URI): Promise<IEnterWorkspaceResult> {
return this.channel.call('enterWorkspace', [windowId, path]).then((result: IEnterWorkspaceResult) => {
result.workspace = reviveWorkspaceIdentifier(result.workspace);
return result;
});
}
toggleFullScreen(windowId: number): Promise<void> {
return this.channel.call('toggleFullScreen', windowId);
}
setRepresentedFilename(windowId: number, fileName: string): Promise<void> {
return this.channel.call('setRepresentedFilename', [windowId, fileName]);
}
addRecentlyOpened(recent: IRecent[]): Promise<void> {
return this.channel.call('addRecentlyOpened', recent);
}
removeFromRecentlyOpened(paths: Array<URI>): Promise<void> {
return this.channel.call('removeFromRecentlyOpened', paths);
}
clearRecentlyOpened(): Promise<void> {
return this.channel.call('clearRecentlyOpened');
}
getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
return this.channel.call('getRecentlyOpened', windowId)
.then((recentlyOpened: IRecentlyOpened) => {
recentlyOpened.workspaces.forEach(recent => isRecentWorkspace(recent) ? recent.workspace = reviveWorkspaceIdentifier(recent.workspace) : recent.folderUri = URI.revive(recent.folderUri));
recentlyOpened.files.forEach(recent => recent.fileUri = URI.revive(recent.fileUri));
return recentlyOpened;
});
}
newWindowTab(): Promise<void> {
return this.channel.call('newWindowTab');
}
showPreviousWindowTab(): Promise<void> {
return this.channel.call('showPreviousWindowTab');
}
showNextWindowTab(): Promise<void> {
return this.channel.call('showNextWindowTab');
}
moveWindowTabToNewWindow(): Promise<void> {
return this.channel.call('moveWindowTabToNewWindow');
}
mergeAllWindowTabs(): Promise<void> {
return this.channel.call('mergeAllWindowTabs');
}
toggleWindowTabsBar(): Promise<void> {
return this.channel.call('toggleWindowTabsBar');
}
focusWindow(windowId: number): Promise<void> {
return this.channel.call('focusWindow', windowId);
}
closeWindow(windowId: number): Promise<void> {
return this.channel.call('closeWindow', windowId);
}
isFocused(windowId: number): Promise<boolean> {
return this.channel.call('isFocused', windowId);
}
isMaximized(windowId: number): Promise<boolean> {
return this.channel.call('isMaximized', windowId);
}
maximizeWindow(windowId: number): Promise<void> {
return this.channel.call('maximizeWindow', windowId);
}
unmaximizeWindow(windowId: number): Promise<void> {
return this.channel.call('unmaximizeWindow', windowId);
}
minimizeWindow(windowId: number): Promise<void> {
return this.channel.call('minimizeWindow', windowId);
}
onWindowTitleDoubleClick(windowId: number): Promise<void> {
return this.channel.call('onWindowTitleDoubleClick', windowId);
}
setDocumentEdited(windowId: number, flag: boolean): Promise<void> {
return this.channel.call('setDocumentEdited', [windowId, flag]);
}
quit(): Promise<void> {
return this.channel.call('quit');
}
relaunch(options: { addArgs?: string[], removeArgs?: string[] }): Promise<void> {
return this.channel.call('relaunch', [options]);
}
whenSharedProcessReady(): Promise<void> {
return this.channel.call('whenSharedProcessReady');
}
toggleSharedProcess(): Promise<void> {
return this.channel.call('toggleSharedProcess');
}
openWindow(windowId: number, uris: IURIToOpen[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }): Promise<void> {
return this.channel.call('openWindow', [windowId, uris, options]);
}
openNewWindow(options?: INewWindowOptions): Promise<void> {
return this.channel.call('openNewWindow', options);
}
showWindow(windowId: number): Promise<void> {
return this.channel.call('showWindow', windowId);
}
getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
return this.channel.call<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>('getWindows').then(result => {
for (const win of result) {
if (win.folderUri) {
win.folderUri = URI.revive(win.folderUri);
}
if (win.workspace) {
win.workspace = reviveWorkspaceIdentifier(win.workspace);
}
}
return result;
});
}
getWindowCount(): Promise<number> {
return this.channel.call('getWindowCount');
}
log(severity: string, ...messages: string[]): Promise<void> {
return this.channel.call('log', [severity, messages]);
}
showItemInFolder(path: URI): Promise<void> {
return this.channel.call('showItemInFolder', path);
}
getActiveWindowId(): Promise<number | undefined> {
return this.channel.call('getActiveWindowId');
}
openExternal(url: string): Promise<boolean> {
return this.channel.call('openExternal', url);
}
startCrashReporter(config: CrashReporterStartOptions): Promise<void> {
return this.channel.call('startCrashReporter', config);
}
updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): Promise<void> {
return this.channel.call('updateTouchBar', [windowId, items]);
}
openAboutDialog(): Promise<void> {
return this.channel.call('openAboutDialog');
}
resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return Promise.resolve(this.channel.call('resolveProxy', [windowId, url]));
}
}
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
export class WorkspacesService implements IWorkspacesService {
_serviceBrand: ServiceIdentifier<any>;
private channel: IChannel;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
this.channel = mainProcessService.getChannel('workspaces');
}
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
return this.channel.call('createUntitledWorkspace', [folders, remoteAuthority]).then(reviveWorkspaceIdentifier);
}
deleteUntitledWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
return this.channel.call('deleteUntitledWorkspace', workspaceIdentifier);
}
getWorkspaceIdentifier(configPath: URI): Promise<IWorkspaceIdentifier> {
return this.channel.call('getWorkspaceIdentifier', configPath);
}
}
@@ -3,8 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesMainService, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
@@ -45,22 +45,3 @@ export class WorkspacesChannel implements IServerChannel {
throw new Error(`Call not found: ${command}`);
}
}
export class WorkspacesChannelClient implements IWorkspacesService {
_serviceBrand: any;
constructor(private channel: IChannel) { }
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
return this.channel.call('createUntitledWorkspace', [folders, remoteAuthority]).then(reviveWorkspaceIdentifier);
}
deleteUntitledWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
return this.channel.call('deleteUntitledWorkspace', workspaceIdentifier);
}
getWorkspaceIdentifier(configPath: URI): Promise<IWorkspaceIdentifier> {
return this.channel.call('getWorkspaceIdentifier', configPath);
}
}
+56
View File
@@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mark } from 'vs/base/common/performance';
import { domContentLoaded, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILogService } from 'vs/platform/log/common/log';
import { Disposable } from 'vs/base/common/lifecycle';
import { SimpleLogService } from 'vs/workbench/browser/nodeless.simpleservices';
import { Workbench } from 'vs/workbench/browser/workbench';
class CodeRendererMain extends Disposable {
private workbench: Workbench;
open(): Promise<void> {
const services = this.initServices();
return domContentLoaded().then(() => {
mark('willStartWorkbench');
// Create Workbench
this.workbench = new Workbench(
document.body,
services.serviceCollection,
services.logService
);
// Layout
this._register(addDisposableListener(window, EventType.RESIZE, () => this.workbench.layout()));
// Workbench Lifecycle
this._register(this.workbench.onShutdown(() => this.dispose()));
// Startup
this.workbench.startup();
});
}
private initServices(): { serviceCollection: ServiceCollection, logService: ILogService } {
const serviceCollection = new ServiceCollection();
const logService = new SimpleLogService();
serviceCollection.set(ILogService, logService);
return { serviceCollection, logService };
}
}
export function main(): Promise<void> {
const renderer = new CodeRendererMain();
return renderer.open();
}
File diff suppressed because it is too large Load Diff
@@ -57,6 +57,7 @@ export class NotificationsCenter extends Themable {
private registerListeners(): void {
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
this._register(this.layoutService.onLayout(dimension => this.layout(dimension)));
}
get isVisible(): boolean {
@@ -79,6 +79,9 @@ export class NotificationsToasts extends Themable {
private registerListeners(): void {
// Layout
this._register(this.layoutService.onLayout(dimension => this.layout(dimension)));
// Delay some tasks until after we can show notifications
this.onCanShowNotifications().then(() => {
+255 -318
View File
@@ -24,7 +24,6 @@ import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet';
import { getServices } from 'vs/platform/instantiation/common/extensions';
import { Position, Parts, IWorkbenchLayoutService, ILayoutOptions } from 'vs/workbench/services/layout/browser/layoutService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
@@ -61,6 +60,8 @@ import { IDimension } from 'vs/platform/layout/browser/layoutService';
import { Part } from 'vs/workbench/browser/part';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
import { coalesce } from 'vs/base/common/arrays';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
export interface IWorkbenchOptions {
hasInitialFilesToOpen: boolean;
@@ -90,8 +91,6 @@ enum Storage {
export class Workbench extends Disposable implements IWorkbenchLayoutService {
//#region workbench
_serviceBrand: ServiceIdentifier<any>;
private readonly _onShutdown = this._register(new Emitter<void>());
@@ -100,47 +99,19 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
private previousErrorValue: string;
private previousErrorTime = 0;
private workbench: HTMLElement;
private restored: boolean;
private disposed: boolean;
private instantiationService: IInstantiationService;
private contextService: IWorkspaceContextService;
private storageService: IStorageService;
private configurationService: IConfigurationService;
private environmentService: IEnvironmentService;
private logService: ILogService;
private parts: Map<string, Part> = new Map<string, Part>();
private workbench: HTMLElement = document.createElement('div');
constructor(
private parent: HTMLElement,
private options: IWorkbenchOptions,
private serviceCollection: ServiceCollection,
@IInstantiationService instantiationService: IInstantiationService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService,
@IConfigurationService configurationService: IConfigurationService,
@IEnvironmentService environmentService: IEnvironmentService,
@ILogService logService: ILogService
private readonly parent: HTMLElement,
private readonly serviceCollection: ServiceCollection,
logService: ILogService
) {
super();
this.instantiationService = instantiationService;
this.contextService = contextService;
this.storageService = storageService;
this.configurationService = configurationService;
this.environmentService = environmentService;
this.logService = logService;
this.registerErrorHandler();
this.registerErrorHandler(logService);
}
private registerErrorHandler(): void {
private registerErrorHandler(logService: ILogService): void {
// Listen on unhandled rejection events
window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
@@ -153,7 +124,7 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
});
// Install handler for unexpected errors
setUnexpectedErrorHandler(error => this.handleUnexpectedError(error));
setUnexpectedErrorHandler(error => this.handleUnexpectedError(error, logService));
// Inform user about loading issues from the loader
(<any>self).require.config({
@@ -165,117 +136,107 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
});
}
private handleUnexpectedError(error: any): void {
const errorMsg = toErrorMessage(error, true);
if (!errorMsg) {
private previousUnexpectedError: { message: string, time: number } = { message: undefined, time: 0 };
private handleUnexpectedError(error: any, logService: ILogService): void {
const message = toErrorMessage(error, true);
if (!message) {
return;
}
const now = Date.now();
if (errorMsg === this.previousErrorValue && now - this.previousErrorTime <= 1000) {
if (message === this.previousUnexpectedError.message && now - this.previousUnexpectedError.time <= 1000) {
return; // Return if error message identical to previous and shorter than 1 second
}
this.previousErrorTime = now;
this.previousErrorValue = errorMsg;
this.previousUnexpectedError.time = now;
this.previousUnexpectedError.message = message;
// Log it
this.logService.error(errorMsg);
logService.error(message);
}
startup(): void {
startup(): IInstantiationService {
try {
this.doStartup().then(undefined, error => this.logService.error(toErrorMessage(error, true)));
// Configure emitter leak warning threshold
setGlobalLeakWarningThreshold(175);
// Setup Intl for comparers
setFileNameComparer(new IdleValue(() => {
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
return {
collator: collator,
collatorIsNumeric: collator.resolvedOptions().numeric
};
}));
// ARIA
setARIAContainer(document.body);
// Services
const instantiationService = this.initServices(this.serviceCollection);
instantiationService.invokeFunction(accessor => {
const lifecycleService = accessor.get(ILifecycleService);
const storageService = accessor.get(IStorageService);
const configurationService = accessor.get(IConfigurationService);
// Layout
this.initLayout(accessor);
// Registries
this.initRegistries(accessor);
// Context Keys
this._register(instantiationService.createInstance(WorkbenchContextKeysHandler));
// Register Listeners
this.registerListeners(lifecycleService, storageService, configurationService);
// Render Workbench
this.renderWorkbench(instantiationService, accessor.get(INotificationService) as NotificationService, storageService, configurationService);
// Workbench Layout
this.createWorkbenchLayout(instantiationService);
// Layout
this.layout();
// Restore
this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService).then(undefined, error => onUnexpectedError(error));
});
return instantiationService;
} catch (error) {
this.logService.error(toErrorMessage(error, true));
onUnexpectedError(error);
throw error; // rethrow because this is a critical issue we cannot handle properly here
}
}
private doStartup(): Promise<void> {
// Configure emitter leak warning threshold
setGlobalLeakWarningThreshold(175);
// Setup Intl for comparers
setFileNameComparer(new IdleValue(() => {
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
return {
collator: collator,
collatorIsNumeric: collator.resolvedOptions().numeric
};
}));
// ARIA
setARIAContainer(document.body);
// Warm up font cache information before building up too many dom elements
restoreFontInfo(this.storageService);
readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), getZoomLevel()));
// Create Workbench Container
this.createWorkbenchContainer();
// Services
this.initServices(this.serviceCollection);
// Registries
this.startRegistries();
// Context Keys
this._register(this.instantiationService.createInstance(WorkbenchContextKeysHandler));
// Register Listeners
this.instantiationService.invokeFunction(accessor => {
this.registerListeners(accessor);
this.registerLayoutListeners(accessor);
});
// Layout State
this.instantiationService.invokeFunction(accessor => this.initLayoutState(accessor));
// Render Workbench
this.renderWorkbench();
// Workbench Layout
this.createWorkbenchLayout();
// Layout
this.layout();
// Restore
return this.instantiationService.invokeFunction(accessor => this.restoreWorkbench(accessor));
}
private createWorkbenchContainer(): void {
this.workbench = document.createElement('div');
const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac';
addClasses(this.workbench, 'monaco-workbench', platformClass);
addClasses(document.body, platformClass); // used by our fonts
}
private initServices(serviceCollection: ServiceCollection): void {
private initServices(serviceCollection: ServiceCollection): IInstantiationService {
// Layout Service
serviceCollection.set(IWorkbenchLayoutService, this);
//
// NOTE: DO NOT ADD ANY OTHER SERVICE INTO THE COLLECTION HERE.
// INSTEAD, CONTRIBUTE IT VIA WORKBENCH.MAIN.TS
//
// All Contributed Services
const contributedServices = getServices();
for (let contributedService of contributedServices) {
serviceCollection.set(contributedService.id, contributedService.descriptor);
}
const instantationServie = new InstantiationService(serviceCollection, true);
// Wrap up
this.instantiationService.invokeFunction(accessor => {
// Signal to lifecycle that services are set
instantationServie.invokeFunction(accessor => {
const lifecycleService = accessor.get(ILifecycleService);
lifecycleService.phase = LifecyclePhase.Ready;
// TODO@Sandeep TODO@Martin debt around cyclic dependencies
// TODO@Ben TODO@Sandeep TODO@Martin debt around cyclic dependencies
const fileService = accessor.get(IFileService);
const instantiationService = accessor.get(IInstantiationService);
const configurationService = accessor.get(IConfigurationService) as any;
@@ -292,21 +253,25 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
if (typeof themeService.acquireFileService === 'function') {
themeService.acquireFileService(fileService);
}
// Signal to lifecycle that services are set
lifecycleService.phase = LifecyclePhase.Ready;
});
return instantationServie;
}
private startRegistries(): void {
this.instantiationService.invokeFunction(accessor => {
Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar).start(accessor);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(accessor);
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor);
});
private initRegistries(accessor: ServicesAccessor): void {
Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar).start(accessor);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(accessor);
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor);
}
private registerListeners(accessor: ServicesAccessor): void {
const lifecycleService = accessor.get(ILifecycleService);
const storageService = accessor.get(IStorageService);
const configurationService = accessor.get(IConfigurationService);
private registerListeners(
lifecycleService: ILifecycleService,
storageService: IStorageService,
configurationService: IConfigurationService
): void {
// Lifecycle
this._register(lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event)));
@@ -316,15 +281,15 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}));
// Storage
this._register(storageService.onWillSaveState(e => this.saveState(e)));
this._register(storageService.onWillSaveState(() => saveFontInfo(storageService)));
// Configuration changes
this._register(configurationService.onDidChangeConfiguration(() => this.setFontAliasing()));
this._register(configurationService.onDidChangeConfiguration(() => this.setFontAliasing(configurationService)));
}
private fontAliasing: 'default' | 'antialiased' | 'none' | 'auto';
private setFontAliasing() {
const aliasing = this.configurationService.getValue<'default' | 'antialiased' | 'none' | 'auto'>(Settings.FONT_ALIASING);
private setFontAliasing(configurationService: IConfigurationService) {
const aliasing = configurationService.getValue<'default' | 'antialiased' | 'none' | 'auto'>(Settings.FONT_ALIASING);
if (this.fontAliasing === aliasing) {
return;
}
@@ -341,100 +306,73 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
}
private renderWorkbench(): void {
if (this.state.sideBar.hidden) {
addClass(this.workbench, 'nosidebar');
}
private renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void {
if (this.state.panel.hidden) {
addClass(this.workbench, 'nopanel');
}
// State specific classes
const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac';
const workbenchClasses = coalesce([
'monaco-workbench',
platformClass,
this.state.sideBar.hidden ? 'nosidebar' : undefined,
this.state.panel.hidden ? 'nopanel' : undefined,
this.state.statusBar.hidden ? 'nostatusbar' : undefined,
this.state.fullscreen ? 'fullscreen' : undefined
]);
if (this.state.statusBar.hidden) {
addClass(this.workbench, 'nostatusbar');
}
if (this.state.fullscreen) {
addClass(this.workbench, 'fullscreen');
}
addClasses(this.workbench, ...workbenchClasses);
addClasses(document.body, platformClass); // used by our fonts
// Apply font aliasing
this.setFontAliasing();
this.setFontAliasing(configurationService);
// Warm up font cache information before building up too many dom elements
restoreFontInfo(storageService);
readFontInfo(BareFontInfo.createFromRawSettings(configurationService.getValue('editor'), getZoomLevel()));
// Create Parts
this.createTitlebarPart();
this.createActivityBarPart();
this.createSidebarPart();
this.createEditorPart();
this.createPanelPart();
this.createStatusbarPart();
[
{ id: Parts.TITLEBAR_PART, role: 'contentinfo', classes: ['titlebar'] },
{ id: Parts.ACTIVITYBAR_PART, role: 'navigation', classes: ['activitybar', this.state.sideBar.position === Position.LEFT ? 'left' : 'right'] },
{ id: Parts.SIDEBAR_PART, role: 'complementary', classes: ['sidebar', this.state.sideBar.position === Position.LEFT ? 'left' : 'right'] },
{ id: Parts.PANEL_PART, role: 'complementary', classes: ['panel', this.state.panel.position === Position.BOTTOM ? 'bottom' : 'right'] },
{ id: Parts.EDITOR_PART, role: 'main', classes: ['editor'], options: { restorePreviousState: this.state.editor.restoreEditors } },
{ id: Parts.STATUSBAR_PART, role: 'contentinfo', classes: ['statusbar'] }
].forEach(({ id, role, classes, options }) => {
const partContainer = this.createPart(id, role, classes);
if (!configurationService.getValue('workbench.useExperimentalGridLayout')) {
// TODO@Ben cleanup once moved to grid
// Insert all workbench parts at the beginning. Issue #52531
// This is primarily for the title bar to allow overriding -webkit-app-region
this.workbench.insertBefore(partContainer, this.workbench.lastChild);
}
this.parts.get(id).create(partContainer, options);
});
// Notification Handlers
this.instantiationService.invokeFunction(accessor => this.createNotificationsHandlers(accessor));
this.createNotificationsHandlers(instantiationService, notificationService);
// Add Workbench to DOM
this.parent.appendChild(this.workbench);
}
private createTitlebarPart(): void {
const titlebarContainer = this.createPart(Parts.TITLEBAR_PART, 'contentinfo', 'titlebar');
this.parts.get(Parts.TITLEBAR_PART).create(titlebarContainer);
}
private createActivityBarPart(): void {
const activitybarPartContainer = this.createPart(Parts.ACTIVITYBAR_PART, 'navigation', 'activitybar', this.state.sideBar.position === Position.LEFT ? 'left' : 'right');
this.parts.get(Parts.ACTIVITYBAR_PART).create(activitybarPartContainer);
}
private createSidebarPart(): void {
const sidebarPartContainer = this.createPart(Parts.SIDEBAR_PART, 'complementary', 'sidebar', this.state.sideBar.position === Position.LEFT ? 'left' : 'right');
this.parts.get(Parts.SIDEBAR_PART).create(sidebarPartContainer);
}
private createPanelPart(): void {
const panelPartContainer = this.createPart(Parts.PANEL_PART, 'complementary', 'panel', this.state.panel.position === Position.BOTTOM ? 'bottom' : 'right');
this.parts.get(Parts.PANEL_PART).create(panelPartContainer);
}
private createEditorPart(): void {
const editorContainer = this.createPart(Parts.EDITOR_PART, 'main', 'editor');
this.parts.get(Parts.EDITOR_PART).create(editorContainer, { restorePreviousState: !this.options.hasInitialFilesToOpen });
}
private createStatusbarPart(): void {
const statusbarContainer = this.createPart(Parts.STATUSBAR_PART, 'contentinfo', 'statusbar');
this.parts.get(Parts.STATUSBAR_PART).create(statusbarContainer);
}
private createPart(id: string, role: string, ...classes: string[]): HTMLElement {
private createPart(id: string, role: string, classes: string[]): HTMLElement {
const part = document.createElement('div');
addClasses(part, 'part', ...classes);
part.id = id;
part.setAttribute('role', role);
if (!this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
// Insert all workbench parts at the beginning. Issue #52531
// This is primarily for the title bar to allow overriding -webkit-app-region
this.workbench.insertBefore(part, this.workbench.lastChild);
}
return part;
}
private createNotificationsHandlers(accessor: ServicesAccessor): void {
const notificationService = accessor.get(INotificationService) as NotificationService;
private createNotificationsHandlers(instantiationService: IInstantiationService, notificationService: NotificationService): void {
// Instantiate Notification components
const notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, notificationService.model));
const notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, notificationService.model));
this._register(this.instantiationService.createInstance(NotificationsAlerts, notificationService.model));
const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, notificationService.model);
const notificationsCenter = this._register(instantiationService.createInstance(NotificationsCenter, this.workbench, notificationService.model));
const notificationsToasts = this._register(instantiationService.createInstance(NotificationsToasts, this.workbench, notificationService.model));
this._register(instantiationService.createInstance(NotificationsAlerts, notificationService.model));
const notificationsStatus = instantiationService.createInstance(NotificationsStatus, notificationService.model);
// Visibility
this._register(notificationsCenter.onDidChangeVisibility(() => {
@@ -442,23 +380,18 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
notificationsToasts.update(notificationsCenter.isVisible);
}));
// Layout
this._register(this.onLayout(dimension => {
notificationsCenter.layout(dimension);
notificationsToasts.layout(dimension);
}));
// Register Commands
registerNotificationCommands(notificationsCenter, notificationsToasts);
}
private restoreWorkbench(accessor: ServicesAccessor): Promise<void> {
const editorService = accessor.get(IEditorService);
const editorGroupService = accessor.get(IEditorGroupsService);
const viewletService = accessor.get(IViewletService);
const panelService = accessor.get(IPanelService);
const logService = accessor.get(ILogService);
private restoreWorkbench(
editorService: IEditorService,
editorGroupService: IEditorGroupsService,
viewletService: IViewletService,
panelService: IPanelService,
logService: ILogService,
lifecycleService: ILifecycleService
): Promise<void> {
const restorePromises: Promise<any>[] = [];
// Restore editors
@@ -514,52 +447,26 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
// Emit a warning after 10s if restore does not complete
const restoreTimeoutHandle = setTimeout(() => logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.'), 10000);
let error: Error;
return Promise.all(restorePromises)
.then(() => clearTimeout(restoreTimeoutHandle))
.catch(err => error = err)
.finally(() => this.instantiationService.invokeFunction(accessor => this.whenRestored(accessor, error)));
.catch(error => onUnexpectedError(error))
.finally(() => {
// Set lifecycle phase to `Restored`
lifecycleService.phase = LifecyclePhase.Restored;
// Set lifecycle phase to `Eventually` after a short delay and when idle (min 2.5sec, max 5sec)
setTimeout(() => {
this._register(runWhenIdle(() => {
lifecycleService.phase = LifecyclePhase.Eventually;
}, 2500));
}, 2500);
// Telemetry: startup metrics
mark('didStartWorkbench');
});
}
private whenRestored(accessor: ServicesAccessor, error?: Error): void {
const lifecycleService = accessor.get(ILifecycleService);
this.restored = true;
// Set lifecycle phase to `Restored`
lifecycleService.phase = LifecyclePhase.Restored;
// Set lifecycle phase to `Eventually` after a short delay and when
// idle (min 2.5sec, max 5sec)
setTimeout(() => {
this._register(runWhenIdle(() => {
lifecycleService.phase = LifecyclePhase.Eventually;
}, 2500));
}, 2500);
if (error) {
onUnexpectedError(error);
}
// Telemetry: startup metrics
mark('didStartWorkbench');
}
private saveState(e: IWillSaveStateEvent): void {
// Font info
saveFontInfo(this.storageService);
}
dispose(): void {
super.dispose();
this.disposed = true;
}
//#endregion
//#region ILayoutService
private readonly _onTitleBarVisibilityChange: Emitter<void> = this._register(new Emitter<void>());
@@ -576,8 +483,12 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
get container(): HTMLElement { return this.workbench; }
private parts: Map<string, Part> = new Map<string, Part>();
private workbenchGrid: Grid<View> | WorkbenchLegacyLayout;
private disposed: boolean;
private titleBarPartView: View;
private activityBarPartView: View;
private sideBarPartView: View;
@@ -585,11 +496,18 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
private editorPartView: View;
private statusBarPartView: View;
private environmentService: IEnvironmentService;
private configurationService: IConfigurationService;
private lifecycleService: ILifecycleService;
private storageService: IStorageService;
private windowService: IWindowService;
private editorService: IEditorService;
private editorGroupService: IEditorGroupsService;
private panelService: IPanelService;
private titleService: ITitleService;
private viewletService: IViewletService;
private contextService: IWorkspaceContextService;
private backupFileService: IBackupFileService;
private readonly state = {
fullscreen: false,
@@ -614,6 +532,7 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
hidden: false,
centered: false,
restoreCentered: false,
restoreEditors: false,
editorsToOpen: undefined as Promise<IResourceEditor[]> | IResourceEditor[]
},
@@ -640,41 +559,57 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
};
registerPart(part: Part): void {
this.parts.set(part.getId(), part);
private initLayout(accessor: ServicesAccessor) {
// Services
this.environmentService = accessor.get(IEnvironmentService);
this.configurationService = accessor.get(IConfigurationService);
this.lifecycleService = accessor.get(ILifecycleService);
this.windowService = accessor.get(IWindowService);
this.contextService = accessor.get(IWorkspaceContextService);
this.storageService = accessor.get(IStorageService);
// Parts
this.editorService = accessor.get(IEditorService);
this.editorGroupService = accessor.get(IEditorGroupsService);
this.panelService = accessor.get(IPanelService);
this.viewletService = accessor.get(IViewletService);
this.titleService = accessor.get(ITitleService);
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
accessor.get(IActivityBarService); // not used, but called to ensure instantiated
// Listeners
this.registerLayoutListeners();
// State
this.initLayoutState(accessor.get(ILifecycleService));
}
private registerLayoutListeners(accessor: ServicesAccessor): void {
const storageService = accessor.get(IStorageService);
const editorService = accessor.get(IEditorService);
const configurationService = accessor.get(IConfigurationService);
const editorGroupService = accessor.get(IEditorGroupsService);
const titleService = accessor.get(ITitleService);
const environmentService = accessor.get(IEnvironmentService);
private registerLayoutListeners(): void {
// Storage
this._register(storageService.onWillSaveState(e => this.saveLayoutState(e)));
this._register(this.storageService.onWillSaveState(e => this.saveLayoutState(e)));
// Restore editor if hidden and it changes
this._register(editorService.onDidVisibleEditorsChange(() => this.setEditorHidden(false)));
this._register(editorGroupService.onDidActivateGroup(() => this.setEditorHidden(false)));
this._register(this.editorService.onDidVisibleEditorsChange(() => this.setEditorHidden(false)));
this._register(this.editorGroupService.onDidActivateGroup(() => this.setEditorHidden(false)));
// Configuration changes
this._register(configurationService.onDidChangeConfiguration(() => this.doUpdateLayoutConfiguration()));
this._register(this.configurationService.onDidChangeConfiguration(() => this.doUpdateLayoutConfiguration()));
// Fullscreen changes
this._register(onDidChangeFullscreen(() => this.onFullscreenChanged()));
// Group changes
this._register(editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.state.editor.centered)));
this._register(editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.state.editor.centered)));
this._register(this.editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.state.editor.centered)));
this._register(this.editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.state.editor.centered)));
// Prevent workbench from scrolling #55456
this._register(addDisposableListener(this.workbench, EventType.SCROLL, () => this.workbench.scrollTop = 0));
// Menubar visibility changes
if ((isWindows || isLinux) && getTitleBarStyle(configurationService, environmentService) === 'custom') {
this._register(titleService.onMenubarVisibilityChange(visible => this.onMenubarToggled(visible)));
if ((isWindows || isLinux) && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') {
this._register(this.titleService.onMenubarVisibilityChange(visible => this.onMenubarToggled(visible)));
}
}
@@ -784,49 +719,32 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
}
private initLayoutState(accessor: ServicesAccessor): void {
const configurationService = accessor.get(IConfigurationService);
const storageService = accessor.get(IStorageService);
const lifecycleService = accessor.get(ILifecycleService);
const contextService = accessor.get(IWorkspaceContextService);
const environmentService = accessor.get(IEnvironmentService);
this.windowService = accessor.get(IWindowService);
// Ensure all part services are created (TODO@ben revisit this requirement)
this.editorService = accessor.get(IEditorService);
this.editorGroupService = accessor.get(IEditorGroupsService);
this.panelService = accessor.get(IPanelService);
this.viewletService = accessor.get(IViewletService);
accessor.get(IStatusbarService);
accessor.get(ITitleService);
accessor.get(IActivityBarService);
private initLayoutState(lifecycleService: ILifecycleService): void {
// Fullscreen
this.state.fullscreen = isFullscreen();
// Menubar visibility
this.state.menuBar.visibility = configurationService.getValue<MenuBarVisibility>(Settings.MENUBAR_VISIBLE);
this.state.menuBar.visibility = this.configurationService.getValue<MenuBarVisibility>(Settings.MENUBAR_VISIBLE);
// Activity bar visibility
this.state.activityBar.hidden = !configurationService.getValue<string>(Settings.ACTIVITYBAR_VISIBLE);
this.state.activityBar.hidden = !this.configurationService.getValue<string>(Settings.ACTIVITYBAR_VISIBLE);
// Sidebar visibility
this.state.sideBar.hidden = storageService.getBoolean(Storage.SIDEBAR_HIDDEN, StorageScope.WORKSPACE, contextService.getWorkbenchState() === WorkbenchState.EMPTY);
this.state.sideBar.hidden = this.storageService.getBoolean(Storage.SIDEBAR_HIDDEN, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY);
// Sidebar position
this.state.sideBar.position = (configurationService.getValue<string>(Settings.SIDEBAR_POSITION) === 'right') ? Position.RIGHT : Position.LEFT;
this.state.sideBar.position = (this.configurationService.getValue<string>(Settings.SIDEBAR_POSITION) === 'right') ? Position.RIGHT : Position.LEFT;
// Sidebar viewlet
if (!this.state.sideBar.hidden) {
const viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
// Only restore last viewlet if window was reloaded or we are in development mode
let viewletToRestore: string;
if (!environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow) {
viewletToRestore = storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, viewletRegistry.getDefaultViewletId());
if (!this.environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow) {
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewletService.getDefaultViewletId());
} else {
viewletToRestore = viewletRegistry.getDefaultViewletId();
viewletToRestore = this.viewletService.getDefaultViewletId();
}
if (viewletToRestore) {
@@ -837,13 +755,13 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
// Editor centered layout
this.state.editor.restoreCentered = storageService.getBoolean(Storage.CENTERED_LAYOUT_ENABLED, StorageScope.WORKSPACE, false);
this.state.editor.restoreCentered = this.storageService.getBoolean(Storage.CENTERED_LAYOUT_ENABLED, StorageScope.WORKSPACE, false);
// Editors to open
this.state.editor.editorsToOpen = this.resolveEditorsToOpen(accessor);
this.state.editor.editorsToOpen = this.resolveEditorsToOpen();
// Panel visibility
this.state.panel.hidden = storageService.getBoolean(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE, true);
this.state.panel.hidden = this.storageService.getBoolean(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE, true);
// Panel position
this.updatePanelPosition();
@@ -852,7 +770,7 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
if (!this.state.panel.hidden) {
const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
let panelToRestore = storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
let panelToRestore = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
if (!panelRegistry.hasPanel(panelToRestore)) {
panelToRestore = panelRegistry.getDefaultPanelId(); // fallback to default if panel is unknown
}
@@ -865,21 +783,21 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
// Statusbar visibility
this.state.statusBar.hidden = !configurationService.getValue<string>(Settings.STATUSBAR_VISIBLE);
this.state.statusBar.hidden = !this.configurationService.getValue<string>(Settings.STATUSBAR_VISIBLE);
// Zen mode enablement
this.state.zenMode.restore = storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && configurationService.getValue(Settings.ZEN_MODE_RESTORE);
this.state.zenMode.restore = this.storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && this.configurationService.getValue(Settings.ZEN_MODE_RESTORE);
}
private resolveEditorsToOpen(accessor: ServicesAccessor): Promise<IResourceEditor[]> | IResourceEditor[] {
const configuration = accessor.get(IWindowService).getConfiguration();
const configurationService = accessor.get(IConfigurationService);
const contextService = accessor.get(IWorkspaceContextService);
const editorGroupService = accessor.get(IEditorGroupsService);
const backupFileService = accessor.get(IBackupFileService);
private resolveEditorsToOpen(): Promise<IResourceEditor[]> | IResourceEditor[] {
const configuration = this.windowService.getConfiguration();
const hasInitialFilesToOpen = this.hasInitialFilesToOpen();
// Only restore editors if we are not instructed to open files initially
this.state.editor.restoreEditors = !hasInitialFilesToOpen;
// Files to open, diff or create
if (this.options.hasInitialFilesToOpen) {
if (hasInitialFilesToOpen) {
// Files to diff is exclusive
const filesToDiff = this.toInputs(configuration.filesToDiff, false);
@@ -900,13 +818,13 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
// Empty workbench
else if (contextService.getWorkbenchState() === WorkbenchState.EMPTY && configurationService.inspect('workbench.startupEditor').value === 'newUntitledFile') {
const isEmpty = editorGroupService.count === 1 && editorGroupService.activeGroup.count === 0;
else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.configurationService.inspect('workbench.startupEditor').value === 'newUntitledFile') {
const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
if (!isEmpty) {
return []; // do not open any empty untitled file if we restored editors from previous session
}
return backupFileService.hasBackups().then(hasBackups => {
return this.backupFileService.hasBackups().then(hasBackups => {
if (hasBackups) {
return []; // do not open any empty untitled file if we have backups to restore
}
@@ -918,6 +836,15 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
return [];
}
private hasInitialFilesToOpen(): boolean {
const configuration = this.windowService.getConfiguration();
return !!(
(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
(configuration.filesToDiff && configuration.filesToDiff.length > 0));
}
private toInputs(paths: IPath[] | undefined, isNew: boolean): Array<IResourceInput | IUntitledResourceInput> {
if (!paths || !paths.length) {
return [];
@@ -950,8 +877,12 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
this.state.panel.position = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
}
registerPart(part: Part): void {
this.parts.set(part.getId(), part);
}
isRestored(): boolean {
return this.restored;
return this.lifecycleService.phase >= LifecyclePhase.Restored;
}
hasFocus(part: Parts): boolean {
@@ -1145,7 +1076,7 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
}
private createWorkbenchLayout(): void {
private createWorkbenchLayout(instantiationService: IInstantiationService): void {
const titleBar = this.parts.get(Parts.TITLEBAR_PART);
const editorPart = this.parts.get(Parts.EDITOR_PART);
const activityBar = this.parts.get(Parts.ACTIVITYBAR_PART);
@@ -1167,7 +1098,7 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
this.workbench.prepend(this.workbenchGrid.element);
} else {
this.workbenchGrid = this.instantiationService.createInstance(
this.workbenchGrid = instantiationService.createInstance(
WorkbenchLegacyLayout,
this.parent,
this.workbench,
@@ -1590,5 +1521,11 @@ export class Workbench extends Disposable implements IWorkbenchLayoutService {
}
}
dispose(): void {
super.dispose();
this.disposed = true;
}
//#endregion
}
@@ -33,11 +33,11 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { URLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionIdentifier, IExtensionContributions, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
suite('ExtensionsActions Test', () => {
@@ -48,7 +48,7 @@ import { IExperimentService } from 'vs/workbench/contrib/experiments/node/experi
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
const mockExtensionGallery: IGalleryExtension[] = [
aGalleryExtension('MockExtension1', {
@@ -37,9 +37,9 @@ import { SinonStub } from 'sinon';
import { IExperimentService, ExperimentService, ExperimentState, ExperimentActionType } from 'vs/workbench/contrib/experiments/node/experimentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import { ExtensionIdentifier, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
suite('ExtensionsListView Tests', () => {
@@ -37,10 +37,10 @@ import { URLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
suite('ExtensionsWorkbenchServiceTest', () => {
+36 -88
View File
@@ -7,7 +7,7 @@ import * as fs from 'fs';
import * as gracefulFs from 'graceful-fs';
import { createHash } from 'crypto';
import { importEntries, mark } from 'vs/base/common/performance';
import { Workbench, IWorkbenchOptions } from 'vs/workbench/browser/workbench';
import { Workbench } from 'vs/workbench/browser/workbench';
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
import { setZoomLevel, setZoomFactor, setFullscreen } from 'vs/base/browser/browser';
import { domContentLoaded, addDisposableListener, EventType, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
@@ -20,27 +20,15 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { stat } from 'vs/base/node/pfs';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IWindowConfiguration, IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { IWindowConfiguration, IWindowService } from 'vs/platform/windows/common/windows';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { webFrame } from 'electron';
import { UpdateChannelClient } from 'vs/platform/update/node/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
import { URLHandlerChannel, URLServiceChannelClient } from 'vs/platform/url/node/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { WorkspacesChannelClient } from 'vs/platform/workspaces/node/workspacesIpc';
import { IWorkspacesService, ISingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, IMultiFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, IMultiFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log';
import { StorageService } from 'vs/platform/storage/node/storageService';
import { IssueChannelClient } from 'vs/platform/issue/node/issueIpc';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc';
import { RelayURLService } from 'vs/platform/url/common/urlService';
import { MenubarChannelClient } from 'vs/platform/menubar/node/menubarIpc';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { Schemas } from 'vs/base/common/network';
import { sanitizeFilePath } from 'vs/base/node/extfs';
import { basename } from 'vs/base/common/path';
@@ -48,9 +36,9 @@ import { GlobalStorageDatabaseChannelClient } from 'vs/platform/storage/node/sto
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { Disposable } from 'vs/base/common/lifecycle';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
class CodeRendererMain extends Disposable {
@@ -102,47 +90,31 @@ class CodeRendererMain extends Disposable {
});
}
private hasInitialFilesToOpen(): boolean {
return !!(
(this.configuration.filesToCreate && this.configuration.filesToCreate.length > 0) ||
(this.configuration.filesToOpen && this.configuration.filesToOpen.length > 0) ||
(this.configuration.filesToDiff && this.configuration.filesToDiff.length > 0));
}
open(): Promise<void> {
const electronMainClient = this._register(new ElectronIPCClient(`window:${this.configuration.windowId}`));
return this.initServices(electronMainClient).then(services => {
return this.initServices().then(services => {
return domContentLoaded().then(() => {
mark('willStartWorkbench');
const instantiationService = new InstantiationService(services, true);
// Create Workbench
this.workbench = instantiationService.createInstance(
Workbench,
document.body,
{ hasInitialFilesToOpen: this.hasInitialFilesToOpen() } as IWorkbenchOptions,
services
);
this.workbench = new Workbench(document.body, services.serviceCollection, services.logService);
// Layout
this._register(addDisposableListener(window, EventType.RESIZE, e => this.onWindowResize(e, true)));
// Workbench Lifecycle
this._register(this.workbench.onShutdown(() => this.dispose()));
this._register(this.workbench.onWillShutdown(event => event.join((services.get(IStorageService) as StorageService).close())));
this._register(this.workbench.onWillShutdown(event => event.join(services.storageService.close())));
// Startup
this.workbench.startup();
const instantiationService = this.workbench.startup();
// Window
this._register(instantiationService.createInstance(ElectronWindow));
// Driver
if (this.configuration.driver) {
registerWindowDriver(electronMainClient, this.configuration.windowId, instantiationService).then(disposable => this._register(disposable));
instantiationService.invokeFunction(accessor => registerWindowDriver(accessor).then(disposable => this._register(disposable)));
}
// Config Exporter
@@ -151,12 +123,12 @@ class CodeRendererMain extends Disposable {
}
// Logging
instantiationService.invokeFunction(accessor => accessor.get(ILogService).trace('workbench configuration', JSON.stringify(this.configuration)));
services.logService.trace('workbench configuration', JSON.stringify(this.configuration));
});
});
}
private onWindowResize(e: any, retry: boolean): void {
private onWindowResize(e: Event, retry: boolean): void {
if (e.target === window) {
if (window.document && window.document.body && window.document.body.clientWidth === 0) {
// TODO@Ben this is an electron issue on macOS when simple fullscreen is enabled
@@ -174,68 +146,44 @@ class CodeRendererMain extends Disposable {
}
}
private initServices(electronMainClient: ElectronIPCClient): Promise<ServiceCollection> {
private initServices(): Promise<{ serviceCollection: ServiceCollection, logService: ILogService, storageService: StorageService }> {
const serviceCollection = new ServiceCollection();
// Windows Service
const windowsChannel = electronMainClient.getChannel('windows');
serviceCollection.set(IWindowsService, new WindowsChannelClient(windowsChannel));
// Main Process
const mainProcessService = this._register(new MainProcessService(this.configuration.windowId));
serviceCollection.set(IMainProcessService, mainProcessService);
// Window
serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, [this.configuration]));
// Update Service
const updateChannel = electronMainClient.getChannel('update');
serviceCollection.set(IUpdateService, new SyncDescriptor(UpdateChannelClient, [updateChannel]));
// URL Service
const urlChannel = electronMainClient.getChannel('url');
const mainUrlService = new URLServiceChannelClient(urlChannel);
const urlService = new RelayURLService(mainUrlService);
serviceCollection.set(IURLService, urlService);
// URLHandler Service
const urlHandlerChannel = new URLHandlerChannel(urlService);
electronMainClient.registerChannel('urlHandler', urlHandlerChannel);
// Issue Service
const issueChannel = electronMainClient.getChannel('issue');
serviceCollection.set(IIssueService, new SyncDescriptor(IssueChannelClient, [issueChannel]));
// Menubar Service
const menubarChannel = electronMainClient.getChannel('menubar');
serviceCollection.set(IMenubarService, new SyncDescriptor(MenubarChannelClient, [menubarChannel]));
// Workspaces Service
const workspacesChannel = electronMainClient.getChannel('workspaces');
serviceCollection.set(IWorkspacesService, new WorkspacesChannelClient(workspacesChannel));
// Environment
const environmentService = new EnvironmentService(this.configuration, this.configuration.execPath);
serviceCollection.set(IEnvironmentService, environmentService);
// Log
const logService = this._register(this.createLogService(electronMainClient, environmentService));
const logService = this._register(this.createLogService(mainProcessService, environmentService));
serviceCollection.set(ILogService, logService);
// Resolve a workspace payload that we can get the workspace ID from
return this.resolveWorkspaceInitializationPayload(environmentService).then(payload => {
return this.resolveWorkspaceInitializationPayload(environmentService).then(payload => Promise.all([
this.createWorkspaceService(payload, environmentService, logService).then(service => {
return Promise.all([
// Workspace
serviceCollection.set(IWorkspaceContextService, service);
// Create and initialize workspace/configuration service
this.createWorkspaceService(payload, environmentService, logService),
// Configuration
serviceCollection.set(IConfigurationService, service);
// Create and initialize storage service
this.createStorageService(payload, environmentService, logService, electronMainClient)
]).then(services => {
serviceCollection.set(IWorkspaceContextService, services[0]);
serviceCollection.set(IConfigurationService, services[0]);
serviceCollection.set(IStorageService, services[1]);
return service;
}),
return serviceCollection;
});
});
this.createStorageService(payload, environmentService, logService, mainProcessService).then(service => {
// Storage
serviceCollection.set(IStorageService, service);
return service;
})
]).then(services => ({ serviceCollection, logService, storageService: services[1] })));
}
private resolveWorkspaceInitializationPayload(environmentService: EnvironmentService): Promise<IWorkspaceInitializationPayload> {
@@ -319,8 +267,8 @@ class CodeRendererMain extends Disposable {
});
}
private createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IEnvironmentService, logService: ILogService, electronMainClient: ElectronIPCClient): Promise<StorageService> {
const globalStorageDatabase = new GlobalStorageDatabaseChannelClient(electronMainClient.getChannel('storage'));
private createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IEnvironmentService, logService: ILogService, mainProcessService: IMainProcessService): Promise<StorageService> {
const globalStorageDatabase = new GlobalStorageDatabaseChannelClient(mainProcessService.getChannel('storage'));
const storageService = new StorageService(globalStorageDatabase, logService, environmentService);
return storageService.initialize(payload).then(() => storageService, error => {
@@ -331,11 +279,11 @@ class CodeRendererMain extends Disposable {
});
}
private createLogService(electronMainClient: ElectronIPCClient, environmentService: IEnvironmentService): ILogService {
private createLogService(mainProcessService: IMainProcessService, environmentService: IEnvironmentService): ILogService {
const spdlogService = createSpdLogService(`renderer${this.configuration.windowId}`, this.configuration.logLevel, environmentService.logsPath);
const consoleLogService = new ConsoleLogService(this.configuration.logLevel);
const logService = new MultiplexLogService([consoleLogService, spdlogService]);
const logLevelClient = new LogLevelSetterChannelClient(electronMainClient.getChannel('loglevel'));
const logLevelClient = new LogLevelSetterChannelClient(mainProcessService.getChannel('loglevel'));
return new FollowerLogService(logLevelClient, logService);
}
+11 -15
View File
@@ -22,7 +22,7 @@ import * as browser from 'vs/base/browser/browser';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { ipcRenderer as ipc, webFrame, crashReporter } from 'electron';
import { ipcRenderer as ipc, webFrame, crashReporter, Event } from 'electron';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -57,8 +57,6 @@ const TextInputActions: IAction[] = [
export class ElectronWindow extends Disposable {
private static readonly closeWhenEmptyConfigurationKey = 'window.closeWhenEmpty';
private touchBarMenu?: IMenu;
private touchBarUpdater: RunOnceScheduler;
private touchBarDisposables: IDisposable[];
@@ -116,7 +114,7 @@ export class ElectronWindow extends Disposable {
});
// Support runAction event
ipc.on('vscode:runAction', (event: any, request: IRunActionInWindowRequest) => {
ipc.on('vscode:runAction', (event: Event, request: IRunActionInWindowRequest) => {
const args: any[] = request.args || [];
// If we run an action from the touchbar, we fill in the currently active resource
@@ -147,29 +145,27 @@ export class ElectronWindow extends Disposable {
});
// Support runKeybinding event
ipc.on('vscode:runKeybinding', (event: any, request: IRunKeybindingInWindowRequest) => {
ipc.on('vscode:runKeybinding', (event: Event, request: IRunKeybindingInWindowRequest) => {
if (document.activeElement) {
this.keybindingService.dispatchByUserSettingsLabel(request.userSettingsLabel, document.activeElement);
}
});
// Error reporting from main
ipc.on('vscode:reportError', (event: any, error: string) => {
ipc.on('vscode:reportError', (event: Event, error: string) => {
if (error) {
const errorParsed = JSON.parse(error);
errorParsed.mainProcess = true;
errors.onUnexpectedError(errorParsed);
errors.onUnexpectedError(JSON.parse(error));
}
});
// Support openFiles event for existing and new files
ipc.on('vscode:openFiles', (event: any, request: IOpenFileRequest) => this.onOpenFiles(request));
ipc.on('vscode:openFiles', (event: Event, request: IOpenFileRequest) => this.onOpenFiles(request));
// Support addFolders event if we have a workspace opened
ipc.on('vscode:addFolders', (event: any, request: IAddFoldersRequest) => this.onAddFoldersRequest(request));
ipc.on('vscode:addFolders', (event: Event, request: IAddFoldersRequest) => this.onAddFoldersRequest(request));
// Message support
ipc.on('vscode:showInfoMessage', (event: any, message: string) => {
ipc.on('vscode:showInfoMessage', (event: Event, message: string) => {
this.notificationService.info(message);
});
@@ -211,7 +207,7 @@ export class ElectronWindow extends Disposable {
});
// keyboard layout changed event
ipc.on('vscode:accessibilitySupportChanged', (event: any, accessibilitySupportEnabled: boolean) => {
ipc.on('vscode:accessibilitySupportChanged', (event: Event, accessibilitySupportEnabled: boolean) => {
this.accessibilityService.setAccessibilitySupport(accessibilitySupportEnabled ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled);
});
@@ -247,7 +243,7 @@ export class ElectronWindow extends Disposable {
// or setting is disabled. Also enabled when running with --wait from the command line.
const visibleEditors = this.editorService.visibleControls;
if (visibleEditors.length === 0 && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && !this.environmentService.isExtensionDevelopment) {
const closeWhenEmpty = this.configurationService.getValue<boolean>(ElectronWindow.closeWhenEmptyConfigurationKey);
const closeWhenEmpty = this.configurationService.getValue<boolean>('window.closeWhenEmpty');
if (closeWhenEmpty || this.environmentService.args.wait) {
this.closeEmptyWindowScheduler.schedule();
}
@@ -316,7 +312,7 @@ export class ElectronWindow extends Disposable {
// Handle window.open() calls
const $this = this;
(<any>window).open = function (url: string, target: string, features: string, replace: boolean): any {
window.open = function (url: string, target: string, features: string, replace: boolean): Window | null {
$this.windowsService.openExternal(url);
return null;
@@ -25,6 +25,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { ContextMenuService as HTMLContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export class ContextMenuService extends Disposable implements IContextMenuService {
@@ -41,13 +42,14 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
@IConfigurationService configurationService: IConfigurationService,
@IEnvironmentService environmentService: IEnvironmentService,
@IContextViewService contextViewService: IContextViewService,
@IThemeService themeService: IThemeService
@IThemeService themeService: IThemeService,
@ILayoutService layoutService: ILayoutService
) {
super();
// Custom context menu: Linux/Windows if custom title is enabled
if (!isMacintosh && getTitleBarStyle(configurationService, environmentService) === 'custom') {
this.impl = new HTMLContextMenuService(null, telemetryService, notificationService, contextViewService, keybindingService, themeService);
this.impl = new HTMLContextMenuService(layoutService, telemetryService, notificationService, contextViewService, keybindingService, themeService);
}
// Native context menu: otherwise
@@ -23,7 +23,7 @@ import { WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc';
interface IMassagedMessageBoxOptions {
@@ -11,7 +11,7 @@ import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagemen
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
const localExtensionManagementServerAuthority: string = 'vscode-local';
@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { computeSHA1Hash } from 'vs/base/common/hash';
export const IHashService = createDecorator<IHashService>('hashService');
@@ -14,4 +16,15 @@ export interface IHashService {
* Produce a SHA1 hash of the provided content.
*/
createSHA1(content: string): string;
}
}
export class HashService implements IHashService {
_serviceBrand: any;
createSHA1(content: string): string {
return computeSHA1Hash(content);
}
}
registerSingleton(IHashService, HashService, true);
@@ -81,7 +81,7 @@ import { Part } from 'vs/workbench/browser/part';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IPanel } from 'vs/workbench/common/panel';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { ISharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, undefined);
+26 -8
View File
@@ -22,7 +22,7 @@ import 'vs/workbench/electron-browser/main';
import 'vs/workbench/browser/actions/layoutActions';
import 'vs/workbench/browser/actions/listCommands';
import 'vs/workbench/browser/actions/navigationActions';
import 'vs/workbench/browser/parts/quickopen/quickopenActions';
import 'vs/workbench/browser/parts/quickopen/quickOpenActions';
import 'vs/workbench/browser/parts/quickinput/quickInputActions';
//#endregion
@@ -72,12 +72,26 @@ import { RequestService } from 'vs/platform/request/electron-browser/requestServ
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsChannelClient } from 'vs/platform/localizations/node/localizationsIpc';
import { ISharedProcessService, SharedProcessService } from 'vs/platform/sharedProcess/node/sharedProcessService';
import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService';
import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService } from 'vs/platform/telemetry/node/telemetryService';
import { TelemetryService } from 'vs/platform/telemetry/electron-browser/telemetryService';
import { IProductService } from 'vs/platform/product/common/product';
import { ProductService } from 'vs/platform/product/node/productService';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService';
import { IUpdateService } from 'vs/platform/update/common/update';
import { UpdateService } from 'vs/platform/update/electron-browser/updateService';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { IssueService } from 'vs/platform/issue/electron-browser/issueService';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesService } from 'vs/platform/workspaces/electron-browser/workspacesService';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-browser/menubarService';
import { IURLService } from 'vs/platform/url/common/url';
import { RelayURLService } from 'vs/platform/url/electron-browser/urlService';
import 'vs/workbench/services/bulkEdit/browser/bulkEditService';
import 'vs/workbench/services/integrity/node/integrityService';
@@ -114,7 +128,7 @@ import 'vs/workbench/services/extensions/electron-browser/extensionService';
import 'vs/workbench/services/contextmenu/electron-browser/contextmenuService';
import 'vs/workbench/services/extensionManagement/node/multiExtensionManagement';
import 'vs/workbench/services/label/common/labelService';
import 'vs/workbench/services/extensions/node/extensionManagementServerService';
import 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import 'vs/workbench/services/notification/common/notificationService';
@@ -135,11 +149,17 @@ registerSingleton(IContextViewService, ContextViewService, true);
registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
registerSingleton(IRequestService, RequestService, true);
registerSingleton(ILifecycleService, LifecycleService);
registerSingleton(ILocalizationsService, LocalizationsChannelClient);
registerSingleton(ILocalizationsService, LocalizationsService);
registerSingleton(ISharedProcessService, SharedProcessService, true);
registerSingleton(IRemoteAuthorityResolverService, RemoteAuthorityResolverService, true);
registerSingleton(ITelemetryService, TelemetryService);
registerSingleton(IProductService, ProductService, true);
registerSingleton(IWindowsService, WindowsService);
registerSingleton(IUpdateService, UpdateService);
registerSingleton(IIssueService, IssueService);
registerSingleton(IWorkspacesService, WorkspacesService);
registerSingleton(IMenubarService, MenubarService);
registerSingleton(IURLService, RelayURLService);
//#endregion
@@ -296,7 +316,5 @@ import 'vs/workbench/contrib/codeinset/electron-browser/codeInset.contribution';
// Issues
import 'vs/workbench/contrib/issue/electron-browser/issue.contribution';
import { IProductService } from 'vs/platform/product/common/product';
import { ProductService } from 'vs/platform/product/node/productService';
//#endregion
@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT */
div.monaco.main.css {
}
@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT
define([], {});
+325
View File
@@ -0,0 +1,325 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//#region --- workbench/editor core
import 'vs/editor/editor.all';
// import 'vs/workbench/api/electron-browser/extensionHost.contribution';
// import 'vs/workbench/electron-browser/main.contribution';
import 'vs/workbench/browser/workbench.contribution';
import 'vs/workbench/browser/nodeless.main';
//#endregion
//#region --- workbench actions
import 'vs/workbench/browser/actions/layoutActions';
import 'vs/workbench/browser/actions/listCommands';
import 'vs/workbench/browser/actions/navigationActions';
import 'vs/workbench/browser/parts/quickopen/quickOpenActions';
import 'vs/workbench/browser/parts/quickinput/quickInputActions';
//#endregion
//#region --- API Extension Points
import 'vs/workbench/api/common/menusExtensionPoint';
import 'vs/workbench/api/common/configurationExtensionPoint';
import 'vs/workbench/api/browser/viewsExtensionPoint';
//#endregion
//#region --- workbench services
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IMenuService } from 'vs/platform/actions/common/actions';
import { MenuService } from 'vs/platform/actions/common/menuService';
import { IListService, ListService } from 'vs/platform/list/browser/listService';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { MarkerService } from 'vs/platform/markers/common/markerService';
// import { IDownloadService } from 'vs/platform/download/common/download';
// import { DownloadService } from 'vs/platform/download/node/downloadService';
// import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { BrowserAccessibilityService } from 'vs/platform/accessibility/common/accessibilityService';
import { IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
// import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
// import { IRequestService } from 'vs/platform/request/node/request';
// import { RequestService } from 'vs/platform/request/electron-browser/requestService';
// import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
// import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
// import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
// import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService';
// import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
// import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService';
// import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
// import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
// import { TelemetryService } from 'vs/platform/telemetry/electron-browser/telemetryService';
// import { IProductService } from 'vs/platform/product/common/product';
// import { ProductService } from 'vs/platform/product/node/productService';
// import { IWindowsService } from 'vs/platform/windows/common/windows';
// import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService';
// import { IUpdateService } from 'vs/platform/update/common/update';
// import { UpdateService } from 'vs/platform/update/electron-browser/updateService';
// import { IIssueService } from 'vs/platform/issue/common/issue';
// import { IssueService } from 'vs/platform/issue/electron-browser/issueService';
// import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
// import { WorkspacesService } from 'vs/platform/workspaces/electron-browser/workspacesService';
// import { IMenubarService } from 'vs/platform/menubar/common/menubar';
// import { MenubarService } from 'vs/platform/menubar/electron-browser/menubarService';
// import { IURLService } from 'vs/platform/url/common/url';
// import { RelayURLService } from 'vs/platform/url/electron-browser/urlService';
import 'vs/workbench/browser/nodeless.simpleservices';
import 'vs/workbench/services/bulkEdit/browser/bulkEditService';
// import 'vs/workbench/services/integrity/node/integrityService';
import 'vs/workbench/services/keybinding/common/keybindingEditing';
import 'vs/workbench/services/hash/common/hashService';
// import 'vs/workbench/services/textMate/electron-browser/textMateService';
import 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
// import 'vs/workbench/services/workspace/node/workspaceEditingService';
// import 'vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler';
import 'vs/workbench/services/decorations/browser/decorationsService';
// import 'vs/workbench/services/search/node/searchService';
import 'vs/workbench/services/progress/browser/progressService2';
import 'vs/workbench/services/editor/browser/codeEditorService';
// import 'vs/workbench/services/broadcast/electron-browser/broadcastService';
import 'vs/workbench/services/preferences/browser/preferencesService';
// import 'vs/workbench/services/output/node/outputChannelModelService';
// import 'vs/workbench/services/configuration/node/jsonEditingService';
import 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import 'vs/workbench/services/textfile/common/textFileService';
// import 'vs/workbench/services/dialogs/electron-browser/dialogService';
// import 'vs/workbench/services/backup/node/backupFileService';
import 'vs/workbench/services/editor/browser/editorService';
import 'vs/workbench/services/history/browser/history';
// import 'vs/workbench/services/files/node/remoteFileService';
import 'vs/workbench/services/activity/browser/activityService';
import 'vs/workbench/browser/parts/views/views';
// import 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import 'vs/workbench/services/untitled/common/untitledEditorService';
// import 'vs/workbench/services/textfile/node/textResourcePropertiesService';
import 'vs/workbench/services/mode/common/workbenchModeService';
import 'vs/workbench/services/commands/common/commandService';
import 'vs/workbench/services/themes/browser/workbenchThemeService';
// import 'vs/workbench/services/extensions/electron-browser/extensionService';
// import 'vs/workbench/services/contextmenu/electron-browser/contextmenuService';
// import 'vs/workbench/services/extensionManagement/node/multiExtensionManagement';
import 'vs/workbench/services/label/common/labelService';
// import 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
// import 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import 'vs/workbench/services/notification/common/notificationService';
registerSingleton(IMenuService, MenuService, true);
registerSingleton(IListService, ListService, true);
registerSingleton(IOpenerService, OpenerService, true);
registerSingleton(IEditorWorkerService, EditorWorkerServiceImpl);
registerSingleton(IMarkerDecorationsService, MarkerDecorationsService);
registerSingleton(IMarkerService, MarkerService, true);
// registerSingleton(IDownloadService, DownloadService, true);
// registerSingleton(IClipboardService, ClipboardService, true);
registerSingleton(IContextKeyService, ContextKeyService);
registerSingleton(IModelService, ModelServiceImpl, true);
registerSingleton(ITextResourceConfigurationService, TextResourceConfigurationService);
registerSingleton(IAccessibilityService, BrowserAccessibilityService, true);
registerSingleton(IExtensionEnablementService, ExtensionEnablementService, true);
registerSingleton(IContextViewService, ContextViewService, true);
// registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
// registerSingleton(IRequestService, RequestService, true);
// registerSingleton(ILifecycleService, LifecycleService);
// registerSingleton(ILocalizationsService, LocalizationsService);
// registerSingleton(ISharedProcessService, SharedProcessService, true);
// registerSingleton(IRemoteAuthorityResolverService, RemoteAuthorityResolverService, true);
// registerSingleton(ITelemetryService, TelemetryService);
// registerSingleton(IProductService, ProductService, true);
// registerSingleton(IWindowsService, WindowsService);
// registerSingleton(IUpdateService, UpdateService);
// registerSingleton(IIssueService, IssueService);
// registerSingleton(IWorkspacesService, WorkspacesService);
// registerSingleton(IMenubarService, MenubarService);
// registerSingleton(IURLService, RelayURLService);
registerSingleton(IContextMenuService, ContextMenuService);
//#endregion
//#region --- workbench parts
import 'vs/workbench/browser/parts/quickinput/quickInput';
import 'vs/workbench/browser/parts/quickopen/quickOpenController';
import 'vs/workbench/browser/parts/titlebar/titlebarPart';
import 'vs/workbench/browser/parts/editor/editorPart';
import 'vs/workbench/browser/parts/activitybar/activitybarPart';
import 'vs/workbench/browser/parts/panel/panelPart';
import 'vs/workbench/browser/parts/sidebar/sidebarPart';
import 'vs/workbench/browser/parts/statusbar/statusbarPart';
//#endregion
//#region --- workbench contributions
// Telemetry
import 'vs/workbench/contrib/telemetry/browser/telemetry.contribution';
// Localizations
// import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
// Preferences
// import 'vs/workbench/contrib/preferences/electron-browser/preferences.contribution';
import 'vs/workbench/contrib/preferences/browser/keybindingsEditorContribution';
// Logs
import 'vs/workbench/contrib/logs/common/logs.contribution';
// Quick Open Handlers
import 'vs/workbench/contrib/quickopen/browser/quickopen.contribution';
// Explorer
import 'vs/workbench/contrib/files/browser/explorerViewlet';
import 'vs/workbench/contrib/files/browser/fileActions.contribution';
import 'vs/workbench/contrib/files/browser/files.contribution';
// Backup
import 'vs/workbench/contrib/backup/common/backup.contribution';
// Stats
// import 'vs/workbench/contrib/stats/node/stats.contribution';
// Rapid Render Splash
// import 'vs/workbench/contrib/splash/electron-browser/partsSplash.contribution';
// Search
import 'vs/workbench/contrib/search/browser/search.contribution';
import 'vs/workbench/contrib/search/browser/searchView';
import 'vs/workbench/contrib/search/browser/openAnythingHandler';
// SCM
import 'vs/workbench/contrib/scm/browser/scm.contribution';
import 'vs/workbench/contrib/scm/browser/scmViewlet';
// Debug
// import 'vs/workbench/contrib/debug/electron-browser/debug.contribution';
// import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
// import 'vs/workbench/contrib/debug/electron-browser/repl';
// import 'vs/workbench/contrib/debug/browser/debugViewlet';
// Markers
import 'vs/workbench/contrib/markers/browser/markers.contribution';
// Comments
// import 'vs/workbench/contrib/comments/electron-browser/comments.contribution';
// URL Support
import 'vs/workbench/contrib/url/common/url.contribution';
// Webview
// import 'vs/workbench/contrib/webview/electron-browser/webview.contribution';
// Extensions Management
// import 'vs/workbench/contrib/extensions/electron-browser/extensions.contribution';
// import 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen';
// import 'vs/workbench/contrib/extensions/electron-browser/extensionsViewlet';
// Output Panel
import 'vs/workbench/contrib/output/browser/output.contribution';
import 'vs/workbench/contrib/output/browser/outputPanel';
// Terminal
// import 'vs/workbench/contrib/terminal/browser/terminal.contribution';
// import 'vs/workbench/contrib/terminal/electron-browser/terminal.contribution';
// import 'vs/workbench/contrib/terminal/browser/terminalQuickOpen';
// import 'vs/workbench/contrib/terminal/browser/terminalPanel';
// Relauncher
// import 'vs/workbench/contrib/relauncher/electron-browser/relauncher.contribution';
// Tasks
// import 'vs/workbench/contrib/tasks/electron-browser/task.contribution';
// Emmet
import 'vs/workbench/contrib/emmet/browser/emmet.contribution';
// CodeEditor Contributions
import 'vs/workbench/contrib/codeEditor/browser/codeEditor.contribution';
// import 'vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution';
// Execution
// import 'vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution';
// Snippets
import 'vs/workbench/contrib/snippets/browser/snippets.contribution';
import 'vs/workbench/contrib/snippets/browser/snippetsService';
import 'vs/workbench/contrib/snippets/browser/insertSnippet';
import 'vs/workbench/contrib/snippets/browser/configureSnippets';
import 'vs/workbench/contrib/snippets/browser/tabCompletion';
// Formatter Help
import 'vs/workbench/contrib/format/browser/format.contribution';
// Send a Smile
// import 'vs/workbench/contrib/feedback/electron-browser/feedback.contribution';
// Update
// import 'vs/workbench/contrib/update/electron-browser/update.contribution';
// Surveys
// import 'vs/workbench/contrib/surveys/electron-browser/nps.contribution';
// import 'vs/workbench/contrib/surveys/electron-browser/languageSurveys.contribution';
// Performance
// import 'vs/workbench/contrib/performance/electron-browser/performance.contribution';
// CLI
// import 'vs/workbench/contrib/cli/node/cli.contribution';
// Themes Support
import 'vs/workbench/contrib/themes/browser/themes.contribution';
// import 'vs/workbench/contrib/themes/test/electron-browser/themes.test.contribution';
// Watermark
import 'vs/workbench/contrib/watermark/browser/watermark';
// Welcome
import 'vs/workbench/contrib/welcome/walkThrough/browser/walkThrough.contribution';
// import 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution';
import 'vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay';
import 'vs/workbench/contrib/welcome/page/browser/welcomePage.contribution';
// Outline
import 'vs/workbench/contrib/outline/browser/outline.contribution';
// Experiments
// import 'vs/workbench/contrib/experiments/electron-browser/experiments.contribution';
// Code Insets
// import 'vs/workbench/contrib/codeinset/electron-browser/codeInset.contribution';
// Issues
// import 'vs/workbench/contrib/issue/electron-browser/issue.contribution';
//#endregion