mobile-cli-lib
Version:
common lib used by different CLI
216 lines (215 loc) • 11.9 kB
JavaScript
"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 = //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);