UNPKG

vscode-chrome-debug-core

Version:

A library for building VS Code debug adapters for targets that support the Chrome Remote Debug Protocol

171 lines (169 loc) 8.58 kB
"use strict"; /*--------------------------------------------------------- * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const utils = require("../utils"); const executionTimingsReporter_1 = require("../executionTimingsReporter"); const chromeUtils = require("./chromeUtils"); const nls = require("vscode-nls"); const localize = nls.loadMessageBundle(__filename); class ProtocolSchema { constructor(_major, _minor) { this._major = _major; this._minor = _minor; } static unknownVersion() { return new ProtocolSchema(0, 0); // Using 0.0 will make behave isAtLeastVersion as if this was the oldest possible version } isAtLeastVersion(major, minor) { return major > this._major || (major === this._major && minor >= this._minor); } } exports.ProtocolSchema = ProtocolSchema; class ChromeTargetDiscovery { constructor(_logger, _telemetry) { this.events = new executionTimingsReporter_1.StepProgressEventsEmitter(); this.logger = _logger; this.telemetry = _telemetry; } getTarget(address, port, targetFilter, targetUrl) { return __awaiter(this, void 0, void 0, function* () { const targets = yield this.getAllTargets(address, port, targetFilter, targetUrl); if (targets.length > 1) { this.logger.log('Warning: Found more than one valid target page. Attaching to the first one. Available pages: ' + JSON.stringify(targets.map(target => target.url))); } const selectedTarget = targets[0]; this.logger.verbose(`Attaching to target: ${JSON.stringify(selectedTarget)}`); this.logger.verbose(`WebSocket Url: ${selectedTarget.webSocketDebuggerUrl}`); return selectedTarget; }); } getAllTargets(address, port, targetFilter, targetUrl) { return __awaiter(this, void 0, void 0, function* () { const targets = yield this._getTargets(address, port); /* __GDPR__ "targetCount" : { "numTargets" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "${include}": [ "${DebugCommonProperties}" ] } */ this.telemetry.reportEvent('targetCount', { numTargets: targets.length }); if (!targets.length) { return utils.errP(localize(0, null)); } return this._getMatchingTargets(targets, targetFilter, targetUrl); }); } _getVersionData(address, port) { return __awaiter(this, void 0, void 0, function* () { const url = `http://${address}:${port}/json/version`; this.logger.log(`Getting browser and debug protocol version via ${url}`); const jsonResponse = yield utils.getURL(url, { headers: { Host: 'localhost' } }) .catch(e => this.logger.log(`There was an error connecting to ${url} : ${e.message}`)); try { if (jsonResponse) { const response = JSON.parse(jsonResponse); const versionString = response['Protocol-Version']; this.logger.log(`Got browser version: ${response.Browser}`); this.logger.log(`Got debug protocol version: ${versionString}`); /* __GDPR__ "targetDebugProtocolVersion" : { "debugProtocolVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "${include}": [ "${DebugCommonProperties}" ] } */ this.telemetry.reportEvent('targetDebugProtocolVersion', { debugProtocolVersion: response['Protcol-Version'] }); const majorAndMinor = versionString.split('.'); const major = parseInt(majorAndMinor[0], 10); const minor = parseInt(majorAndMinor[1], 10); return new ProtocolSchema(major, minor); } } catch (e) { this.logger.log(`Didn't get a valid response for /json/version call. Error: ${e.message}. Response: ${jsonResponse}`); } return ProtocolSchema.unknownVersion(); }); } _getTargets(address, port) { return __awaiter(this, void 0, void 0, function* () { // Get the browser and the protocol version const version = this._getVersionData(address, port); /* __GDPR__FRAGMENT__ "StepNames" : { "Attach.RequestDebuggerTargetsInformation" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.events.emitStepStarted('Attach.RequestDebuggerTargetsInformation'); const checkDiscoveryEndpoint = (url) => { this.logger.log(`Discovering targets via ${url}`); return utils.getURL(url, { headers: { Host: 'localhost' } }); }; const jsonResponse = yield checkDiscoveryEndpoint(`http://${address}:${port}/json/list`) .catch(() => checkDiscoveryEndpoint(`http://${address}:${port}/json`)) .catch(e => utils.errP(localize(1, null, e.message))); /* __GDPR__FRAGMENT__ "StepNames" : { "Attach.ProcessDebuggerTargetsInformation" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.events.emitStepStarted('Attach.ProcessDebuggerTargetsInformation'); try { const responseArray = JSON.parse(jsonResponse); if (Array.isArray(responseArray)) { return responseArray .map(target => { this._fixRemoteUrl(address, port, target); target.version = version; return target; }); } else { return utils.errP(localize(2, null, jsonResponse)); } } catch (e) { return utils.errP(localize(3, null, e.message, jsonResponse)); } }); } _getMatchingTargets(targets, targetFilter, targetUrl) { let filteredTargets = targetFilter ? targets.filter(targetFilter) : // Apply the consumer-specific target filter targets; // If a url was specified, try to filter to that url filteredTargets = targetUrl ? chromeUtils.getMatchingTargets(filteredTargets, targetUrl) : filteredTargets; if (!filteredTargets.length) { throw new Error(localize(4, null, targetUrl, JSON.stringify(targets.map(target => target.url)))); } // If all possible targets appear to be attached to have some other devtool attached, then fail const targetsWithWSURLs = filteredTargets.filter(target => !!target.webSocketDebuggerUrl); if (!targetsWithWSURLs.length) { throw new Error(localize(5, null, filteredTargets[0].url)); } return targetsWithWSURLs; } _fixRemoteUrl(remoteAddress, remotePort, target) { if (target.webSocketDebuggerUrl) { const addressMatch = target.webSocketDebuggerUrl.match(/ws:\/\/([^/]+)\/?/); if (addressMatch) { const replaceAddress = `${remoteAddress}:${remotePort}`; target.webSocketDebuggerUrl = target.webSocketDebuggerUrl.replace(addressMatch[1], replaceAddress); } } return target; } } exports.ChromeTargetDiscovery = ChromeTargetDiscovery; //# sourceMappingURL=chromeTargetDiscoveryStrategy.js.map