@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
253 lines (249 loc) • 13.7 kB
JavaScript
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
import { ExtHostContext, CandidatePortSource, MainContext } from '@codingame/monaco-vscode-api/vscode/vs/workbench/api/common/extHost.protocol';
import { TunnelDtoConverter } from '@codingame/monaco-vscode-api/vscode/vs/workbench/api/common/extHostTunnelService';
import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
import { PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_OUTPUT, PortsEnablement, PORT_AUTO_SOURCE_SETTING_HYBRID } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteExplorerService';
import { IRemoteExplorerService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteExplorerService.service';
import { TunnelProtocol } from '@codingame/monaco-vscode-api/vscode/vs/platform/tunnel/common/tunnel';
import { ITunnelService } from '@codingame/monaco-vscode-api/vscode/vs/platform/tunnel/common/tunnel.service';
import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
import '@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification';
import { INotificationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification.service';
import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
import { IRemoteAgentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteAgentService.service';
import { Registry } from '@codingame/monaco-vscode-api/vscode/vs/platform/registry/common/platform';
import { Extensions } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configurationRegistry';
import { IContextKeyService } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey.service';
import { TunnelSource, TunnelCloseReason, makeAddress, forwardedPortsFeaturesEnabled } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/tunnelModel';
import Severity from '@codingame/monaco-vscode-api/vscode/vs/base/common/severity';
let MainThreadTunnelService = class MainThreadTunnelService extends Disposable {
constructor(
extHostContext,
remoteExplorerService,
tunnelService,
notificationService,
configurationService,
logService,
remoteAgentService,
contextKeyService
) {
super();
this.remoteExplorerService = remoteExplorerService;
this.tunnelService = tunnelService;
this.notificationService = notificationService;
this.configurationService = configurationService;
this.logService = logService;
this.remoteAgentService = remoteAgentService;
this.contextKeyService = contextKeyService;
this.elevateionRetry = false;
this.portsAttributesProviders = ( new Map());
this._alreadyRegistered = false;
this._proxy = ( extHostContext.getProxy(ExtHostContext.ExtHostTunnelService));
this._register(tunnelService.onTunnelOpened(() => this._proxy.$onDidTunnelsChange()));
this._register(tunnelService.onTunnelClosed(() => this._proxy.$onDidTunnelsChange()));
}
processFindingEnabled() {
return (!!this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING) || this.tunnelService.hasTunnelProvider) && (this.configurationService.getValue(PORT_AUTO_SOURCE_SETTING) !== PORT_AUTO_SOURCE_SETTING_OUTPUT);
}
async $setRemoteTunnelService(processId) {
this.remoteExplorerService.namedProcesses.set(processId, "Code Extension Host");
if (this.remoteExplorerService.portsFeaturesEnabled === PortsEnablement.AdditionalFeatures) {
this._proxy.$registerCandidateFinder(this.processFindingEnabled());
} else {
this._register(
this.remoteExplorerService.onEnabledPortsFeatures(() => this._proxy.$registerCandidateFinder(this.processFindingEnabled()))
);
}
this._register(this.configurationService.onDidChangeConfiguration(async e => {
if ((this.remoteExplorerService.portsFeaturesEnabled === PortsEnablement.AdditionalFeatures) && (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING) || e.affectsConfiguration(PORT_AUTO_SOURCE_SETTING))) {
return this._proxy.$registerCandidateFinder(this.processFindingEnabled());
}
}));
this._register(this.tunnelService.onAddedTunnelProvider(async () => {
if (this.remoteExplorerService.portsFeaturesEnabled === PortsEnablement.AdditionalFeatures) {
return this._proxy.$registerCandidateFinder(this.processFindingEnabled());
}
}));
}
async $registerPortsAttributesProvider(selector, providerHandle) {
this.portsAttributesProviders.set(providerHandle, selector);
if (!this._alreadyRegistered) {
this.remoteExplorerService.tunnelModel.addAttributesProvider(this);
this._alreadyRegistered = true;
}
}
async $unregisterPortsAttributesProvider(providerHandle) {
this.portsAttributesProviders.delete(providerHandle);
}
async providePortAttributes(ports, pid, commandLine, token) {
if (this.portsAttributesProviders.size === 0) {
return [];
}
const appropriateHandles = ( Array.from(this.portsAttributesProviders.entries()).filter(entry => {
const selector = entry[1];
const portRange = (typeof selector.portRange === "number") ? [selector.portRange, selector.portRange + 1] : selector.portRange;
const portInRange = portRange ? ( ports.some(port => portRange[0] <= port && port < portRange[1])) : true;
const commandMatches = !selector.commandPattern || (commandLine && (commandLine.match(selector.commandPattern)));
return portInRange && commandMatches;
}).map(entry => entry[0]));
if (appropriateHandles.length === 0) {
return [];
}
return this._proxy.$providePortAttributes(appropriateHandles, ports, pid, commandLine, token);
}
async $openTunnel(tunnelOptions, source) {
const tunnel = await this.remoteExplorerService.forward({
remote: tunnelOptions.remoteAddress,
local: tunnelOptions.localAddressPort,
name: tunnelOptions.label,
source: {
source: TunnelSource.Extension,
description: source
},
elevateIfNeeded: false
});
if (!tunnel || (typeof tunnel === "string")) {
return undefined;
}
if (!this.elevateionRetry && (tunnelOptions.localAddressPort !== undefined) && (tunnel.tunnelLocalPort !== undefined) && this.tunnelService.isPortPrivileged(tunnelOptions.localAddressPort) && (tunnel.tunnelLocalPort !== tunnelOptions.localAddressPort) && this.tunnelService.canElevate) {
this.elevationPrompt(tunnelOptions, tunnel, source);
}
return TunnelDtoConverter.fromServiceTunnel(tunnel);
}
async elevationPrompt(tunnelOptions, tunnel, source) {
return this.notificationService.prompt(Severity.Info, ( localize(
2644,
"The extension {0} has forwarded port {1}. You'll need to run as superuser to use port {2} locally.",
source,
tunnelOptions.remoteAddress.port,
tunnelOptions.localAddressPort
)), [{
label: ( localize(2645, "Use Port {0} as Sudo...", tunnel.tunnelRemotePort)),
run: async () => {
this.elevateionRetry = true;
await this.remoteExplorerService.close({
host: tunnel.tunnelRemoteHost,
port: tunnel.tunnelRemotePort
}, TunnelCloseReason.Other);
await this.remoteExplorerService.forward({
remote: tunnelOptions.remoteAddress,
local: tunnelOptions.localAddressPort,
name: tunnelOptions.label,
source: {
source: TunnelSource.Extension,
description: source
},
elevateIfNeeded: true
});
this.elevateionRetry = false;
}
}]);
}
async $closeTunnel(remote) {
return this.remoteExplorerService.close(remote, TunnelCloseReason.Other);
}
async $getTunnels() {
return ( (await this.tunnelService.tunnels).map(tunnel => {
return {
remoteAddress: {
port: tunnel.tunnelRemotePort,
host: tunnel.tunnelRemoteHost
},
localAddress: tunnel.localAddress,
privacy: tunnel.privacy,
protocol: tunnel.protocol
};
}));
}
async $onFoundNewCandidates(candidates) {
this.remoteExplorerService.onFoundNewCandidates(candidates);
}
async $setTunnelProvider(features, isResolver) {
const tunnelProvider = {
forwardPort: (tunnelOptions, tunnelCreationOptions) => {
const forward = this._proxy.$forwardPort(tunnelOptions, tunnelCreationOptions);
return forward.then(tunnelOrError => {
if (!tunnelOrError) {
return undefined;
} else if (typeof tunnelOrError === "string") {
return tunnelOrError;
}
const tunnel = tunnelOrError;
this.logService.trace(
`ForwardedPorts: (MainThreadTunnelService) New tunnel established by tunnel provider: ${tunnel?.remoteAddress.host}:${tunnel?.remoteAddress.port}`
);
return {
tunnelRemotePort: tunnel.remoteAddress.port,
tunnelRemoteHost: tunnel.remoteAddress.host,
localAddress: typeof tunnel.localAddress === "string" ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port),
tunnelLocalPort: typeof tunnel.localAddress !== "string" ? tunnel.localAddress.port : undefined,
public: tunnel.public,
privacy: tunnel.privacy,
protocol: tunnel.protocol ?? TunnelProtocol.Http,
dispose: async silent => {
this.logService.trace(
`ForwardedPorts: (MainThreadTunnelService) Closing tunnel from tunnel provider: ${tunnel?.remoteAddress.host}:${tunnel?.remoteAddress.port}`
);
return this._proxy.$closeTunnel({
host: tunnel.remoteAddress.host,
port: tunnel.remoteAddress.port
}, silent);
}
};
});
}
};
if (features) {
this.tunnelService.setTunnelFeatures(features);
}
this.tunnelService.setTunnelProvider(tunnelProvider);
if (isResolver) {
this.contextKeyService.createKey(forwardedPortsFeaturesEnabled.key, true);
}
}
async $hasTunnelProvider() {
return this.tunnelService.hasTunnelProvider;
}
async $setCandidateFilter() {
this.remoteExplorerService.setCandidateFilter(candidates => {
return this._proxy.$applyCandidateFilter(candidates);
});
}
async $setCandidatePortSource(source) {
this.remoteAgentService.getEnvironment().then(() => {
switch (source) {
case CandidatePortSource.None:
{
( Registry.as(Extensions.Configuration)).registerDefaultConfigurations([{
overrides: {
"remote.autoForwardPorts": false
}
}]);
break;
}
case CandidatePortSource.Output:
{
( Registry.as(Extensions.Configuration)).registerDefaultConfigurations([{
overrides: {
"remote.autoForwardPortsSource": PORT_AUTO_SOURCE_SETTING_OUTPUT
}
}]);
break;
}
case CandidatePortSource.Hybrid:
{
( Registry.as(Extensions.Configuration)).registerDefaultConfigurations([{
overrides: {
"remote.autoForwardPortsSource": PORT_AUTO_SOURCE_SETTING_HYBRID
}
}]);
break;
}
}
}).catch(() => {});
}
};
MainThreadTunnelService = __decorate([extHostNamedCustomer(MainContext.MainThreadTunnelService), ( __param(1, IRemoteExplorerService)), ( __param(2, ITunnelService)), ( __param(3, INotificationService)), ( __param(4, IConfigurationService)), ( __param(5, ILogService)), ( __param(6, IRemoteAgentService)), ( __param(7, IContextKeyService))], MainThreadTunnelService);
export { MainThreadTunnelService };