提交 76c330c3 编写于 作者: B Benjamin Pasero

electron 5 - bootstrap a nodeless configuration (#68302)

上级 65ede5e2
......@@ -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",
......
......@@ -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;
}
}
\ No newline at end of file
}
//#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
\ No newline at end of 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');
});
});
\ No newline at end of file
......@@ -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);
......
<!-- 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>
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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);
});
});
})();
\ No newline at end of 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));
......
/*---------------------------------------------------------------------------------------------
* 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;
}
}
\ No newline at end of file
......@@ -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 {
......
......@@ -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');
......
......@@ -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 {
......
/*---------------------------------------------------------------------------------------------
* 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);
}
}
\ No newline at end of file
......@@ -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 {
......
/*---------------------------------------------------------------------------------------------
* 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);
}
}
\ No newline at end of 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);
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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();
}
}
\ No newline at end of file
......@@ -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();
}
}
/*---------------------------------------------------------------------------------------------
* 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);
}
}
\ No newline at end of file
......@@ -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);
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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]);
}
}
......@@ -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]);
}
}
}
\ No newline at end of file
......@@ -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';
......
/*---------------------------------------------------------------------------------------------
* 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');
}
}
......@@ -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');
}
}
}
\ No newline at end of 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);
}
}
/*---------------------------------------------------------------------------------------------
* 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);
}
}
/*---------------------------------------------------------------------------------------------
* 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]));
}
}
\ No newline at end of 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]));
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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);
}
}
/*---------------------------------------------------------------------------------------------
* 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();
}
此差异已折叠。
......@@ -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(() => {
......
......@@ -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', () => {
......
......@@ -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);
}
......
......@@ -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
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册