UNPKG

mobile-cli-lib

Version:
216 lines (215 loc) 11.9 kB
"use strict"; var os_1 = require("os"); var shelljs = require("shelljs"); var device_android_debug_bridge_1 = require("../android/device-android-debug-bridge"); var constants_1 = require("../../constants"); var AndroidProcessService = (function () { function AndroidProcessService($errors, $staticConfig, $injector, $net, $processService) { this.$errors = $errors; this.$staticConfig = $staticConfig; this.$injector = $injector; this.$net = $net; this.$processService = $processService; this._devicesAdbs = {}; this._forwardedLocalPorts = []; } Object.defineProperty(AndroidProcessService.prototype, "androidPortInformationRegExp", { get: function () { var wordCharacters = "[0-9A-Za-z]+"; var hexIpAddressWithPort = "[0-9A-Za-z]+:[0-9A-Za-z]+"; var hexIpAddressWithPortWithSpace = hexIpAddressWithPort + "\\s+"; var hexIpAddressWithPortWithSpaceMatch = "(" + hexIpAddressWithPort + ")\\s+"; return new RegExp("(\\d+):\\s+" + hexIpAddressWithPortWithSpaceMatch + hexIpAddressWithPortWithSpaceMatch + wordCharacters + "\\s+" + hexIpAddressWithPortWithSpace + hexIpAddressWithPortWithSpace + wordCharacters + "\\s+(\\d+)", "g"); }, enumerable: true, configurable: true }); AndroidProcessService.prototype.mapAbstractToTcpPort = function (deviceIdentifier, appIdentifier, framework) { var _this = this; return (function () { _this.tryAttachToProcessExitSignals(); var adb = _this.getAdb(deviceIdentifier); var processId = _this.getProcessIds(adb, [appIdentifier]).wait()[appIdentifier]; var applicationNotStartedErrorMessage = "The application is not started on the device with identifier " + deviceIdentifier + "."; if (!processId) { _this.$errors.failWithoutHelp(applicationNotStartedErrorMessage); } var abstractPortsInformation = _this.getAbstractPortsInformation(adb).wait(); var abstractPort = _this.getAbstractPortForApplication(adb, processId, appIdentifier, abstractPortsInformation, framework).wait(); if (!abstractPort) { _this.$errors.failWithoutHelp(applicationNotStartedErrorMessage); } var localPort = _this.getAlreadyMappedPort(adb, deviceIdentifier, abstractPort).wait(); if (!localPort) { localPort = _this.$net.getFreePort().wait(); adb.executeCommand(["forward", ("tcp:" + localPort), ("localabstract:" + abstractPort)]).wait(); } _this._forwardedLocalPorts.push(localPort); return localPort; }).future()(); }; AndroidProcessService.prototype.getMappedAbstractToTcpPorts = function (deviceIdentifier, appIdentifiers, framework) { var _this = this; return (function () { var adb = _this.getAdb(deviceIdentifier), abstractPortsInformation = _this.getAbstractPortsInformation(adb).wait(), processIds = _this.getProcessIds(adb, appIdentifiers).wait(), adbForwardList = adb.executeCommand(["forward", "--list"]).wait(), localPorts = {}; _.each(appIdentifiers, function (appIdentifier) { localPorts[appIdentifier] = null; var processId = processIds[appIdentifier]; if (!processId) { return; } var abstractPort = _this.getAbstractPortForApplication(adb, processId, appIdentifier, abstractPortsInformation, framework).wait(); if (!abstractPort) { return; } var localPort = _this.getAlreadyMappedPort(adb, deviceIdentifier, abstractPort, adbForwardList).wait(); if (localPort) { localPorts[appIdentifier] = localPort; } }); return localPorts; }).future()(); }; AndroidProcessService.prototype.getDebuggableApps = function (deviceIdentifier) { var _this = this; return (function () { var adb = _this.getAdb(deviceIdentifier); var androidWebViewPortInformation = _this.getAbstractPortsInformation(adb).wait().split(os_1.EOL); return _(androidWebViewPortInformation) .map(function (line) { return _this.getApplicationInfoFromWebViewPortInformation(adb, deviceIdentifier, line).wait() || _this.getNativeScriptApplicationInformation(adb, deviceIdentifier, line).wait(); }) .filter(function (deviceAppInfo) { return !!deviceAppInfo; }) .groupBy(function (element) { return element.framework; }) .map(function (group) { return _.uniqBy(group, function (g) { return g.appIdentifier; }); }) .flatten() .value(); }).future()(); }; AndroidProcessService.prototype.getApplicationInfoFromWebViewPortInformation = function (adb, deviceIdentifier, information) { var _this = this; return (function () { var processIdRegExp = /@webview_devtools_remote_(.+)/g, processIdMatches = processIdRegExp.exec(information), cordovaAppIdentifier; if (processIdMatches) { var processId = processIdMatches[1]; cordovaAppIdentifier = _this.getApplicationIdentifierFromPid(adb, processId).wait(); } else { var chromeAppIdentifierRegExp = /@(.+)_devtools_remote\s?/g; var chromeAppIdentifierMatches = chromeAppIdentifierRegExp.exec(information); if (chromeAppIdentifierMatches && chromeAppIdentifierMatches.length > 0) { cordovaAppIdentifier = chromeAppIdentifierMatches[1]; } } if (cordovaAppIdentifier) { return { deviceIdentifier: deviceIdentifier, appIdentifier: cordovaAppIdentifier, framework: constants_1.TARGET_FRAMEWORK_IDENTIFIERS.Cordova }; } return null; }).future()(); }; AndroidProcessService.prototype.getNativeScriptApplicationInformation = function (adb, deviceIdentifier, information) { return (function () { var nativeScriptAppIdentifierRegExp = /@(.+)-debug/g; var nativeScriptAppIdentifierMatches = nativeScriptAppIdentifierRegExp.exec(information); if (nativeScriptAppIdentifierMatches && nativeScriptAppIdentifierMatches.length > 0) { var appIdentifier = nativeScriptAppIdentifierMatches[1]; return { deviceIdentifier: deviceIdentifier, appIdentifier: appIdentifier, framework: constants_1.TARGET_FRAMEWORK_IDENTIFIERS.NativeScript }; } return null; }).future()(); }; AndroidProcessService.prototype.getAbstractPortForApplication = function (adb, processId, appIdentifier, abstractPortsInformation, framework) { var _this = this; return (function () { framework = framework || ""; switch (framework.toLowerCase()) { case constants_1.TARGET_FRAMEWORK_IDENTIFIERS.Cordova.toLowerCase(): return _this.getCordovaPortInformation(abstractPortsInformation, appIdentifier, processId); case constants_1.TARGET_FRAMEWORK_IDENTIFIERS.NativeScript.toLowerCase(): return _this.getNativeScriptPortInformation(abstractPortsInformation, appIdentifier); default: return _this.getCordovaPortInformation(abstractPortsInformation, appIdentifier, processId) || _this.getNativeScriptPortInformation(abstractPortsInformation, appIdentifier); } }).future()(); }; AndroidProcessService.prototype.getCordovaPortInformation = function (abstractPortsInformation, appIdentifier, processId) { return this.getPortInformation(abstractPortsInformation, appIdentifier + "_devtools_remote") || this.getPortInformation(abstractPortsInformation, processId); }; AndroidProcessService.prototype.getNativeScriptPortInformation = function (abstractPortsInformation, appIdentifier) { return this.getPortInformation(abstractPortsInformation, appIdentifier + "-debug"); }; AndroidProcessService.prototype.getAbstractPortsInformation = function (adb) { return adb.executeShellCommand(["cat", "/proc/net/unix"]); }; AndroidProcessService.prototype.getPortInformation = function (abstractPortsInformation, searchedInfo) { var processRegExp = new RegExp("\\w+:\\s+(?:\\w+\\s+){1,6}@(.*?" + searchedInfo + ")$", "gm"); var match = processRegExp.exec(abstractPortsInformation); return match && match[1]; }; AndroidProcessService.prototype.getProcessIds = function (adb, appIdentifiers) { var _this = this; return (function () { var result = {}; var processIdInformation = adb.executeShellCommand(["ps"]).wait(); _.each(appIdentifiers, function (appIdentifier) { var processIdRegExp = new RegExp("^\\w*\\s*(\\d+).*?" + appIdentifier + "$"); result[appIdentifier] = _this.getFirstMatchingGroupFromMultilineResult(processIdInformation, processIdRegExp); }); return result; }).future()(); }; AndroidProcessService.prototype.getAlreadyMappedPort = function (adb, deviceIdentifier, abstractPort, adbForwardList) { var _this = this; return (function () { var allForwardedPorts = adbForwardList || adb.executeCommand(["forward", "--list"]).wait() || ""; var regex = new RegExp(deviceIdentifier + "\\s+?tcp:(\\d+?)\\s+?.*?" + abstractPort + "$"); return _this.getFirstMatchingGroupFromMultilineResult(allForwardedPorts, regex); }).future()(); }; AndroidProcessService.prototype.getAdb = function (deviceIdentifier) { if (!this._devicesAdbs[deviceIdentifier]) { this._devicesAdbs[deviceIdentifier] = this.$injector.resolve(device_android_debug_bridge_1.DeviceAndroidDebugBridge, { identifier: deviceIdentifier }); } return this._devicesAdbs[deviceIdentifier]; }; AndroidProcessService.prototype.getApplicationIdentifierFromPid = function (adb, pid, psData) { var _this = this; return (function () { psData = psData || adb.executeShellCommand(["ps"]).wait(); return _this.getFirstMatchingGroupFromMultilineResult(psData, new RegExp("\\s+" + pid + "(?:\\s+\\d+){3}\\s+.*\\s+(.*?)$")); }).future()(); }; AndroidProcessService.prototype.getFirstMatchingGroupFromMultilineResult = function (input, regex) { var result; _((input || "").split('\n')) .map(function (line) { return line.trim(); }) .filter(function (line) { return !!line; }) .each(function (line) { var matches = line.match(regex); if (matches && matches[1]) { result = matches[1]; return false; } }); return result; }; AndroidProcessService.prototype.tryAttachToProcessExitSignals = function () { var _this = this; this.$processService.attachToProcessExitSignals(this, function () { _.each(_this._forwardedLocalPorts, function (port) { shelljs.exec("adb forward --remove tcp:" + port); }); }); }; return AndroidProcessService; }()); exports.AndroidProcessService = AndroidProcessService; $injector.register("androidProcessService", AndroidProcessService);