tenfourfox/testing/marionette/emulator.js

112 lines
3.4 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const logger = Log.repository.getLogger("Marionette");
this.EXPORTED_SYMBOLS = ["Emulator"];
/**
* Represents the connection between Marionette and the emulator it's
* running on.
*
* When injected scripts call the JS routines {@code runEmulatorCmd} or
* {@code runEmulatorShell}, the second argument to those is a callback
* which is stored in cbs. They are later retreived by their unique ID
* using popCallback.
*
* @param {function(Object)} sendToEmulatorFn
* Callback function that sends a message to the emulator.
* @param {function(Object)} sendToEmulatorFn
* Callback function that sends a message asynchronously to the
* current listener.
*/
this.Emulator = function(sendToEmulatorFn) {
this.sendToEmulator = sendToEmulatorFn;
};
/**
* Instruct the client to run an Android emulator command.
*
* @param {string} cmd
* The command to run.
* @param {function(?)} resCb
* Callback on a result response from the emulator.
* @param {function(?)} errCb
* Callback on an error in running the command.
*/
Emulator.prototype.command = function(cmd, resCb, errCb) {
assertDefined(cmd, "runEmulatorCmd");
this.sendToEmulator(
"runEmulatorCmd", {emulator_cmd: cmd}, resCb, errCb);
};
/**
* Instruct the client to execute Android emulator shell arguments.
*
* @param {Array.<string>} args
* The shell instruction for the emulator to execute.
* @param {function(?)} resCb
* Callback on a result response from the emulator.
* @param {function(?)} errCb
* Callback on an error in executing the shell arguments.
*/
Emulator.prototype.shell = function(args, resCb, errCb) {
assertDefined(args, "runEmulatorShell");
this.sendToEmulator(
"runEmulatorShell", {emulator_shell: args}, resCb, errCb);
};
Emulator.prototype.processMessage = function(msg) {
let resCb = this.resultCallback(msg.json.id);
let errCb = this.errorCallback(msg.json.id);
switch (msg.name) {
case "Marionette:runEmulatorCmd":
this.command(msg.json.command, resCb, errCb);
break;
case "Marionette:runEmulatorShell":
this.shell(msg.json.arguments, resCb, errCb);
break;
}
};
Emulator.prototype.resultCallback = function(msgId) {
return res => this.sendResult({result: res, id: msgId});
};
Emulator.prototype.errorCallback = function(msgId) {
return err => this.sendResult({error: err, id: msgId});
};
Emulator.prototype.sendResult = function(msg) {
// sendToListener set explicitly in GeckoDriver's ctor
this.sendToListener("emulatorCmdResult", msg);
};
/** Receives IPC messages from the listener. */
Emulator.prototype.receiveMessage = function(msg) {
try {
this.processMessage(msg);
} catch (e) {
this.sendResult({error: `${e.name}: ${e.message}`, id: msg.json.id});
}
};
Emulator.prototype.QueryInterface = XPCOMUtils.generateQI(
[Ci.nsIMessageListener, Ci.nsISupportsWeakReference]);
function assertDefined(arg, action) {
if (typeof arg == "undefined") {
throw new TypeError("Not enough arguments to " + action);
}
}