use appium-chromedriver package for chrome/chromedriver

This commit is contained in:
Jonathan Lipps 2015-01-09 16:33:23 -08:00
Родитель 6c78716d96
Коммит a7b85ecd84
6 изменённых файлов: 217 добавлений и 372 удалений

Просмотреть файл

@ -3,14 +3,20 @@
var logger = require('../../server/logger.js').get('appium')
, _ = require('underscore')
, errors = require('../../server/errors.js')
, path = require('path')
, system = require('appium-support').system
, isWindows = system.isWindows()
, isLinux = system.isLinux()
, exec = require('child_process').exec
, UnknownError = errors.UnknownError
, async = require('async')
, Chromedriver = require('./chromedriver.js')
, Chromedriver = require('appium-chromedriver').default
, status = require("../../server/status.js");
var androidHybrid = {};
androidHybrid.chromedriver = null;
androidHybrid.chromedriverStopCbs = {};
androidHybrid.sessionChromedrivers = {};
androidHybrid.listWebviews = function (cb) {
@ -65,17 +71,12 @@ androidHybrid.listWebviews = function (cb) {
var previousState = {};
// remember whether we were previously proxying to a chromedriver or not
androidHybrid.rememberProxyState = function () {
previousState.proxyHost = this.proxyHost;
previousState.proxyPort = this.proxyPort;
previousState.proxySessionId = this.proxySessionId;
previousState.isProxy = this.isProxy;
};
androidHybrid.restoreProxyState = function () {
this.proxyHost = previousState.proxyHost;
this.proxyPort = previousState.proxyPort;
this.proxySessionId = previousState.proxySessionId;
this.isProxy = previousState.isProxy;
};
@ -118,101 +119,136 @@ androidHybrid.getProcessNameFromWebview = function (webview, cb) {
};
androidHybrid.startChromedriverProxy = function (context, cb) {
cb = _.once(cb);
logger.debug("Connecting to chrome-backed webview");
if (this.chromedriver !== null) {
return cb(new Error("We already have a chromedriver instance running"));
}
var setupNewChromeDriver = function (ocb) {
var chromeArgs = {
port: this.args.chromeDriverPort
, executable: this.args.chromedriverExecutable
, deviceId: this.adb.curDeviceId
, enablePerformanceLogging: this.args.enablePerformanceLogging
};
this.chromedriver = new Chromedriver(chromeArgs, this.onChromedriverExit.bind(this));
this.rememberProxyState();
this.proxyHost = this.chromedriver.proxyHost;
this.proxyPort = this.chromedriver.proxyPort;
this.isProxy = true;
var caps = {
chromeOptions: {
androidPackage: this.args.appPackage,
androidUseRunningApp: true
}
};
// For now the only known arg passed this way is androidDeviceSocked used by Operadriver (deriving from Chromedriver)
// We don't know how other Chromium embedders will call this argument so for now it's name needs to be configurable
// When Google adds the androidDeviceSocket argument to the original Chromedriver then we will be sure about it's name
// for all Chromium embedders (as their Webdrivers will derive from Chromedriver)
if (this.args.specialChromedriverSessionArgs) {
_.each(this.args.specialChromedriverSessionArgs, function (val, option) {
logger.debug("This method is being deprecated. Apply chromeOptions normally to pass along options," +
"see sites.google.com/a/chromium.org/chromedriver/capabilities for more info");
caps.chromeOptions[option] = val;
});
}
caps = this.decorateChromeOptions(caps);
this.chromedriver.createSession(caps, function (err, sessId) {
if (err) return cb(err);
logger.debug("Setting proxy session id to " + sessId);
this.proxySessionId = sessId;
this.sessionChromedrivers[context] = this.chromedriver;
ocb();
}.bind(this));
}.bind(this);
if (this.sessionChromedrivers[context]) {
logger.debug("Found existing Chromedriver for context '" + context + "'." +
" Using it.");
this.rememberProxyState();
this.chromedriver = this.sessionChromedrivers[context];
this.proxyHost = this.chromedriver.proxyHost;
this.proxyPort = this.chromedriver.proxyPort;
this.proxySessionId = this.chromedriver.chromeSessionId;
this.isProxy = true;
// in the case where we've already set up a chromedriver for a context,
// we want to reconnect to it, not create a whole new one
this.setupExistingChromedriver(context, cb);
} else {
this.setupNewChromedriver(context, cb);
}
};
// check the status by sending a simple window-based command to ChromeDriver
// if there is an error, we want to recreate the ChromeDriver session
var url = '/wd/hub/session/' + this.proxySessionId + '/url';
this.chromedriver.proxyTo(url, 'GET', {}, function (err, res, body) {
body = JSON.parse(body);
if ((body.status === status.codes.NoSuchWindow.code && body.value.message.indexOf('no such window: window was already closed') !== -1) ||
(body.status === 100 && body.value.message.indexOf('chrome not reachable') !== -1)) {
// the window is closed and we need to reinitialize
logger.debug("ChromeDriver is not associated with a window. Re-initializing the session.");
this.cleanupChromedriver(this.chromedriver, function () {
setupNewChromeDriver(cb);
});
} else {
cb();
androidHybrid.setupNewChromedriver = function (context, ocb) {
var chromeArgs = {
port: this.args.chromeDriverPort
, executable: this.args.chromedriverExecutable
, deviceId: this.adb.curDeviceId
};
this.chromedriver = new Chromedriver(chromeArgs);
this.proxyReqRes = this.chromedriver.proxyReq.bind(this.chromedriver);
this.rememberProxyState();
this.isProxy = true;
var caps = {
chromeOptions: {
androidPackage: this.args.appPackage,
androidUseRunningApp: true
}
};
if (this.args.enablePerformanceLogging) {
caps.loggingPrefs = {performance: 'ALL'};
}
// For now the only known arg passed this way is androidDeviceSocket used
// by Operadriver (deriving from Chromedriver) // We don't know how other
// Chromium embedders will call this argument so for now it's name needs to
// be configurable. When Google adds the androidDeviceSocket argument to
// the original Chromedriver then we will be sure about its name for all
// Chromium embedders (as their Webdrivers will derive from Chromedriver)
if (this.args.specialChromedriverSessionArgs) {
_.each(this.args.specialChromedriverSessionArgs, function (val, option) {
logger.debug("This method is being deprecated. Apply chromeOptions " +
"normally to pass along options,see sites.google.com/a/" +
"chromium.org/chromedriver/capabilities for more info");
caps.chromeOptions[option] = val;
});
}
caps = this.decorateChromeOptions(caps);
// see note in chrome.js::createSession for explanation of this pattern
this.chromedriver.once(Chromedriver.EVENT_ERROR, ocb);
this.chromedriver.on(Chromedriver.EVENT_CHANGED, function (msg) {
if (msg.state === Chromedriver.STATE_ONLINE) {
// save the chromedriver object under the context
this.sessionChromedrivers[context] = this.chromedriver;
// let whoever called us know that we're done setting up session
ocb();
} else if (msg.state === Chromedriver.STATE_STOPPED) {
// bind our stop/exit handler, passing in context so we know which
// one stopped
this.onChromedriverStop(context);
}
}.bind(this));
this.chromedriver.start(caps);
};
androidHybrid.setupExistingChromedriver = function (context, cb) {
logger.debug("Found existing Chromedriver for context '" + context + "'." +
" Using it.");
this.rememberProxyState();
this.chromedriver = this.sessionChromedrivers[context];
this.proxyReqRes = this.chromedriver.proxyReq.bind(this.chromedriver);
this.isProxy = true;
// make sure that no matter how many times Chromedriver emits a changed
// state event, we only call back on the first ONLINE message
var restartCb = _.once(function () {
// once we're back online, let upstream know
this.chromedriverRestartingContext = null;
cb();
}.bind(this));
// check the status by sending a simple window-based command to ChromeDriver
// if there is an error, we want to recreate the ChromeDriver session
this.chromedriver.hasWorkingWebview().then(function (works) {
if (works) return cb();
logger.debug("ChromeDriver is not associated with a window. " +
"Re-initializing the session.");
// catch any errors the restart process bubbles up
this.chromedriver.once(Chromedriver.EVENT_ERROR, cb);
// once the restart is successful, reset context flag and continue
this.chromedriver.on(Chromedriver.EVENT_CHANGED, function (msg) {
if (msg.state === Chromedriver.STATE_ONLINE) {
restartCb();
}
}.bind(this));
} else {
setupNewChromeDriver(cb);
}
this.chromedriverRestartingContext = context;
this.chromedriver.restart();
}.bind(this)).catch(cb);
};
androidHybrid.onChromedriverExit = function () {
logger.debug("Chromedriver exited unexpectedly");
if (typeof this.cbForCurrentCmd === "function") {
androidHybrid.onChromedriverStop = function (context) {
logger.debug("Chromedriver for context " + context + " stopped");
// chromedriver isn't valid anymore, so remove it from context list
if (_.has(this.chromedriverStopCbs, context)) {
// if we intentionally stopped this context's chromedriver, we'll have a
// callback for it in this.chromedriverStopCbs
delete this.sessionChromedrivers[context];
this.chromedriverStopCbs[context]();
} else if (context === this.curContext) {
// if we don't have a stop callback, we exited unexpectedly and so want
// to shut down the session and respond with an error
// TODO: this kind of thing should be emitted and handled by a higher-level
// controlling function
var error = new UnknownError("Chromedriver quit unexpectedly during session");
this.shutdown(function () {
this.cbForCurrentCmd(error, null);
}.bind(this));
}
};
androidHybrid.cleanupChromedriver = function (chromedriver, cb) {
if (chromedriver) {
logger.debug("Cleaning up Chromedriver");
chromedriver.stop(function (err) {
if (err) logger.warn("Error stopping chromedriver: " + err.message);
this.restoreProxyState();
cb();
}.bind(this));
} else {
cb();
logger.error(error.message);
if (typeof this.cbForCurrentCmd === "function") {
this.shutdown(function () {
this.cbForCurrentCmd(error, null);
}.bind(this));
}
} else if (context !== this.chromedriverRestartingContext) {
// if a Chromedriver in the non-active context barfs, we don't really
// care, we'll just make a new one next time we need the context.
// The only time we ignore this is if we know we're in the middle of a
// Chromedriver restart
logger.warn("Chromedriver quit unexpectedly, but it wasn't the active " +
"context, ignoring");
delete this.sessionChromedrivers[context];
}
};
@ -224,13 +260,16 @@ androidHybrid.suspendChromedriverProxy = function (cb) {
androidHybrid.stopChromedriverProxies = function (ocb) {
async.eachSeries(Object.keys(this.sessionChromedrivers), function (context, cb) {
var chromedriver = this.sessionChromedrivers[context];
chromedriver.deleteSession(function (err) {
if (err) return cb(err);
this.cleanupChromedriver(chromedriver, cb);
delete this.sessionChromedrivers[context];
}.bind(this));
}.bind(this), ocb);
logger.debug("Stopping chromedriver for context " + context);
// add a stop cb for this context so we get called back once this context's
// chromedriver finishes exiting
this.chromedriverStopCbs[context] = _.once(cb);
this.sessionChromedrivers[context].stop();
}.bind(this), function (err) {
// if one of these fails, go back to last proxy state and error out
this.restoreProxyState();
ocb(err);
}.bind(this));
};
androidHybrid.defaultWebviewName = function () {
@ -255,4 +294,38 @@ androidHybrid.initAutoWebview = function (cb) {
}
};
// get the correct chromedriver executable path based on our system
// TODO: don't download/build chromedriver in reset.sh, instead let this be
// something that the appium-chromedriver package manages
androidHybrid.initChromedriverPath = function (cb) {
if (this.args.chromedriverExecutable) {
cb();
} else {
var setPath = function (platform, executable) {
this.args.chromedriverExecutable = path.resolve(__dirname, "..", "..",
"..", "build", "chromedriver", platform, executable);
logger.debug("Set chromedriver binary as: " + this.args.chromedriverExecutable);
}.bind(this);
if (isLinux) {
logger.debug("Determining linux architecture");
exec("uname -m", function (err, stdout) {
var executable;
if (err) return cb(err);
if (stdout.trim() === "i686") {
executable = "chromedriver32";
} else {
executable = "chromedriver64";
}
setPath("linux", executable);
cb();
});
} else {
var executable = isWindows ? "chromedriver.exe" : "chromedriver";
var platform = isWindows ? "windows" : "mac";
setPath(platform, executable);
cb();
}
}
};
module.exports = androidHybrid;

Просмотреть файл

@ -101,6 +101,7 @@ Android.prototype.start = function (cb, onDie) {
this.initAdb.bind(this),
this.packageAndLaunchActivityFromManifest.bind(this),
this.initUiautomator.bind(this),
this.initChromedriverPath.bind(this),
this.prepareDevice.bind(this),
this.checkApiLevel.bind(this),
this.pushStrings.bind(this),

Просмотреть файл

@ -1,13 +1,15 @@
"use strict";
var Android = require('./android.js')
, Chromedriver = require('appium-chromedriver').default
, _ = require('underscore')
, logger = require('../../server/logger.js').get('appium')
, status = require('../../server/status.js')
, deviceCommon = require('../common.js')
, jwpSuccess = deviceCommon.jwpSuccess
, async = require('async')
, Chromedriver = require('./chromedriver.js');
, ADB = require('./adb.js')
, UiAutomator = require('./uiautomator.js');
var NATIVE_WIN = "NATIVE_APP";
var WEBVIEW_WIN = "WEBVIEW";
@ -22,7 +24,7 @@ ChromeAndroid.prototype._androidInit = Android.prototype.init;
ChromeAndroid.prototype.init = function () {
this._androidInit();
this.adb = null;
this.onDie = null;
this.stopCb = null;
this.setChromedriverMode();
};
@ -79,12 +81,16 @@ ChromeAndroid.prototype.startAutomation = function (cb) {
};
ChromeAndroid.prototype.start = function (cb, onDie) {
this.onDie = onDie;
this.adb = new ADB(this.args);
this.uiautomator = new UiAutomator(this.adb, this.args);
this.uiautomator.setExitHandler(this.onUiautomatorExit.bind(this));
this.stopCb = onDie;
async.series([
this.initAdb.bind(this),
this.initUiautomator.bind(this),
this.prepareDevice.bind(this),
this.initChromedriverPath.bind(this),
this.prepareChromedriver.bind(this),
this.pushAndUnlock.bind(this),
this.forwardPort.bind(this),
@ -105,14 +111,9 @@ ChromeAndroid.prototype.prepareChromedriver = function (cb) {
port: this.args.proxyPort
, executable: this.args.chromedriverExecutable
, deviceId: this.adb.curDeviceId
, enablePerformanceLogging: this.args.enablePerformanceLogging
};
this.chromedriver = new Chromedriver(chromeArgs, this.adb,
this.onChromedriverExit.bind(this));
this.proxyTo = this.chromedriver.proxyTo.bind(this.chromedriver);
this.proxyHost = this.chromedriver.proxyHost;
this.proxyPort = this.chromedriver.proxyPort;
this.deleteSession = this.chromedriver.deleteSession.bind(this.chromedriver);
this.chromedriver = new Chromedriver(chromeArgs);
this.proxyReqRes = this.chromedriver.proxyReq.bind(this.chromedriver);
cb();
};
@ -124,11 +125,15 @@ ChromeAndroid.prototype.pushAndUnlock = function (cb) {
};
ChromeAndroid.prototype.createSession = function (cb) {
cb = _.once(cb);
var caps = {
chromeOptions: {
androidPackage: this.args.appPackage
}
};
if (this.args.enablePerformanceLogging) {
caps.loggingPrefs = {performance: 'ALL'};
}
var knownPackages = ["org.chromium.chrome.shell",
"com.android.chrome",
@ -139,30 +144,34 @@ ChromeAndroid.prototype.createSession = function (cb) {
}
caps = this.decorateChromeOptions(caps);
this.chromedriver.createSession(caps, cb);
this.chromedriver.once(Chromedriver.EVENT_ERROR, cb);
this.chromedriver.on(Chromedriver.EVENT_CHANGED, function (msg) {
if (msg.state === Chromedriver.STATE_ONLINE) {
cb();
} else if (msg.state === Chromedriver.STATE_STOPPED) {
this.onChromedriverStop();
}
}.bind(this));
this.chromedriver.start(caps);
};
ChromeAndroid.prototype.stop = function (cb) {
this.uiautomator.shutdown(function () {
this.chromedriver.stop(function (err) {
if (err) return cb(err);
this.stopCb = cb; // change stopCb from original onDie to this cb
this.chromedriver.stop();
};
ChromeAndroid.prototype.onChromedriverStop = function () {
var cb = this.stopCb;
if (this.adb) {
this.uiautomator.shutdown(function () {
this.adb.forceStop(this.args.appPackage, function (err) {
if (err) return cb(err);
this.adb.stopLogcat(cb);
}.bind(this));
}.bind(this));
}.bind(this));
};
ChromeAndroid.prototype.onChromedriverExit = function () {
if (!this.adb) return; // cleaning up has already occured.
async.series([
this.adb.getConnectedDevices.bind(this.adb),
_.partial(this.adb.forceStop.bind(this.adb), this.args.appPackage)
], function (err) {
if (err) logger.error(err.message);
this.adb.stopLogcat(this.onDie.bind(this));
}.bind(this));
} else {
cb();
}
};
// since we're in chrome, our default context is not the native mode, but web

Просмотреть файл

@ -1,249 +0,0 @@
"use strict";
var proxyTo = require('../common.js').proxyTo
, _ = require('underscore')
, logger = require('../../server/logger.js').get('appium')
, exec = require('child_process').exec
, spawn = require('child_process').spawn
, async = require('async')
, through = require('through')
, system = require('appium-support').system
, isWindows = system.isWindows()
, isLinux = system.isLinux()
, path = require('path')
, fs = require('fs')
, ADB = require('./adb.js');
var Chromedriver = function (args, adb, onDie) {
this.proxyHost = '127.0.0.1';
this.proxyPort = args.port || 9515;
this.deviceId = args.deviceId;
this.enablePerformanceLogging = args.enablePerformanceLogging;
this.proc = null;
this.onChromedriverStart = null;
this.onDie = onDie;
this.exitCb = null;
this.shuttingDown = false;
this.executable = args.executable;
this.adb = adb;
};
Chromedriver.prototype.initChromedriverPath = function (cb) {
if (this.executable) {
this.chromedriver = this.executable;
cb();
} else {
var setPath = function (platform, executable) {
this.chromedriver = path.resolve(__dirname, "..", "..", "..", "build",
"chromedriver", platform, executable);
logger.debug("Set chromedriver binary as: " + this.chromedriver);
}.bind(this);
if (isLinux) {
logger.debug("Determining linux architecture");
exec("uname -m", function (err, stdout) {
var executable;
if (err) return cb(err);
if (stdout.trim() === "i686") {
executable = "chromedriver32";
} else {
executable = "chromedriver64";
}
setPath("linux", executable);
cb();
});
} else {
var executable = isWindows ? "chromedriver.exe" : "chromedriver";
var platform = isWindows ? "windows" : "mac";
setPath(platform, executable);
cb();
}
}
};
Chromedriver.prototype.ensureChromedriverExists = function (cb) {
logger.debug("Ensuring Chromedriver exists");
fs.exists(this.chromedriver, function (exists) {
if (!exists) return cb(new Error("Could not find chromedriver. Need to run reset script?"));
cb();
});
};
Chromedriver.prototype.killOldChromedrivers = function (cb) {
var cmd;
if (isWindows) {
cmd = "FOR /F \"usebackq tokens=5\" %a in (`netstat -nao ^| findstr /R /C:\"" + this.proxyPort + " \"`) do (" +
"FOR /F \"usebackq\" %b in (`TASKLIST /FI \"PID eq %a\" ^| findstr /I chromedriver.exe`) do (" +
"IF NOT %b==\"\" TASKKILL /F /PID %a" +
")" +
")";
} else {
cmd = "ps -ef | grep " + this.chromedriver + " | grep -v grep |" +
"grep -e '--port=" + this.proxyPort + "\\(\\s.*\\)\\?$' | awk '{ print $2 }' | " +
"xargs kill -15";
}
logger.debug("Killing any old chromedrivers, running: " + cmd);
exec(cmd, function (err) {
if (err) {
logger.debug("No old chromedrivers seemed to exist");
} else {
logger.debug("Successfully cleaned up old chromedrivers");
}
cb();
});
};
Chromedriver.prototype.start = function (cb) {
this.onChromedriverStart = cb;
logger.debug("Spawning chromedriver with: " + this.chromedriver);
var alreadyReturned = false;
var args = ["--url-base=wd/hub", "--port=" + this.proxyPort, "--adb-port=" + ADB.getAdbServerPort()];
this.proc = spawn(this.chromedriver, args);
this.proc.stdout.setEncoding('utf8');
this.proc.stderr.setEncoding('utf8');
this.proc.on('error', function (err) {
logger.error('Chromedriver process failed with error: ' + err.message);
alreadyReturned = true;
this.shuttingDown = true;
logger.error('Killing chromedriver');
this.proc.kill();
this.onDie();
}.bind(this));
this.proc.stdout.pipe(through(function (data) {
logger.debug('[CHROMEDRIVER] ' + data.trim());
if (!alreadyReturned && data.indexOf('Starting ') === 0) {
this.chromedriverStarted = true;
alreadyReturned = true;
return cb();
}
}.bind(this)));
this.proc.stderr.pipe(through(function (data) {
logger.debug('[CHROMEDRIVER STDERR] ' + data.trim());
}));
this.proc.on('exit', this.onClose.bind(this));
this.proc.on('close', this.onClose.bind(this));
};
Chromedriver.prototype.onClose = function (code, signal) {
if (!this.shuttingDown) {
this.shuttingDown = true;
logger.debug("Chromedriver exited with code " + code);
if (signal) {
logger.debug("(killed by signal " + signal + ")");
}
if (!this.chromedriverStarted) {
return this.onChromedriverStart(
new Error("Chromedriver quit before it was available"));
}
if (this.exitCb !== null) {
return this.exitCb();
}
this.onDie();
}
};
Chromedriver.prototype.createSession = function (caps, cb) {
logger.debug("Creating Chrome session");
caps.chromeOptions.androidDeviceSerial = this.deviceId;
if (this.enablePerformanceLogging) {
caps.loggingPrefs = {performance: 'ALL'};
}
var data = {
sessionId: null,
desiredCapabilities: caps
};
async.waterfall([
this.initChromedriverPath.bind(this),
this.ensureChromedriverExists.bind(this),
this.killOldChromedrivers.bind(this),
this.start.bind(this),
_.partial(this.proxyNewSession.bind(this), data)
], cb);
};
Chromedriver.prototype.proxyNewSession = function (data, cb) {
var maxRetries = 5;
var curRetry = 0;
var retryInt = 500;
var doProxy = function (alreadyRestarted) {
this.proxyTo('/wd/hub/session', 'POST', data, function (err, res, body) {
if (err) {
if (/ECONNREFUSED/.test(err.message) && curRetry < maxRetries) {
logger.debug("Could not connect yet; retrying");
curRetry++;
setTimeout(doProxy, retryInt);
return;
}
return cb(err);
}
// first checking if we get a well formed success response
this.chromeSessionId = null;
try {
if (body.status === 0 && body.sessionId) {
logger.debug("Successfully started chrome session " + body.sessionId);
this.chromeSessionId = body.sessionId;
}
} catch (ignore) {}
if (this.chromeSessionId) return cb(null, this.chromeSessionId);
// then check redirect success case
try {
if (res.statusCode === 303 && res.headers.location) {
logger.debug("Successfully started chrome session");
var loc = res.headers.location;
this.chromeSessionId = /\/([^\/]+)$/.exec(loc)[1];
}
} catch (ignore) {}
if (this.chromeSessionId) return cb(null, this.chromeSessionId);
// those are error cases
if (typeof body !== "undefined" &&
typeof body.value !== "undefined" &&
typeof body.value.message !== "undefined" &&
body.value.message.indexOf("Failed to run adb command") !== -1) {
logger.error("Chromedriver had trouble running adb");
if (!alreadyRestarted) {
logger.error("Restarting adb for chromedriver");
return this.adb.restartAdb(function () {
this.adb.getConnectedDevices(function () {
doProxy(true);
}.bind(this));
}.bind(this));
} else {
cb(new Error("Chromedriver wasn't able to use adb. Is the server up?"));
}
} else {
logger.error("Chromedriver create session did not work. Status was " +
res.statusCode + " and body was " +
JSON.stringify(body));
cb(new Error("Did not get session redirect from Chromedriver"));
}
}.bind(this));
}.bind(this);
doProxy();
};
Chromedriver.prototype.deleteSession = function (cb) {
logger.debug("Deleting Chrome session");
var url = '/wd/hub/session/' + this.chromeSessionId;
this.proxyTo(url, 'DELETE', null, function (err, res) {
if (err) return cb(err);
if (res.statusCode !== 200) return cb(new Error("Status was not 200"));
cb();
}.bind(this));
};
Chromedriver.prototype.stop = function (cb) {
logger.debug('Killing chromedriver and waiting for close');
this.exitCb = cb;
this.proc.kill('SIGINT');
};
Chromedriver.prototype.proxyTo = proxyTo;
module.exports = Chromedriver;

Просмотреть файл

@ -39,6 +39,16 @@ module.exports.shouldProxy = function (req) {
};
module.exports.doProxy = function (req, res) {
if (req.device.proxyReqRes) {
// this section is triggered when we have defined the proxy device to use
// the appium-jsonwp-proxy method proxyReqRes. Ultimately we'll be moving
// everything to this paradigm and will delete the code after this block
req.device.proxyReqRes(req, res).catch(function (err) {
logger.error(err.message);
});
return;
}
logger.debug("Proxying command to " + req.device.proxyHost + ":" +
req.device.proxyPort);
var sessRe = new RegExp('^/wd/hub/session/([^/]+)');

Просмотреть файл

@ -43,6 +43,7 @@
"adm-zip": "~0.4.7",
"appium-adb": "=1.7.5",
"appium-atoms": "=0.0.5",
"appium-chromedriver": "=0.2.0",
"appium-instruments": "=1.5.4",
"appium-support": "=0.1.1",
"appium-uiauto": "=1.10.7",