UNPKG

sussudio

Version:

An unofficial VS Code Internal API

68 lines (67 loc) 2.94 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Schemas } from "../../../base/common/network.mjs"; import { URI } from "../../../base/common/uri.mjs"; import { extractLocalHostUriMetaDataForPortMapping } from "../../tunnel/common/tunnel.mjs"; /** * Manages port mappings for a single webview. */ export class WebviewPortMappingManager { _getExtensionLocation; _getMappings; tunnelService; _tunnels = new Map(); constructor(_getExtensionLocation, _getMappings, tunnelService) { this._getExtensionLocation = _getExtensionLocation; this._getMappings = _getMappings; this.tunnelService = tunnelService; } async getRedirect(resolveAuthority, url) { const uri = URI.parse(url); const requestLocalHostInfo = extractLocalHostUriMetaDataForPortMapping(uri); if (!requestLocalHostInfo) { return undefined; } for (const mapping of this._getMappings()) { if (mapping.webviewPort === requestLocalHostInfo.port) { const extensionLocation = this._getExtensionLocation(); if (extensionLocation && extensionLocation.scheme === Schemas.vscodeRemote) { const tunnel = resolveAuthority && await this.getOrCreateTunnel(resolveAuthority, mapping.extensionHostPort); if (tunnel) { if (tunnel.tunnelLocalPort === mapping.webviewPort) { return undefined; } return encodeURI(uri.with({ authority: `127.0.0.1:${tunnel.tunnelLocalPort}`, }).toString(true)); } } if (mapping.webviewPort !== mapping.extensionHostPort) { return encodeURI(uri.with({ authority: `${requestLocalHostInfo.address}:${mapping.extensionHostPort}` }).toString(true)); } } } return undefined; } async dispose() { for (const tunnel of this._tunnels.values()) { await tunnel.dispose(); } this._tunnels.clear(); } async getOrCreateTunnel(remoteAuthority, remotePort) { const existing = this._tunnels.get(remotePort); if (existing) { return existing; } const tunnel = await this.tunnelService.openTunnel({ getAddress: async () => remoteAuthority }, undefined, remotePort); if (tunnel) { this._tunnels.set(remotePort, tunnel); } return tunnel; } }