提交 69563902 编写于 作者: A Alex Dima

Add webSocketFactory option

上级 d827a3a6
......@@ -326,6 +326,20 @@ export namespace Event {
return result.event;
}
export interface DOMEventEmitter {
addEventListener(event: string | symbol, listener: Function): void;
removeEventListener(event: string | symbol, listener: Function): void;
}
export function fromDOMEventEmitter<T>(emitter: DOMEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {
const fn = (...args: any[]) => result.fire(map(...args));
const onFirstListenerAdd = () => emitter.addEventListener(eventName, fn);
const onLastListenerRemove = () => emitter.removeEventListener(eventName, fn);
const result = new Emitter<T>({ onFirstListenerAdd, onLastListenerRemove });
return result.event;
}
export function fromPromise<T = any>(promise: Promise<T>): Event<undefined> {
const emitter = new Emitter<undefined>();
let shouldEmit = false;
......
......@@ -77,7 +77,7 @@ import { HistoryMainService } from 'vs/platform/history/electron-main/historyMai
import { URLService } from 'vs/platform/url/common/urlService';
import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory';
import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
import { VSBuffer } from 'vs/base/common/buffer';
import { statSync } from 'fs';
import { ISignService } from 'vs/platform/sign/common/sign';
......@@ -708,7 +708,7 @@ export class CodeApplication extends Disposable {
const options: IConnectionOptions = {
isBuilt,
commit: product.commit,
webSocketFactory: nodeWebSocketFactory,
socketFactory: nodeSocketFactory,
addressProvider: {
getAddress: () => {
return Promise.resolve({ host, port });
......
......@@ -3,63 +3,111 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWebSocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
import { ISocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
import { VSBuffer } from 'vs/base/common/buffer';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Event, Emitter } from 'vs/base/common/event';
class BrowserSocket implements ISocket {
public readonly socket: WebSocket;
export interface IWebSocketFactory {
create(url: string): IWebSocket;
}
constructor(socket: WebSocket) {
this.socket = socket;
}
export interface IWebSocket {
readonly onData: Event<ArrayBuffer>;
readonly onOpen: Event<void>;
readonly onClose: Event<void>;
readonly onError: Event<any>;
public dispose(): void {
this.socket.close();
}
send(data: ArrayBuffer | ArrayBufferView): void;
close(): void;
}
class BrowserWebSocket implements IWebSocket {
private readonly _onData = new Emitter<ArrayBuffer>();
public readonly onData = this._onData.event;
public readonly onOpen: Event<void>;
public readonly onClose: Event<void>;
public readonly onError: Event<any>;
private readonly _socket: WebSocket;
private readonly _fileReader: FileReader;
private readonly _queue: Blob[];
private _isReading: boolean;
public onData(_listener: (e: VSBuffer) => void): IDisposable {
const fileReader = new FileReader();
const queue: Blob[] = [];
let isReading = false;
fileReader.onload = function (event) {
isReading = false;
private readonly _socketMessageListener: (ev: MessageEvent) => void;
constructor(socket: WebSocket) {
this._socket = socket;
this._fileReader = new FileReader();
this._queue = [];
this._isReading = false;
this._fileReader.onload = (event) => {
this._isReading = false;
const buff = <ArrayBuffer>(<any>event.target).result;
try {
_listener(VSBuffer.wrap(new Uint8Array(buff)));
} catch (err) {
onUnexpectedError(err);
}
this._onData.fire(buff);
if (queue.length > 0) {
enqueue(queue.shift()!);
if (this._queue.length > 0) {
enqueue(this._queue.shift()!);
}
};
const enqueue = (blob: Blob) => {
if (isReading) {
queue.push(blob);
if (this._isReading) {
this._queue.push(blob);
return;
}
isReading = true;
fileReader.readAsArrayBuffer(blob);
};
const listener = (e: MessageEvent) => {
enqueue(<Blob>e.data);
this._isReading = true;
this._fileReader.readAsArrayBuffer(blob);
};
this.socket.addEventListener('message', listener);
return {
dispose: () => this.socket.removeEventListener('message', listener)
this._socketMessageListener = (ev: MessageEvent) => {
enqueue(<Blob>ev.data);
};
this._socket.addEventListener('message', this._socketMessageListener);
this.onOpen = Event.fromDOMEventEmitter(this._socket, 'open');
this.onClose = Event.fromDOMEventEmitter(this._socket, 'close');
this.onError = Event.fromDOMEventEmitter(this._socket, 'error');
}
send(data: ArrayBuffer | ArrayBufferView): void {
this._socket.send(data);
}
close(): void {
this._socket.close();
this._socket.removeEventListener('message', this._socketMessageListener);
}
}
export const defaultWebSocketFactory = new class implements IWebSocketFactory {
create(url: string): IWebSocket {
return new BrowserWebSocket(new WebSocket(url));
}
};
class BrowserSocket implements ISocket {
public readonly socket: IWebSocket;
constructor(socket: IWebSocket) {
this.socket = socket;
}
public dispose(): void {
this.socket.close();
}
public onData(listener: (e: VSBuffer) => void): IDisposable {
return this.socket.onData((data) => listener(VSBuffer.wrap(new Uint8Array(data))));
}
public onClose(listener: () => void): IDisposable {
this.socket.addEventListener('close', listener);
return {
dispose: () => this.socket.removeEventListener('close', listener)
};
return this.socket.onClose(listener);
}
public onEnd(listener: () => void): IDisposable {
......@@ -76,14 +124,23 @@ class BrowserSocket implements ISocket {
}
export const browserWebSocketFactory = new class implements IWebSocketFactory {
export class BrowserSocketFactory implements ISocketFactory {
private readonly _webSocketFactory: IWebSocketFactory;
constructor(webSocketFactory: IWebSocketFactory | null | undefined) {
this._webSocketFactory = webSocketFactory || defaultWebSocketFactory;
}
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
const errorListener = (err: any) => callback(err, undefined);
const socket = new WebSocket(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`);
socket.onopen = function (event) {
socket.removeEventListener('error', errorListener);
const socket = this._webSocketFactory.create(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`);
const errorListener = socket.onError((err) => callback(err, undefined));
socket.onOpen(() => {
errorListener.dispose();
callback(undefined, new BrowserSocket(socket));
};
socket.addEventListener('error', errorListener);
});
}
};
}
......@@ -57,7 +57,7 @@ interface ISimpleConnectionOptions {
port: number;
reconnectionToken: string;
reconnectionProtocol: PersistentProtocol | null;
webSocketFactory: IWebSocketFactory;
socketFactory: ISocketFactory;
signService: ISignService;
}
......@@ -65,13 +65,13 @@ export interface IConnectCallback {
(err: any | undefined, socket: ISocket | undefined): void;
}
export interface IWebSocketFactory {
export interface ISocketFactory {
connect(host: string, port: number, query: string, callback: IConnectCallback): void;
}
async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<PersistentProtocol> {
const protocol = await new Promise<PersistentProtocol>((c, e) => {
options.webSocketFactory.connect(
options.socketFactory.connect(
options.host,
options.port,
`reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`,
......@@ -202,7 +202,7 @@ async function doConnectRemoteAgentTunnel(options: ISimpleConnectionOptions, sta
export interface IConnectionOptions {
isBuilt: boolean;
commit: string | undefined;
webSocketFactory: IWebSocketFactory;
socketFactory: ISocketFactory;
addressProvider: IAddressProvider;
signService: ISignService;
}
......@@ -216,7 +216,7 @@ async function resolveConnectionOptions(options: IConnectionOptions, reconnectio
port: port,
reconnectionToken: reconnectionToken,
reconnectionProtocol: reconnectionProtocol,
webSocketFactory: options.webSocketFactory,
socketFactory: options.socketFactory,
signService: options.signService
};
}
......
......@@ -5,9 +5,9 @@
import * as net from 'net';
import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
import { IWebSocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
import { ISocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
export const nodeWebSocketFactory = new class implements IWebSocketFactory {
export const nodeSocketFactory = new class implements ISocketFactory {
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
const errorListener = (err: any) => callback(err, undefined);
......
......@@ -135,7 +135,7 @@ class CodeRendererMain extends Disposable {
serviceCollection.set(ISignService, signService);
// Remote Agent
const remoteAgentService = this._register(new RemoteAgentService(environmentService, productService, remoteAuthorityResolverService, signService));
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService));
serviceCollection.set(IRemoteAgentService, remoteAgentService);
// Files
......
......@@ -14,7 +14,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IFileService } from 'vs/platform/files/common/files';
import { IProductService } from 'vs/platform/product/common/product';
import { AbstractExtensionService } from 'vs/workbench/services/extensions/common/abstractExtensionService';
import { browserWebSocketFactory } from 'vs/platform/remote/browser/browserWebSocketFactory';
import { ExtensionHostProcessManager } from 'vs/workbench/services/extensions/common/extensionHostProcessManager';
import { RemoteExtensionHostClient, IInitDataProvider } from 'vs/workbench/services/extensions/common/remoteExtensionHostClient';
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
......@@ -63,7 +62,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
const result: ExtensionHostProcessManager[] = [];
const remoteAgentConnection = this._remoteAgentService.getConnection()!;
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, this.getExtensions(), this._createProvider(remoteAgentConnection.remoteAuthority), browserWebSocketFactory);
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, this.getExtensions(), this._createProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory);
const remoteExtHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, remoteExtHostProcessWorker, remoteAgentConnection.remoteAuthority, initialActivationEvents);
result.push(remoteExtHostProcessManager);
......
......@@ -8,7 +8,7 @@ import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ILabelService } from 'vs/platform/label/common/label';
import { ILogService } from 'vs/platform/log/common/log';
import { connectRemoteAgentExtensionHost, IRemoteExtensionHostStartParams, IConnectionOptions, IWebSocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
import { connectRemoteAgentExtensionHost, IRemoteExtensionHostStartParams, IConnectionOptions, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
......@@ -47,7 +47,7 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
constructor(
private readonly _allExtensions: Promise<IExtensionDescription[]>,
private readonly _initDataProvider: IInitDataProvider,
private readonly _webSocketFactory: IWebSocketFactory,
private readonly _socketFactory: ISocketFactory,
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
......@@ -73,7 +73,7 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
const options: IConnectionOptions = {
isBuilt: this._environmentService.isBuilt,
commit: this._productService.commit,
webSocketFactory: this._webSocketFactory,
socketFactory: this._socketFactory,
addressProvider: {
getAddress: async () => {
const { authority } = await this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority);
......
......@@ -7,7 +7,6 @@ import { ipcRenderer as ipc } from 'electron';
import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost';
import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electron-browser/cachedExtensionScanner';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory';
import { AbstractExtensionService } from 'vs/workbench/services/extensions/common/abstractExtensionService';
import * as nls from 'vs/nls';
import * as path from 'vs/base/common/path';
......@@ -356,7 +355,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
const remoteAgentConnection = this._remoteAgentService.getConnection();
if (remoteAgentConnection) {
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, this.getExtensions(), this._createProvider(remoteAgentConnection.remoteAuthority), nodeWebSocketFactory);
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, this.getExtensions(), this._createProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory);
const remoteExtHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, remoteExtHostProcessWorker, remoteAgentConnection.remoteAuthority, initialActivationEvents);
result.push(remoteExtHostProcessManager);
}
......
......@@ -4,18 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IRemoteAgentConnection } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
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 { IWebSocketFactory, BrowserSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
import { ISignService } from 'vs/platform/sign/common/sign';
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
export class RemoteAgentService extends AbstractRemoteAgentService {
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
public readonly socketFactory: ISocketFactory;
private readonly _connection: IRemoteAgentConnection | null = null;
constructor(
webSocketFactory: IWebSocketFactory | null | undefined,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IProductService productService: IProductService,
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
......@@ -23,7 +27,8 @@ export class RemoteAgentService extends AbstractRemoteAgentService {
) {
super(environmentService);
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, browserWebSocketFactory, environmentService, remoteAuthorityResolverService, signService));
this.socketFactory = new BrowserSocketFactory(webSocketFactory);
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, environmentService, remoteAuthorityResolverService, signService));
}
getConnection(): IRemoteAgentConnection | null {
......
......@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { Client } from 'vs/base/parts/ipc/common/ipc.net';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { connectRemoteAgentManagement, IConnectionOptions, IWebSocketFactory, PersistenConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection';
import { connectRemoteAgentManagement, IConnectionOptions, ISocketFactory, PersistenConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection';
import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
......@@ -21,7 +21,7 @@ import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics
import { Emitter } from 'vs/base/common/event';
import { ISignService } from 'vs/platform/sign/common/sign';
export abstract class AbstractRemoteAgentService extends Disposable implements IRemoteAgentService {
export abstract class AbstractRemoteAgentService extends Disposable {
_serviceBrand: any;
......@@ -83,7 +83,7 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
constructor(
remoteAuthority: string,
private readonly _commit: string | undefined,
private readonly _webSocketFactory: IWebSocketFactory,
private readonly _socketFactory: ISocketFactory,
private readonly _environmentService: IEnvironmentService,
private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
private readonly _signService: ISignService
......@@ -113,7 +113,7 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
const options: IConnectionOptions = {
isBuilt: this._environmentService.isBuilt,
commit: this._commit,
webSocketFactory: this._webSocketFactory,
socketFactory: this._socketFactory,
addressProvider: {
getAddress: async () => {
if (firstCall) {
......
......@@ -8,7 +8,7 @@ import { RemoteAgentConnectionContext, IRemoteAgentEnvironment } from 'vs/platfo
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnosticsService';
import { Event } from 'vs/base/common/event';
import { PersistenConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection';
import { PersistenConnectionEvent as PersistentConnectionEvent, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
export const RemoteExtensionLogFileName = 'remoteagent';
......@@ -17,6 +17,8 @@ export const IRemoteAgentService = createDecorator<IRemoteAgentService>('remoteA
export interface IRemoteAgentService {
_serviceBrand: any;
readonly socketFactory: ISocketFactory;
getConnection(): IRemoteAgentConnection | null;
getEnvironment(bail?: boolean): Promise<IRemoteAgentEnvironment | null>;
getDiagnosticInfo(options: IDiagnosticInfoOptions): Promise<IDiagnosticInfo | undefined>;
......@@ -27,7 +29,7 @@ export interface IRemoteAgentConnection {
readonly remoteAuthority: string;
readonly onReconnecting: Event<void>;
readonly onDidStateChange: Event<PersistenConnectionEvent>;
readonly onDidStateChange: Event<PersistentConnectionEvent>;
getChannel<T extends IChannel>(channelName: string): T;
registerChannel<T extends IServerChannel<RemoteAgentConnectionContext>>(channelName: string, channel: T): void;
......
......@@ -5,14 +5,17 @@
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IRemoteAgentConnection } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import product from 'vs/platform/product/node/product';
import { nodeWebSocketFactory } from 'vs/platform/remote/node/nodeWebSocketFactory';
import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
import { AbstractRemoteAgentService, RemoteAgentConnection } from 'vs/workbench/services/remote/common/abstractRemoteAgentService';
import { ISignService } from 'vs/platform/sign/common/sign';
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
export class RemoteAgentService extends AbstractRemoteAgentService {
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
public readonly socketFactory: ISocketFactory;
private readonly _connection: IRemoteAgentConnection | null = null;
......@@ -22,8 +25,9 @@ export class RemoteAgentService extends AbstractRemoteAgentService {
@ISignService signService: ISignService
) {
super(environmentService);
this.socketFactory = nodeSocketFactory;
if (remoteAuthority) {
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeWebSocketFactory, environmentService, remoteAuthorityResolverService, signService));
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, environmentService, remoteAuthorityResolverService, signService));
}
}
......
......@@ -12,7 +12,7 @@ import product from 'vs/platform/product/node/product';
import { connectRemoteAgentTunnel, IConnectionOptions } from 'vs/platform/remote/common/remoteAgentConnection';
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 { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
import { ISignService } from 'vs/platform/sign/common/sign';
export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<RemoteTunnel> {
......@@ -102,7 +102,7 @@ export class TunnelService implements ITunnelService {
const options: IConnectionOptions = {
isBuilt: this.environmentService.isBuilt,
commit: product.commit,
webSocketFactory: nodeWebSocketFactory,
socketFactory: nodeSocketFactory,
addressProvider: {
getAddress: async () => {
const { authority } = await this.remoteAuthorityResolverService.resolveAuthority(remoteAuthority);
......
......@@ -8,6 +8,7 @@ import { main } from 'vs/workbench/browser/web.main';
import { UriComponents } from 'vs/base/common/uri';
import { IFileSystemProvider } from 'vs/platform/files/common/files';
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
import { IWebSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
export interface IWorkbenchConstructionOptions {
......@@ -44,6 +45,11 @@ export interface IWorkbenchConstructionOptions {
* In case not provided, workbench uses <code>XMLHttpRequest</code>.
*/
requestHandler?: (requestOptions: IRequestOptions) => Promise<IRequestContext>;
/**
* A factory for web sockets.
*/
webSocketFactory?: IWebSocketFactory;
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册