UNPKG

node-firefox-find-ports

Version:

Find ports where debuggable runtimes are listening

204 lines (140 loc) 4.42 kB
'use strict'; // See https://github.com/jshint/jshint/issues/1747 for context /* global -Promise */ var Promise = require('es6-promise').Promise; var exec = require('shelljs').exec; var FirefoxClient = require('firefox-client'); var os = process.platform; var parsers = require('./lib/parsers'); var commands = { darwin: 'lsof -i -n -P -sTCP:LISTEN', linux: 'netstat -lnptu', win32: ['tasklist', 'netstat -ano'] }; var adb = require('adbkit'); var REMOTE_DEBUGGER_SOCKET = 'localfilesystem:/data/local/debugger-socket'; module.exports = findPorts; function findPorts(opts) { opts = opts || {}; var isDefaultSearch = !opts.firefox && !opts.firefoxOSSimulator && !opts.firefoxOSDevice; if (isDefaultSearch) { // By default, search for all kinds of debugging ports. opts.firefox = opts.firefoxOSSimulator = opts.firefoxOSDevice = true; } if (!opts.hasOwnProperty('ignoreMultiplePortsPerDevice')) { // By default, ignore multiple debugging ports found for the same device. opts.ignoreMultiplePortsPerDevice = true; } return findLocalPorts(opts).then(function(results) { return findForwardedPorts(opts, results); }).then(function(results) { return expandResults(opts, results); }); } function findLocalPorts(opts) { return new Promise(function(resolve, reject) { var search = []; if (opts.firefox) { search.push('firefox'); } if (opts.firefoxOSSimulator) { search.push('b2g'); } if (search.length === 0) { return resolve([]); } var command = commands[os]; var parser = parsers[os]; if (parser === undefined) { return reject(new Error(os + ' not supported yet')); } var lines = Array.isArray(command) ? command.map(execAndSplitLines) : execAndSplitLines(command); var results = parser(lines, search); return resolve(results); }); } function findForwardedPorts(opts, results) { if (!opts.firefoxOSDevice) { return results; } return adb.createClient().listForwards().then(function(ports) { var seenDevices = {}; var deviceResults = ports.filter(function(port) { // Filter out multiple ports per device when necessary. if (opts.ignoreMultiplePortsPerDevice) { var seenKey = port.serial; if (opts.ignoreMultiplePortsPerDevice && seenKey in seenDevices) { return false; } seenDevices[seenKey] = true; } // We only want local TCP/IP ports forwarded to remote debugging sockets. return port.remote === REMOTE_DEBUGGER_SOCKET && port.local.indexOf('tcp:') === 0; }).map(function(port) { // Extract the port number from tcp:{port} var portNumber = parseInt(port.local.substr(4)); return { type: 'device', port: portNumber, deviceId: port.serial }; }); return results.concat(deviceResults); }); } function expandResults(opts, results) { if (opts.release && opts.release.length > 0) { opts.detailed = true; } if (!opts.detailed) { return results; } return Promise.all(results.map(getDeviceInfo)) .then(function(detailedResults) { return filterByRelease(detailedResults, opts.release); }); } function execAndSplitLines(command) { return exec(command, { silent: true }).output.split('\n'); } function getDeviceInfo(instance) { return new Promise(function(resolve, reject) { var client = new FirefoxClient(); client.connect(instance.port, function(err) { if (err) { return reject(err); } client.getDevice(function(err, device) { if (err) { return reject(err); } device.getDescription(function(err, deviceDescription) { if (err) { return reject(err); } instance.device = deviceDescription; instance.release = deviceDescription.version; client.disconnect(); resolve(instance); }); }); }); }); } function filterByRelease(results, release) { if (!release) { return results; } if (typeof release === 'string') { release = [ release ]; } return results.filter(function(result) { var regex = new RegExp('^(' + release.join('|') + ')'); return regex.exec(result.device.version); }); }