Bug 1185486 - Part 2: Prevent message listeners from a failed command from causing an out of order response when a content command hangs. r=ato

--HG--
extra : commitid : 9x2P0ubHLCZ
This commit is contained in:
Chris Manchester 2015-09-25 07:33:11 -07:00
parent 7c2c936f02
commit cc73ee6143

View File

@ -72,12 +72,18 @@ var ContentSender = function(mmFn, sendAsyncFn) {
this.curId = null;
this.sendAsync = sendAsyncFn;
this.mmFn_ = mmFn;
this._listeners = [];
};
Object.defineProperty(ContentSender.prototype, "mm", {
get: function() { return this.mmFn_(); }
});
ContentSender.prototype.removeListeners = function () {
this._listeners.map(l => this.mm.removeMessageListener(l[0], l[1]));
this._listeners = [];
}
/**
* Call registered function in the frame script environment of the
* current browsing context's content frame.
@ -94,6 +100,13 @@ Object.defineProperty(ContentSender.prototype, "mm", {
* A promise that resolves to the result of the command.
*/
ContentSender.prototype.send = function(name, args) {
if (this._listeners[0]) {
// A prior (probably timed-out) request has left listeners behind.
// Remove them before proceeding.
logger.warn("A previous failed command left content listeners behind!");
this.removeListeners();
}
this.curId = uuidgen.generateUUID().toString();
let proxy = new Promise((resolve, reject) => {
@ -106,40 +119,33 @@ ContentSender.prototype.send = function(name, args) {
return;
}
listeners.remove();
this.removeListeners();
modal.removeHandler(handleDialog);
fn(msg);
this.curId = null;
};
listeners.push([n, rmFn]);
this._listeners.push([n, rmFn]);
return rmFn;
};
let listeners = [];
listeners.add = () => {
this.mm.addMessageListener(MARIONETTE_OK, removeListeners(MARIONETTE_OK, okListener));
this.mm.addMessageListener(MARIONETTE_DONE, removeListeners(MARIONETTE_DONE, valListener));
this.mm.addMessageListener(MARIONETTE_ERROR, removeListeners(MARIONETTE_ERROR, errListener));
};
listeners.remove = () =>
listeners.map(l => this.mm.removeMessageListener(l[0], l[1]));
let okListener = () => resolve();
let valListener = msg => resolve(msg.json.value);
let errListener = msg => reject(msg.objects.error);
let handleDialog = function(subject, topic) {
listeners.remove();
let handleDialog = (subject, topic) => {
this.removeListeners()
modal.removeHandler(handleDialog);
this.sendAsync("cancelRequest");
resolve();
}.bind(this);
};
// start content process listeners, and install observers for global-
// and tab modal dialogues
listeners.add();
this.mm.addMessageListener(MARIONETTE_OK, removeListeners(MARIONETTE_OK, okListener));
this.mm.addMessageListener(MARIONETTE_DONE, removeListeners(MARIONETTE_DONE, valListener));
this.mm.addMessageListener(MARIONETTE_ERROR, removeListeners(MARIONETTE_ERROR, errListener));
modal.addHandler(handleDialog);
// new style dispatches are arrays of arguments, old style dispatches