From 77de8faba574274cf0b91a4b050c5861499025b2 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 10 Jun 2019 15:31:55 +0200 Subject: [PATCH 1/3] ISignService --- src/vs/code/electron-main/app.ts | 11 +++++---- src/vs/code/electron-main/main.ts | 3 +++ .../remote/common/remoteAgentConnection.ts | 23 +++++------------- src/vs/platform/sign/browser/signService.ts | 14 +++++++++++ src/vs/platform/sign/common/sign.ts | 15 ++++++++++++ src/vs/platform/sign/node/signService.ts | 24 +++++++++++++++++++ src/vs/workbench/browser/web.main.ts | 8 ++++++- .../debug/electron-browser/debugSession.ts | 6 +++-- .../debug/electron-browser/rawDebugSession.ts | 14 +++++------ .../test/electron-browser/debugModel.test.ts | 4 ++-- src/vs/workbench/electron-browser/main.ts | 8 ++++++- .../configurationService.test.ts | 3 ++- .../common/remoteExtensionHostClient.ts | 7 ++++-- .../remote/browser/remoteAgentServiceImpl.ts | 6 +++-- .../common/abstractRemoteAgentService.ts | 7 ++++-- .../remoteAgentServiceImpl.ts | 6 +++-- .../services/remote/node/tunnelService.ts | 5 +++- 17 files changed, 120 insertions(+), 44 deletions(-) create mode 100644 src/vs/platform/sign/browser/signService.ts create mode 100644 src/vs/platform/sign/common/sign.ts create mode 100644 src/vs/platform/sign/node/signService.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 06d7085d6d77b..23da157c70f91 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -80,6 +80,7 @@ import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAg import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory'; import { VSBuffer } from 'vs/base/common/buffer'; import { statSync } from 'fs'; +import { ISignService } from 'vs/platform/sign/common/sign'; export class CodeApplication extends Disposable { @@ -95,7 +96,8 @@ export class CodeApplication extends Disposable { @IEnvironmentService private readonly environmentService: IEnvironmentService, @ILifecycleService private readonly lifecycleService: ILifecycleService, @IConfigurationService private readonly configurationService: IConfigurationService, - @IStateService private readonly stateService: IStateService + @IStateService private readonly stateService: IStateService, + @ISignService private readonly signService: ISignService ) { super(); @@ -646,7 +648,7 @@ export class CodeApplication extends Disposable { private readonly _connection: Promise; private readonly _disposeRunner: RunOnceScheduler; - constructor(authority: string, host: string, port: number) { + constructor(authority: string, host: string, port: number, signService: ISignService) { this._authority = authority; const options: IConnectionOptions = { @@ -657,7 +659,8 @@ export class CodeApplication extends Disposable { getAddress: () => { return Promise.resolve({ host, port }); } - } + }, + signService: signService }; this._connection = connectRemoteAgentManagement(options, authority, `main`); @@ -726,7 +729,7 @@ export class CodeApplication extends Disposable { return; } - activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port); + activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port, this.signService); connectionPool.set(uri.authority, activeConnection); } diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 25385702555cf..012815714c8b9 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -40,6 +40,8 @@ import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; import { IThemeMainService, ThemeMainService } from 'vs/platform/theme/electron-main/themeMainService'; import { Client } from 'vs/base/parts/ipc/common/ipc.net'; import { once } from 'vs/base/common/functional'; +import { ISignService } from 'vs/platform/sign/common/sign'; +import { SignService } from 'vs/platform/sign/node/signService'; class ExpectedError extends Error { readonly isExpected = true; @@ -147,6 +149,7 @@ class CodeMain { services.set(IRequestService, new SyncDescriptor(RequestService)); services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService)); services.set(IThemeMainService, new SyncDescriptor(ThemeMainService)); + services.set(ISignService, new SyncDescriptor(SignService)); return [new InstantiationService(services, true), instanceEnvironment]; } diff --git a/src/vs/platform/remote/common/remoteAgentConnection.ts b/src/vs/platform/remote/common/remoteAgentConnection.ts index 34108aab23fe1..b57337d99d974 100644 --- a/src/vs/platform/remote/common/remoteAgentConnection.ts +++ b/src/vs/platform/remote/common/remoteAgentConnection.ts @@ -8,10 +8,10 @@ import { generateUuid } from 'vs/base/common/uuid'; import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { Disposable } from 'vs/base/common/lifecycle'; import { VSBuffer } from 'vs/base/common/buffer'; -import * as platform from 'vs/base/common/platform'; import { Emitter } from 'vs/base/common/event'; import { RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { isPromiseCanceledError } from 'vs/base/common/errors'; +import { ISignService } from 'vs/platform/sign/common/sign'; export const enum ConnectionType { Management = 1, @@ -58,6 +58,7 @@ interface ISimpleConnectionOptions { reconnectionToken: string; reconnectionProtocol: PersistentProtocol | null; webSocketFactory: IWebSocketFactory; + signService: ISignService; } export interface IConnectCallback { @@ -92,7 +93,7 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio return new Promise((c, e) => { - const messageRegistration = protocol.onControlMessage(raw => { + const messageRegistration = protocol.onControlMessage(async raw => { const msg = JSON.parse(raw.toString()); // Stop listening for further events messageRegistration.dispose(); @@ -104,21 +105,7 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio if (msg.type === 'sign') { - let signed = msg.data; - if (platform.isNative) { - try { - const vsda = require.__$__nodeRequire('vsda'); - const signer = new vsda.signer(); - if (signer) { - signed = signer.sign(msg.data); - } - } catch (e) { - console.error('signer.sign: ' + e); - } - } else { - signed = (self).CONNECTION_AUTH_TOKEN; - } - + const signed = await options.signService.sign(msg.data); const connTypeRequest: ConnectionTypeRequest = { type: 'connectionType', commit: options.commit, @@ -216,6 +203,7 @@ export interface IConnectionOptions { commit: string | undefined; webSocketFactory: IWebSocketFactory; addressProvider: IAddressProvider; + signService: ISignService; } async function resolveConnectionOptions(options: IConnectionOptions, reconnectionToken: string, reconnectionProtocol: PersistentProtocol | null): Promise { @@ -228,6 +216,7 @@ async function resolveConnectionOptions(options: IConnectionOptions, reconnectio reconnectionToken: reconnectionToken, reconnectionProtocol: reconnectionProtocol, webSocketFactory: options.webSocketFactory, + signService: options.signService }; } diff --git a/src/vs/platform/sign/browser/signService.ts b/src/vs/platform/sign/browser/signService.ts new file mode 100644 index 0000000000000..20ee67f6064d6 --- /dev/null +++ b/src/vs/platform/sign/browser/signService.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ISignService } from 'vs/platform/sign/common/sign'; + +export class SignService implements ISignService { + _serviceBrand: any; + + async sign(value: string): Promise { + return Promise.resolve((self).CONNECTION_AUTH_TOKEN); + } +} \ No newline at end of file diff --git a/src/vs/platform/sign/common/sign.ts b/src/vs/platform/sign/common/sign.ts new file mode 100644 index 0000000000000..026c8580d73e5 --- /dev/null +++ b/src/vs/platform/sign/common/sign.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const SIGN_SERVICE_ID = 'signService'; +export const ISignService = createDecorator(SIGN_SERVICE_ID); + +export interface ISignService { + _serviceBrand: any; + + sign(value: string): Promise; +} diff --git a/src/vs/platform/sign/node/signService.ts b/src/vs/platform/sign/node/signService.ts new file mode 100644 index 0000000000000..515cc869e815d --- /dev/null +++ b/src/vs/platform/sign/node/signService.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ISignService } from 'vs/platform/sign/common/sign'; + +export class SignService implements ISignService { + _serviceBrand: any; + + async sign(value: string): Promise { + try { + const vsda = await import('vsda'); + const signer = new vsda.signer(); + if (signer) { + return signer.sign(value); + } + } catch (e) { + console.error('signer.sign: ' + e); + } + + return value; + } +} \ No newline at end of file diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 5cc0b5ed05b4f..7ffa1bf351502 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -30,6 +30,8 @@ import { WorkspaceService } from 'vs/workbench/services/configuration/browser/co import { ConfigurationCache } from 'vs/workbench/services/configuration/browser/configurationCache'; import { ConfigurationFileService } from 'vs/workbench/services/configuration/common/configuration'; import { WebResources } from 'vs/workbench/browser/web.resources'; +import { ISignService } from 'vs/platform/sign/common/sign'; +import { SignService } from 'vs/platform/sign/browser/signService'; interface IWindowConfiguration { settingsUri: URI; @@ -96,7 +98,11 @@ class CodeRendererMain extends Disposable { const remoteAuthorityResolverService = new RemoteAuthorityResolverService(); serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService); - const remoteAgentService = this._register(new RemoteAgentService(environmentService, productService, remoteAuthorityResolverService)); + // Sign + const signService = new SignService(); + serviceCollection.set(ISignService, signService); + + const remoteAgentService = this._register(new RemoteAgentService(environmentService, productService, remoteAuthorityResolverService, signService)); serviceCollection.set(IRemoteAgentService, remoteAgentService); // Files diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts index 9cb99a3bf8187..0704d389289fb 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts @@ -32,6 +32,7 @@ import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ISignService } from 'vs/platform/sign/common/sign'; export class DebugSession implements IDebugSession { @@ -66,7 +67,8 @@ export class DebugSession implements IDebugSession { @IViewletService private readonly viewletService: IViewletService, @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, @IEnvironmentService private readonly environmentService: IEnvironmentService, - @INotificationService private readonly notificationService: INotificationService + @INotificationService private readonly notificationService: INotificationService, + @ISignService private readonly signService: ISignService ) { this.id = generateUuid(); this.repl = new ReplModel(this); @@ -167,7 +169,7 @@ export class DebugSession implements IDebugSession { return dbgr.createDebugAdapter(this).then(debugAdapter => { - this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.environmentService); + this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.environmentService, this.signService); return this.raw!.start().then(() => { diff --git a/src/vs/workbench/contrib/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/electron-browser/rawDebugSession.ts index 2d0c3f784c199..7640fb949460c 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/rawDebugSession.ts @@ -14,6 +14,7 @@ import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger } from 'vs/workbench import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; import * as cp from 'child_process'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ISignService } from 'vs/platform/sign/common/sign'; /** * This interface represents a single command line argument split into a "prefix" and a "path" half. @@ -69,9 +70,10 @@ export class RawDebugSession { constructor( debugAdapter: IDebugAdapter, dbgr: IDebugger, - private telemetryService: ITelemetryService, - public customTelemetryService: ITelemetryService | undefined, - private environmentService: IEnvironmentService + private readonly telemetryService: ITelemetryService, + public readonly customTelemetryService: ITelemetryService | undefined, + private readonly environmentService: IEnvironmentService, + private readonly signService: ISignService ) { this.debugAdapter = debugAdapter; this._capabilities = Object.create(null); @@ -528,11 +530,9 @@ export class RawDebugSession { break; case 'handshake': try { - const vsda = await import('vsda'); - const obj = new vsda.signer(); - const sig = obj.sign(request.arguments.value); + const signature = await this.signService.sign(request.arguments.value); response.body = { - signature: sig + signature: signature }; safeSendResponse(response); } catch (e) { diff --git a/src/vs/workbench/contrib/debug/test/electron-browser/debugModel.test.ts b/src/vs/workbench/contrib/debug/test/electron-browser/debugModel.test.ts index d27a7998cb2be..0a31e7a0b92ff 100644 --- a/src/vs/workbench/contrib/debug/test/electron-browser/debugModel.test.ts +++ b/src/vs/workbench/contrib/debug/test/electron-browser/debugModel.test.ts @@ -15,7 +15,7 @@ import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel'; import { IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug'; function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession { - return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); + return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); } suite('Debug - Model', () => { @@ -437,7 +437,7 @@ suite('Debug - Model', () => { // Repl output test('repl output', () => { - const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); + const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); const repl = new ReplModel(session); repl.appendToRepl('first line\n', severity.Error); repl.appendToRepl('second line ', severity.Error); diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 572226a4f7c34..39a00efc7eb5a 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -49,6 +49,8 @@ import { DefaultConfigurationExportHelper } from 'vs/workbench/services/configur import { ConfigurationCache } from 'vs/workbench/services/configuration/node/configurationCache'; import { ConfigurationFileService } from 'vs/workbench/services/configuration/node/configurationFileService'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { SignService } from 'vs/platform/sign/node/signService'; +import { ISignService } from 'vs/platform/sign/common/sign'; class CodeRendererMain extends Disposable { @@ -183,7 +185,11 @@ class CodeRendererMain extends Disposable { const remoteAuthorityResolverService = new RemoteAuthorityResolverService(); serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService); - const remoteAgentService = this._register(new RemoteAgentService(this.configuration, environmentService, remoteAuthorityResolverService)); + // Sign + const signService = new SignService(); + serviceCollection.set(ISignService, signService); + + const remoteAgentService = this._register(new RemoteAgentService(this.configuration, environmentService, remoteAuthorityResolverService, signService)); serviceCollection.set(IRemoteAgentService, remoteAgentService); // Files diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 77a390dd0b9a1..3fd5bf00d75a8 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -45,6 +45,7 @@ import { ConfigurationFileService } from 'vs/workbench/services/configuration/no import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { IConfigurationCache } from 'vs/workbench/services/configuration/common/configuration'; import { VSBuffer } from 'vs/base/common/buffer'; +import { SignService } from 'vs/platform/sign/browser/signService'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -103,7 +104,7 @@ suite('WorkspaceContextService - Folder', () => { workspaceResource = folderDir; const globalSettingsFile = path.join(parentDir, 'settings.json'); const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); - workspaceContextService = new WorkspaceService({ userSettingsResource: environmentService.settingsResource, configurationCache: new ConfigurationCache(environmentService) }, new ConfigurationFileService(), new RemoteAgentService({}, environmentService, new RemoteAuthorityResolverService())); + workspaceContextService = new WorkspaceService({ userSettingsResource: environmentService.settingsResource, configurationCache: new ConfigurationCache(environmentService) }, new ConfigurationFileService(), new RemoteAgentService({}, environmentService, new RemoteAuthorityResolverService(), new SignService())); return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); }); }); diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts index d848799f87306..75ca5ef552aa6 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts @@ -26,6 +26,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import { VSBuffer } from 'vs/base/common/buffer'; import { IExtensionHostDebugService } from 'vs/workbench/services/extensions/common/extensionHostDebug'; import { IProductService } from 'vs/platform/product/common/product'; +import { ISignService } from 'vs/platform/sign/common/sign'; export interface IInitDataProvider { readonly remoteAuthority: string; @@ -55,7 +56,8 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH @ILabelService private readonly _labelService: ILabelService, @IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, @IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService, - @IProductService private readonly _productService: IProductService + @IProductService private readonly _productService: IProductService, + @ISignService private readonly _signService: ISignService ) { super(); this._protocol = null; @@ -77,7 +79,8 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH const { host, port } = await this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority); return { host, port }; } - } + }, + signService: this._signService }; return this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority).then((resolvedAuthority) => { diff --git a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts index c1cd786ebb11e..3f2d25705ad10 100644 --- a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts @@ -9,6 +9,7 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot import { AbstractRemoteAgentService, RemoteAgentConnection } from 'vs/workbench/services/remote/common/abstractRemoteAgentService'; import { IProductService } from 'vs/platform/product/common/product'; import { browserWebSocketFactory } from 'vs/platform/remote/browser/browserWebSocketFactory'; +import { ISignService } from 'vs/platform/sign/common/sign'; export class RemoteAgentService extends AbstractRemoteAgentService { @@ -17,11 +18,12 @@ export class RemoteAgentService extends AbstractRemoteAgentService { constructor( @IEnvironmentService environmentService: IEnvironmentService, @IProductService productService: IProductService, - @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService + @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService, + @ISignService signService: ISignService ) { super(environmentService); const authority = document.location.host; - this._connection = this._register(new RemoteAgentConnection(authority, productService.commit, browserWebSocketFactory, environmentService, remoteAuthorityResolverService)); + this._connection = this._register(new RemoteAgentConnection(authority, productService.commit, browserWebSocketFactory, environmentService, remoteAuthorityResolverService, signService)); } getConnection(): IRemoteAgentConnection | null { diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index 79b10c15b6594..c5ece27cfb25f 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -19,6 +19,7 @@ import { RemoteExtensionEnvironmentChannelClient } from 'vs/workbench/services/r import { INotificationService } from 'vs/platform/notification/common/notification'; import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnosticsService'; import { Emitter } from 'vs/base/common/event'; +import { ISignService } from 'vs/platform/sign/common/sign'; export abstract class AbstractRemoteAgentService extends Disposable implements IRemoteAgentService { @@ -84,7 +85,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon private readonly _commit: string | undefined, private readonly _webSocketFactory: IWebSocketFactory, private readonly _environmentService: IEnvironmentService, - private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService + private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, + private readonly _signService: ISignService ) { super(); this.remoteAuthority = remoteAuthority; @@ -122,7 +124,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon const { host, port } = await this._remoteAuthorityResolverService.resolveAuthority(this.remoteAuthority); return { host, port }; } - } + }, + signService: this._signService }; const connection = this._register(await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`)); this._register(connection.onDidStateChange(e => this._onDidStateChange.fire(e))); diff --git a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts index 4415f1cf11892..d101f0c57dc51 100644 --- a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts @@ -10,6 +10,7 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot import product from 'vs/platform/product/node/product'; import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory'; import { AbstractRemoteAgentService, RemoteAgentConnection } from 'vs/workbench/services/remote/common/abstractRemoteAgentService'; +import { ISignService } from 'vs/platform/sign/common/sign'; export class RemoteAgentService extends AbstractRemoteAgentService { @@ -17,11 +18,12 @@ export class RemoteAgentService extends AbstractRemoteAgentService { constructor({ remoteAuthority }: IWindowConfiguration, @IEnvironmentService environmentService: IEnvironmentService, - @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService + @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService, + @ISignService signService: ISignService ) { super(environmentService); if (remoteAuthority) { - this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeWebSocketFactory, environmentService, remoteAuthorityResolverService)); + this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeWebSocketFactory, environmentService, remoteAuthorityResolverService, signService)); } } diff --git a/src/vs/workbench/services/remote/node/tunnelService.ts b/src/vs/workbench/services/remote/node/tunnelService.ts index a3d5311a7ea81..b8e30ea867bc7 100644 --- a/src/vs/workbench/services/remote/node/tunnelService.ts +++ b/src/vs/workbench/services/remote/node/tunnelService.ts @@ -13,6 +13,7 @@ import { connectRemoteAgentTunnel, IConnectionOptions } from 'vs/platform/remote import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory'; +import { ISignService } from 'vs/platform/sign/common/sign'; export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise { const tunnel = new NodeRemoteTunnel(options, tunnelRemotePort); @@ -88,6 +89,7 @@ export class TunnelService implements ITunnelService { public constructor( @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, + @ISignService private readonly signService: ISignService ) { } @@ -106,7 +108,8 @@ export class TunnelService implements ITunnelService { const { host, port } = await this.remoteAuthorityResolverService.resolveAuthority(remoteAuthority); return { host, port }; } - } + }, + signService: this.signService }; return createRemoteTunnel(options, remotePort); } From 8a26027b11ece0eb7d173c6a95eb266986d5a4d5 Mon Sep 17 00:00:00 2001 From: Isidor Nikolic Date: Tue, 11 Jun 2019 10:03:34 +0200 Subject: [PATCH 2/3] Polish as suggested by Ben Co-Authored-By: Benjamin Pasero --- src/vs/code/electron-main/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 23da157c70f91..bf75167101e20 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -660,7 +660,7 @@ export class CodeApplication extends Disposable { return Promise.resolve({ host, port }); } }, - signService: signService + signService }; this._connection = connectRemoteAgentManagement(options, authority, `main`); From 74d99f6b144df29984b1c5f80450e75229e752b6 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 11 Jun 2019 12:56:33 +0200 Subject: [PATCH 3/3] Cache the 'vsda' import, because when the same missing module is imported multiple times, The ones after the first will not throw an error. And this will break the contract of the sign method --- src/vs/platform/sign/node/signService.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/sign/node/signService.ts b/src/vs/platform/sign/node/signService.ts index 515cc869e815d..b33e5e25be170 100644 --- a/src/vs/platform/sign/node/signService.ts +++ b/src/vs/platform/sign/node/signService.ts @@ -4,13 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { ISignService } from 'vs/platform/sign/common/sign'; +import { memoize } from 'vs/base/common/decorators'; export class SignService implements ISignService { _serviceBrand: any; + // Cache the 'vsda' import, because when the same missing module is imported multiple times, + // the ones after the first will not throw an error. And this will break the contract of the sign method. + @memoize + private vsda(): Promise { + return import('vsda'); + } + async sign(value: string): Promise { try { - const vsda = await import('vsda'); + const vsda = await this.vsda(); const signer = new vsda.signer(); if (signer) { return signer.sign(value);