appium-adb
Version:
Android Debug Bridge interface
387 lines (299 loc) • 26.8 kB
JavaScript
;
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _teen_process = require('teen_process');
var _loggerJs = require('../logger.js');
var _loggerJs2 = _interopRequireDefault(_loggerJs);
var _helpersJs = require('../helpers.js');
var _appiumSupport = require('appium-support');
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var helperJarPath = _path2['default'].resolve(__dirname, '..', '..', '..', 'jars');
var manifestMethods = {};
// android:process= may be defined in AndroidManifest.xml
// http://developer.android.com/reference/android/R.attr.html#process
// note that the process name when used with ps must be truncated to the last 15 chars
// ps -c com.example.android.apis becomes ps -c le.android.apis
manifestMethods.processFromManifest = function callee$0$0(localApk) {
var args, _ref, stdout, result, lines, applicationRegex, applicationFound, attributeRegex, processRegex, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, line, notAttribute, _process;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
context$1$0.next = 3;
return _regeneratorRuntime.awrap(this.initAapt());
case 3:
_loggerJs2['default'].info("Retrieving process from manifest");
args = ['dump', 'xmltree', localApk, 'AndroidManifest.xml'];
context$1$0.next = 7;
return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.binaries.aapt, args));
case 7:
_ref = context$1$0.sent;
stdout = _ref.stdout;
result = null;
lines = stdout.split("\n");
applicationRegex = new RegExp(/\s+E: application \(line=\d+\).*/);
applicationFound = false;
attributeRegex = new RegExp(/\s+A: .+/);
processRegex = new RegExp(/\s+A: android:process\(0x01010011\)="([^"]+).*"/);
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 18;
_iterator = _getIterator(lines);
case 20:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 37;
break;
}
line = _step.value;
if (applicationFound) {
context$1$0.next = 26;
break;
}
if (applicationRegex.test(line)) {
applicationFound = true;
}
context$1$0.next = 34;
break;
case 26:
notAttribute = !attributeRegex.test(line);
if (!notAttribute) {
context$1$0.next = 29;
break;
}
return context$1$0.abrupt('break', 37);
case 29:
_process = processRegex.exec(line);
if (!(_process && _process.length > 1)) {
context$1$0.next = 34;
break;
}
result = _process[1];
// must trim to last 15 for android's ps binary
if (result.length > 15) {
result = result.substr(result.length - 15);
}
return context$1$0.abrupt('break', 37);
case 34:
_iteratorNormalCompletion = true;
context$1$0.next = 20;
break;
case 37:
context$1$0.next = 43;
break;
case 39:
context$1$0.prev = 39;
context$1$0.t0 = context$1$0['catch'](18);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 43:
context$1$0.prev = 43;
context$1$0.prev = 44;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 46:
context$1$0.prev = 46;
if (!_didIteratorError) {
context$1$0.next = 49;
break;
}
throw _iteratorError;
case 49:
return context$1$0.finish(46);
case 50:
return context$1$0.finish(43);
case 51:
return context$1$0.abrupt('return', result);
case 54:
context$1$0.prev = 54;
context$1$0.t1 = context$1$0['catch'](0);
_loggerJs2['default'].errorAndThrow('processFromManifest failed. Original error: ' + context$1$0.t1.message);
case 57:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 54], [18, 39, 43, 51], [44,, 46, 50]]);
};
manifestMethods.packageAndLaunchActivityFromManifest = function callee$0$0(localApk) {
var args, _ref2, stdout, apkPackage, apkActivity, outputPath, getLaunchActivity, _ref3, _stdout, stderr, act;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
context$1$0.next = 3;
return _regeneratorRuntime.awrap(this.initAapt());
case 3:
_loggerJs2['default'].info("Extracting package and launch activity from manifest");
args = ['dump', 'badging', localApk];
context$1$0.next = 7;
return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.binaries.aapt, args));
case 7:
_ref2 = context$1$0.sent;
stdout = _ref2.stdout;
apkPackage = new RegExp(/package: name='([^']+)'/g).exec(stdout);
if (apkPackage && apkPackage.length >= 2) {
apkPackage = apkPackage[1];
} else {
apkPackage = null;
}
apkActivity = new RegExp(/launchable-activity: name='([^']+)'/g).exec(stdout);
if (!(apkActivity && apkActivity.length >= 2)) {
context$1$0.next = 16;
break;
}
apkActivity = apkActivity[1];
context$1$0.next = 26;
break;
case 16:
outputPath = _path2['default'].resolve(this.tmpDir, apkPackage);
getLaunchActivity = ['-jar', this.jars['appium_apk_tools.jar'], 'printLaunchActivity', this.opts.app, outputPath];
context$1$0.next = 20;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('java', getLaunchActivity));
case 20:
_ref3 = context$1$0.sent;
_stdout = _ref3.stdout;
stderr = _ref3.stderr;
if (stderr) {
_loggerJs2['default'].errorAndThrow('Cannot parse launchActivity from manifest: ' + stderr);
}
act = new RegExp(/Launch activity parsed:([^']+)/g).exec(_stdout);
if (act && act.length >= 2) {
apkActivity = act[1];
}
case 26:
_loggerJs2['default'].debug('badging package: ' + apkPackage);
_loggerJs2['default'].debug('badging act: ' + apkActivity);
return context$1$0.abrupt('return', { apkPackage: apkPackage, apkActivity: apkActivity });
case 31:
context$1$0.prev = 31;
context$1$0.t0 = context$1$0['catch'](0);
_loggerJs2['default'].errorAndThrow('packageAndLaunchActivityFromManifest failed. Original error: ' + context$1$0.t0.message);
case 34:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 31]]);
};
manifestMethods.compileManifest = function callee$0$0(manifest, manifestPackage, targetPackage) {
var _ref4, platform, platformPath, args;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Compiling manifest ' + manifest);
context$1$0.next = 3;
return _regeneratorRuntime.awrap((0, _helpersJs.getAndroidPlatformAndPath)());
case 3:
_ref4 = context$1$0.sent;
platform = _ref4.platform;
platformPath = _ref4.platformPath;
if (platform) {
context$1$0.next = 8;
break;
}
return context$1$0.abrupt('return', new Error("Required platform doesn't exist (API level >= 17)"));
case 8:
_loggerJs2['default'].debug('Compiling manifest.');
context$1$0.prev = 9;
args = ['package', '-M', manifest, '--rename-manifest-package', manifestPackage, '--rename-instrumentation-target-package', targetPackage, '-I', _path2['default'].resolve(platformPath, 'android.jar'), '-F', manifest + '.apk', '-f'];
context$1$0.next = 13;
return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.binaries.aapt, args));
case 13:
_loggerJs2['default'].debug("Compiled manifest");
context$1$0.next = 19;
break;
case 16:
context$1$0.prev = 16;
context$1$0.t0 = context$1$0['catch'](9);
_loggerJs2['default'].errorAndThrow('Error compiling manifest. Original error: ' + context$1$0.t0.message);
case 19:
case 'end':
return context$1$0.stop();
}
}, null, this, [[9, 16]]);
};
manifestMethods.insertManifest = function callee$0$0(manifest, srcApk, dstApk) {
var java, args;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Inserting manifest, src: ' + srcApk + ' dst: ' + dstApk);
context$1$0.prev = 1;
context$1$0.next = 4;
return _regeneratorRuntime.awrap((0, _helpersJs.unzipFile)(manifest + '.apk'));
case 4:
context$1$0.next = 6;
return _regeneratorRuntime.awrap(_appiumSupport.fs.copyFile(srcApk, dstApk));
case 6:
_loggerJs2['default'].debug("Testing new tmp apk");
context$1$0.next = 9;
return _regeneratorRuntime.awrap((0, _helpersJs.assertZipArchive)(dstApk));
case 9:
_loggerJs2['default'].debug("Moving manifest");
if (!_appiumSupport.system.isWindows()) {
context$1$0.next = 17;
break;
}
java = _path2['default'].resolve(process.env.JAVA_HOME, 'bin', 'java');
args = ['-jar', _path2['default'].resolve(helperJarPath, 'move_manifest.jar'), dstApk, manifest];
context$1$0.next = 15;
return _regeneratorRuntime.awrap((0, _teen_process.exec)(java, args));
case 15:
context$1$0.next = 19;
break;
case 17:
context$1$0.next = 19;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('zip', ['-j', '-m', dstApk, manifest]));
case 19:
_loggerJs2['default'].debug("Inserted manifest.");
context$1$0.next = 25;
break;
case 22:
context$1$0.prev = 22;
context$1$0.t0 = context$1$0['catch'](1);
_loggerJs2['default'].errorAndThrow('Error inserting manifest. Original error: ' + context$1$0.t0.message);
case 25:
case 'end':
return context$1$0.stop();
}
}, null, this, [[1, 22]]);
};
manifestMethods.hasInternetPermissionFromManifest = function callee$0$0(localApk) {
var _ref5, stdout;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
context$1$0.next = 3;
return _regeneratorRuntime.awrap(this.initAapt());
case 3:
_loggerJs2['default'].debug("Checking if has internet permission from manifest");
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.binaries.aapt, ['dump', 'badging', localApk]));
case 6:
_ref5 = context$1$0.sent;
stdout = _ref5.stdout;
return context$1$0.abrupt('return', new RegExp(/uses-permission:.*'android.permission.INTERNET'/).test(stdout));
case 11:
context$1$0.prev = 11;
context$1$0.t0 = context$1$0['catch'](0);
_loggerJs2['default'].errorAndThrow('Error checking internet permission for manifest. Original error: ' + context$1$0.t0.message);
case 14:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 11]]);
};
exports['default'] = manifestMethods;
module.exports = exports['default'];
// process must be an attribute after application.
// this is an application attribute process.
// Insert compiled manifest into /tmp/appPackage.clean.apk
// -j = keep only the file, not the dirs
// -m = move manifest into target apk.
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9hbmRyb2lkLW1hbmlmZXN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs0QkFBcUIsY0FBYzs7d0JBQ25CLGNBQWM7Ozs7eUJBQ3lDLGVBQWU7OzZCQUMzRCxnQkFBZ0I7O29CQUMxQixNQUFNOzs7O0FBRXZCLElBQU0sYUFBYSxHQUFHLGtCQUFLLE9BQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDeEUsSUFBSSxlQUFlLEdBQUcsRUFBRSxDQUFDOzs7Ozs7QUFNekIsZUFBZSxDQUFDLG1CQUFtQixHQUFHLG9CQUFnQixRQUFRO01BSXRELElBQUksUUFDSCxNQUFNLEVBQ1AsTUFBTSxFQUNOLEtBQUssRUFDTCxnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLGNBQWMsRUFDZCxZQUFZLGtGQUNQLElBQUksRUFNTCxZQUFZLEVBS1osUUFBTzs7Ozs7Ozt5Q0FyQlQsSUFBSSxDQUFDLFFBQVEsRUFBRTs7O0FBQ3JCLDhCQUFJLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0FBQ3pDLFlBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixDQUFDOzt5Q0FDMUMsd0JBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDOzs7O0FBQTlDLGNBQU0sUUFBTixNQUFNO0FBQ1AsY0FBTSxHQUFHLElBQUk7QUFDYixhQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7QUFDMUIsd0JBQWdCLEdBQUcsSUFBSSxNQUFNLENBQUMsa0NBQWtDLENBQUM7QUFDakUsd0JBQWdCLEdBQUcsS0FBSztBQUN4QixzQkFBYyxHQUFHLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQztBQUN2QyxvQkFBWSxHQUFHLElBQUksTUFBTSxDQUFDLGlEQUFpRCxDQUFDOzs7OztpQ0FDL0QsS0FBSzs7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QUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDOzs7Ozs7QUFFakYsOEJBQUksYUFBYSx1RUFBcUUsZUFBRSxPQUFPLENBQUcsQ0FBQzs7Ozs7OztDQUV0RyxDQUFDOztxQkFHYSxlQUFlIiwiZmlsZSI6ImxpYi90b29scy9hbmRyb2lkLW1hbmlmZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlYyB9IGZyb20gJ3RlZW5fcHJvY2Vzcyc7XG5pbXBvcnQgbG9nIGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBnZXRBbmRyb2lkUGxhdGZvcm1BbmRQYXRoLCB1bnppcEZpbGUsIGFzc2VydFppcEFyY2hpdmUgfSBmcm9tICcuLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IHN5c3RlbSwgZnMgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcblxuY29uc3QgaGVscGVySmFyUGF0aCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLicsICcuLicsICcuLicsICdqYXJzJyk7XG5sZXQgbWFuaWZlc3RNZXRob2RzID0ge307XG5cbi8vIGFuZHJvaWQ6cHJvY2Vzcz0gbWF5IGJlIGRlZmluZWQgaW4gQW5kcm9pZE1hbmlmZXN0LnhtbFxuLy8gaHR0cDovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9yZWZlcmVuY2UvYW5kcm9pZC9SLmF0dHIuaHRtbCNwcm9jZXNzXG4vLyBub3RlIHRoYXQgdGhlIHByb2Nlc3MgbmFtZSB3aGVuIHVzZWQgd2l0aCBwcyBtdXN0IGJlIHRydW5jYXRlZCB0byB0aGUgbGFzdCAxNSBjaGFyc1xuLy8gcHMgLWMgY29tLmV4YW1wbGUuYW5kcm9pZC5hcGlzIGJlY29tZXMgcHMgLWMgbGUuYW5kcm9pZC5hcGlzXG5tYW5pZmVzdE1ldGhvZHMucHJvY2Vzc0Zyb21NYW5pZmVzdCA9IGFzeW5jIGZ1bmN0aW9uIChsb2NhbEFwaykge1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuaW5pdEFhcHQoKTtcbiAgICBsb2cuaW5mbyhcIlJldHJpZXZpbmcgcHJvY2VzcyBmcm9tIG1hbmlmZXN0XCIpO1xuICAgIGxldCBhcmdzID0gWydkdW1wJywgJ3htbHRyZWUnLCBsb2NhbEFwaywgJ0FuZHJvaWRNYW5pZmVzdC54bWwnXTtcbiAgICBsZXQge3N0ZG91dH0gPSBhd2FpdCBleGVjKHRoaXMuYmluYXJpZXMuYWFwdCwgYXJncyk7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG4gICAgbGV0IGxpbmVzID0gc3Rkb3V0LnNwbGl0KFwiXFxuXCIpO1xuICAgIGxldCBhcHBsaWNhdGlvblJlZ2V4ID0gbmV3IFJlZ0V4cCgvXFxzK0U6IGFwcGxpY2F0aW9uIFxcKGxpbmU9XFxkK1xcKS4qLyk7XG4gICAgbGV0IGFwcGxpY2F0aW9uRm91bmQgPSBmYWxzZTtcbiAgICBsZXQgYXR0cmlidXRlUmVnZXggPSBuZXcgUmVnRXhwKC9cXHMrQTogLisvKTtcbiAgICBsZXQgcHJvY2Vzc1JlZ2V4ID0gbmV3IFJlZ0V4cCgvXFxzK0E6IGFuZHJvaWQ6cHJvY2Vzc1xcKDB4MDEwMTAwMTFcXCk9XCIoW15cIl0rKS4qXCIvKTtcbiAgICBmb3IgKGxldCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICBpZiAoIWFwcGxpY2F0aW9uRm91bmQpIHtcbiAgICAgICAgaWYgKGFwcGxpY2F0aW9uUmVnZXgudGVzdChsaW5lKSkge1xuICAgICAgICAgIGFwcGxpY2F0aW9uRm91bmQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgbm90QXR0cmlidXRlID0gIWF0dHJpYnV0ZVJlZ2V4LnRlc3QobGluZSk7XG4gICAgICAgIC8vIHByb2Nlc3MgbXVzdCBiZSBhbiBhdHRyaWJ1dGUgYWZ0ZXIgYXBwbGljYXRpb24uXG4gICAgICAgIGlmIChub3RBdHRyaWJ1dGUpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBsZXQgcHJvY2VzcyA9IHByb2Nlc3NSZWdleC5leGVjKGxpbmUpO1xuICAgICAgICAvLyB0aGlzIGlzIGFuIGFwcGxpY2F0aW9uIGF0dHJpYnV0ZSBwcm9jZXNzLlxuICAgICAgICBpZiAocHJvY2VzcyAmJiBwcm9jZXNzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICByZXN1bHQgPSBwcm9jZXNzWzFdO1xuICAgICAgICAgIC8vIG11c3QgdHJpbSB0byBsYXN0IDE1IGZvciBhbmRyb2lkJ3MgcHMgYmluYXJ5XG4gICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPiAxNSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnN1YnN0cihyZXN1bHQubGVuZ3RoIC0gMTUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmVycm9yQW5kVGhyb3coYHByb2Nlc3NGcm9tTWFuaWZlc3QgZmFpbGVkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbm1hbmlmZXN0TWV0aG9kcy5wYWNrYWdlQW5kTGF1bmNoQWN0aXZpdHlGcm9tTWFuaWZlc3QgPSBhc3luYyBmdW5jdGlvbiAobG9jYWxBcGspIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLmluaXRBYXB0KCk7XG4gICAgbG9nLmluZm8oXCJFeHRyYWN0aW5nIHBhY2thZ2UgYW5kIGxhdW5jaCBhY3Rpdml0eSBmcm9tIG1hbmlmZXN0XCIpO1xuICAgIGxldCBhcmdzID0gWydkdW1wJywgJ2JhZGdpbmcnLCBsb2NhbEFwa107XG4gICAgbGV0IHtzdGRvdXR9ID0gYXdhaXQgZXhlYyh0aGlzLmJpbmFyaWVzLmFhcHQsIGFyZ3MpO1xuICAgIGxldCBhcGtQYWNrYWdlID0gbmV3IFJlZ0V4cCgvcGFja2FnZTogbmFtZT0nKFteJ10rKScvZykuZXhlYyhzdGRvdXQpO1xuICAgIGlmIChhcGtQYWNrYWdlICYmIGFwa1BhY2thZ2UubGVuZ3RoID49IDIpIHtcbiAgICAgIGFwa1BhY2thZ2UgPSBhcGtQYWNrYWdlWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcGtQYWNrYWdlID0gbnVsbDtcbiAgICB9XG4gICAgbGV0IGFwa0FjdGl2aXR5ID0gbmV3IFJlZ0V4cCgvbGF1bmNoYWJsZS1hY3Rpdml0eTogbmFtZT0nKFteJ10rKScvZykuZXhlYyhzdGRvdXQpO1xuICAgIGlmIChhcGtBY3Rpdml0eSAmJiBhcGtBY3Rpdml0eS5sZW5ndGggPj0gMikge1xuICAgICAgYXBrQWN0aXZpdHkgPSBhcGtBY3Rpdml0eVsxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG91dHB1dFBhdGggPSBwYXRoLnJlc29sdmUodGhpcy50bXBEaXIsIGFwa1BhY2thZ2UpO1xuICAgICAgbGV0IGdldExhdW5jaEFjdGl2aXR5ID0gWyctamFyJywgdGhpcy5qYXJzWydhcHBpdW1fYXBrX3Rvb2xzLmphciddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdwcmludExhdW5jaEFjdGl2aXR5JywgdGhpcy5vcHRzLmFwcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRQYXRoXTtcbiAgICAgIGxldCB7c3Rkb3V0LCBzdGRlcnJ9ID0gYXdhaXQgZXhlYygnamF2YScsIGdldExhdW5jaEFjdGl2aXR5KTtcbiAgICAgIGlmIChzdGRlcnIpIHtcbiAgICAgICAgbG9nLmVycm9yQW5kVGhyb3coYENhbm5vdCBwYXJzZSBsYXVuY2hBY3Rpdml0eSBmcm9tIG1hbmlmZXN0OiAke3N0ZGVycn1gKTtcbiAgICAgIH1cbiAgICAgIGxldCBhY3QgPSBuZXcgUmVnRXhwKC9MYXVuY2ggYWN0aXZpdHkgcGFyc2VkOihbXiddKykvZykuZXhlYyhzdGRvdXQpO1xuICAgICAgaWYgKGFjdCAmJiBhY3QubGVuZ3RoID49IDIpIHtcbiAgICAgICAgYXBrQWN0aXZpdHkgPSBhY3RbMV07XG4gICAgICB9XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgYmFkZ2luZyBwYWNrYWdlOiAke2Fwa1BhY2thZ2V9YCk7XG4gICAgbG9nLmRlYnVnKGBiYWRnaW5nIGFjdDogJHthcGtBY3Rpdml0eX1gKTtcbiAgICByZXR1cm4ge2Fwa1BhY2thZ2UsIGFwa0FjdGl2aXR5fTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZy5lcnJvckFuZFRocm93KGBwYWNrYWdlQW5kTGF1bmNoQWN0aXZpdHlGcm9tTWFuaWZlc3QgZmFpbGVkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbm1hbmlmZXN0TWV0aG9kcy5jb21waWxlTWFuaWZlc3QgPSBhc3luYyBmdW5jdGlvbiAobWFuaWZlc3QsIG1hbmlmZXN0UGFja2FnZSwgdGFyZ2V0UGFja2FnZSkge1xuICBsb2cuZGVidWcoYENvbXBpbGluZyBtYW5pZmVzdCAke21hbmlmZXN0fWApO1xuICBsZXQge3BsYXRmb3JtLCBwbGF0Zm9ybVBhdGh9ID0gYXdhaXQgZ2V0QW5kcm9pZFBsYXRmb3JtQW5kUGF0aCgpO1xuICBpZiAoIXBsYXRmb3JtKSB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihcIlJlcXVpcmVkIHBsYXRmb3JtIGRvZXNuJ3QgZXhpc3QgKEFQSSBsZXZlbCA+PSAxNylcIik7XG4gIH1cbiAgbG9nLmRlYnVnKCdDb21waWxpbmcgbWFuaWZlc3QuJyk7XG4gIHRyeSB7XG4gICAgbGV0IGFyZ3MgPSBbJ3BhY2thZ2UnLCAnLU0nLCBtYW5pZmVzdCwgJy0tcmVuYW1lLW1hbmlmZXN0LXBhY2thZ2UnLFxuICAgICAgICAgICAgICAgIG1hbmlmZXN0UGFja2FnZSwgJy0tcmVuYW1lLWluc3RydW1lbnRhdGlvbi10YXJnZXQtcGFja2FnZScsXG4gICAgICAgICAgICAgICAgdGFyZ2V0UGFja2FnZSwgJy1JJywgcGF0aC5yZXNvbHZlKHBsYXRmb3JtUGF0aCwgJ2FuZHJvaWQuamFyJyksXG4gICAgICAgICAgICAgICAgJy1GJywgbWFuaWZlc3QgKyAnLmFwaycsICctZiddO1xuICAgIGF3YWl0IGV4ZWModGhpcy5iaW5hcmllcy5hYXB0LCBhcmdzKTtcbiAgICBsb2cuZGVidWcoXCJDb21waWxlZCBtYW5pZmVzdFwiKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nLmVycm9yQW5kVGhyb3coYEVycm9yIGNvbXBpbGluZyBtYW5pZmVzdC4gT3JpZ2luYWwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbm1hbmlmZXN0TWV0aG9kcy5pbnNlcnRNYW5pZmVzdCA9IGFzeW5jIGZ1bmN0aW9uIChtYW5pZmVzdCwgc3JjQXBrLCBkc3RBcGspIHtcbiAgbG9nLmRlYnVnKGBJbnNlcnRpbmcgbWFuaWZlc3QsIHNyYzogJHtzcmNBcGt9IGRzdDogJHtkc3RBcGt9YCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgdW56aXBGaWxlKGAke21hbmlmZXN0fS5hcGtgKTtcbiAgICBhd2FpdCBmcy5jb3B5RmlsZShzcmNBcGssIGRzdEFwayk7XG4gICAgbG9nLmRlYnVnKFwiVGVzdGluZyBuZXcgdG1wIGFwa1wiKTtcbiAgICBhd2FpdCBhc3NlcnRaaXBBcmNoaXZlKGRzdEFwayk7XG4gICAgbG9nLmRlYnVnKFwiTW92aW5nIG1hbmlmZXN0XCIpO1xuICAgIGlmIChzeXN0ZW0uaXNXaW5kb3dzKCkpIHtcbiAgICAgIGxldCBqYXZhID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuZW52LkpBVkFfSE9NRSwgJ2JpbicsICdqYXZhJyk7XG4gICAgICBsZXQgYXJncyA9IFsnLWphcicsICBwYXRoLnJlc29sdmUoaGVscGVySmFyUGF0aCwgJ21vdmVfbWFuaWZlc3QuamFyJyksXG4gICAgICAgICAgICAgICAgICBkc3RBcGssIG1hbmlmZXN0XTtcbiAgICAgIGF3YWl0IGV4ZWMoamF2YSwgYXJncyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEluc2VydCBjb21waWxlZCBtYW5pZmVzdCBpbnRvIC90bXAvYXBwUGFja2FnZS5jbGVhbi5hcGtcbiAgICAgIC8vIC1qID0ga2VlcCBvbmx5IHRoZSBmaWxlLCBub3QgdGhlIGRpcnNcbiAgICAgIC8vIC1tID0gbW92ZSBtYW5pZmVzdCBpbnRvIHRhcmdldCBhcGsuXG4gICAgICBhd2FpdCBleGVjKCd6aXAnLCBbJy1qJywgJy1tJywgZHN0QXBrLCBtYW5pZmVzdF0pO1xuICAgIH1cbiAgICBsb2cuZGVidWcoXCJJbnNlcnRlZCBtYW5pZmVzdC5cIik7XG4gIH0gY2F0Y2goZSkge1xuICAgIGxvZy5lcnJvckFuZFRocm93KGBFcnJvciBpbnNlcnRpbmcgbWFuaWZlc3QuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxubWFuaWZlc3RNZXRob2RzLmhhc0ludGVybmV0UGVybWlzc2lvbkZyb21NYW5pZmVzdCA9IGFzeW5jIGZ1bmN0aW9uIChsb2NhbEFwaykge1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuaW5pdEFhcHQoKTtcbiAgICBsb2cuZGVidWcoXCJDaGVja2luZyBpZiBoYXMgaW50ZXJuZXQgcGVybWlzc2lvbiBmcm9tIG1hbmlmZXN0XCIpO1xuICAgIGxldCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWModGhpcy5iaW5hcmllcy5hYXB0LCBbJ2R1bXAnLCAnYmFkZ2luZycsIGxvY2FsQXBrXSk7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoL3VzZXMtcGVybWlzc2lvbjouKidhbmRyb2lkLnBlcm1pc3Npb24uSU5URVJORVQnLykudGVzdChzdGRvdXQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmVycm9yQW5kVGhyb3coYEVycm9yIGNoZWNraW5nIGludGVybmV0IHBlcm1pc3Npb24gZm9yIG1hbmlmZXN0LiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cblxuZXhwb3J0IGRlZmF1bHQgbWFuaWZlc3RNZXRob2RzO1xuIl19