Bug 1107706: Part 8: Adapt emulator callbacks

Emulator callbacks are now created dynamically upon request, and uses
a nicer data structure in chrome context.  Each emulator callback is
encapsulated in EmulatorCallback, and stored on Emulator.

Emulator is stored on Dispatcher (as opposed to in marionette-server.js)
which bypasses some of the problems with circumventing the Marionette
protocol in GeckoDriver because of CommandProcessor.

Emulator callbacks to the client should be considered transparent, hence
they do not use the ListenerProxy.  They are explicitly meant _not_
to be blocking.

--HG--
extra : rebase_source : 9e887526af99c02036575e5c7b6790629d5f917d
extra : source : eeb3d39874b17e02888427afb9709f35abc95120
This commit is contained in:
Andreas Tolfsen 2015-03-17 16:10:58 +00:00
Родитель 04cfbfd5fe
Коммит 443a731154
2 изменённых файлов: 122 добавлений и 10 удалений

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

@ -0,0 +1,118 @@
/* 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} = Components;
const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
this.EXPORTED_SYMBOLS = ["emulator", "Emulator", "EmulatorCallback"];
this.emulator = {};
/**
* Determines if command ID is an emulator callback.
*/
this.emulator.isCallback = function(cmdId) {
return cmdId < 0;
};
/**
* 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)} sendFn
* Callback function that sends a message to the emulator.
*/
this.Emulator = function(sendFn) {
this.send = sendFn;
this.cbs = [];
};
/**
* Pops a callback off the stack if found. Otherwise this is a no-op.
*
* @param {number} id
* Unique ID associated with the callback.
*
* @return {?function(Object)}
* Callback function that takes an emulator response message as
* an argument.
*/
Emulator.prototype.popCallback = function(id) {
let f, fi;
for (let i = 0; i < this.cbs.length; ++i) {
if (this.cbs[i].id == id) {
f = this.cbs[i];
fi = i;
}
}
if (!f)
return null;
this.cbs.splice(fi, 1);
return f;
};
/**
* Pushes callback on to the stack.
*
* @param {function(Object)} cb
* Callback function that takes an emulator response message as
* an argument.
*/
Emulator.prototype.pushCallback = function(cb) {
cb.send_ = this.sendFn;
this.cbs.push(cb);
};
/**
* Encapsulates a callback to the emulator and provides an execution
* environment for them.
*
* Each callback is assigned a unique identifier, id, that can be used
* to retrieve them from Emulator's stack using popCallback.
*
* The onresult event listener is triggered when a result arrives on
* the callback.
*
* The onerror event listener is triggered when an error occurs during
* the execution of that callback.
*/
this.EmulatorCallback = function() {
this.id = uuidGen.generateUUID().toString();
this.onresult = null;
this.onerror = null;
this.send_ = null;
};
EmulatorCallback.prototype.command = function(cmd, cb) {
this.onresult = cb;
this.send_({emulator_cmd: cmd, id: this.id});
};
EmulatorCallback.prototype.shell = function(args, cb) {
this.onresult = cb;
this.send_({emulator_shell: args, id: this.id});
};
EmulatorCallback.prototype.result = function(msg) {
if (this.send_ === null)
throw new TypeError(
"EmulatorCallback must be registered with Emulator to fire");
try {
if (!this.onresult)
return;
this.onresult(msg.result);
} catch (e) {
if (this.onerror)
this.onerror(e);
}
};

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

@ -2,6 +2,10 @@
* 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/. */
let {utils: Cu} = Components;
Cu.import("chrome://marionette/content/error.js");
this.EXPORTED_SYMBOLS = ["Marionette"];
/*
@ -197,14 +201,4 @@ Marionette.prototype = {
}
this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, deadline);
},
runEmulatorCmd: function runEmulatorCmd(cmd, callback) {
this.heartbeatCallback();
this.scope.runEmulatorCmd(cmd, callback);
},
runEmulatorShell: function runEmulatorShell(args, callback) {
this.heartbeatCallback();
this.scope.runEmulatorShell(args, callback);
},
};