mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-01-08 07:31:32 +00:00
121 lines
3.9 KiB
JavaScript
121 lines
3.9 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/. */
|
|
|
|
/*
|
|
* This module implements a number of utility functions that can be loaded
|
|
* into content scope.
|
|
*
|
|
* All asynchronous helper methods should return promises, rather than being
|
|
* callback based.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
this.EXPORTED_SYMBOLS = [
|
|
"ContentTaskUtils",
|
|
];
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
Cu.import("resource://gre/modules/Timer.jsm");
|
|
|
|
this.ContentTaskUtils = {
|
|
/**
|
|
* Will poll a condition function until it returns true.
|
|
*
|
|
* @param condition
|
|
* A condition function that must return true or false. If the
|
|
* condition ever throws, this is also treated as a false.
|
|
* @param interval
|
|
* The time interval to poll the condition function. Defaults
|
|
* to 100ms.
|
|
* @param attempts
|
|
* The number of times to poll before giving up and rejecting
|
|
* if the condition has not yet returned true. Defaults to 50
|
|
* (~5 seconds for 100ms intervals)
|
|
* @return Promise
|
|
* Resolves when condition is true.
|
|
* Rejects if timeout is exceeded or condition ever throws.
|
|
*/
|
|
waitForCondition(condition, msg, interval=100, maxTries=50) {
|
|
return new Promise((resolve, reject) => {
|
|
let tries = 0;
|
|
let intervalID = setInterval(() => {
|
|
if (tries >= maxTries) {
|
|
clearInterval(intervalID);
|
|
msg += ` - timed out after ${maxTries} tries.`;
|
|
reject(msg);
|
|
return;
|
|
}
|
|
|
|
let conditionPassed = false;
|
|
try {
|
|
conditionPassed = condition();
|
|
} catch(e) {
|
|
msg += ` - threw exception: ${e}`;
|
|
clearInterval(intervalID);
|
|
reject(msg);
|
|
return;
|
|
}
|
|
|
|
if (conditionPassed) {
|
|
clearInterval(intervalID);
|
|
resolve();
|
|
}
|
|
tries++;
|
|
}, interval);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Waits for an event to be fired on a specified element.
|
|
*
|
|
* Usage:
|
|
* let promiseEvent = ContentTasKUtils.waitForEvent(element, "eventName");
|
|
* // Do some processing here that will cause the event to be fired
|
|
* // ...
|
|
* // Now yield until the Promise is fulfilled
|
|
* let receivedEvent = yield promiseEvent;
|
|
*
|
|
* @param {Element} subject
|
|
* The element that should receive the event.
|
|
* @param {string} eventName
|
|
* Name of the event to listen to.
|
|
* @param {bool} capture [optional]
|
|
* True to use a capturing listener.
|
|
* @param {function} checkFn [optional]
|
|
* Called with the Event object as argument, should return true if the
|
|
* event is the expected one, or false if it should be ignored and
|
|
* listening should continue. If not specified, the first event with
|
|
* the specified name resolves the returned promise.
|
|
*
|
|
* @note Because this function is intended for testing, any error in checkFn
|
|
* will cause the returned promise to be rejected instead of waiting for
|
|
* the next event, since this is probably a bug in the test.
|
|
*
|
|
* @returns {Promise}
|
|
* @resolves The Event object.
|
|
*/
|
|
waitForEvent(subject, eventName, capture, checkFn) {
|
|
return new Promise((resolve, reject) => {
|
|
subject.addEventListener(eventName, function listener(event) {
|
|
try {
|
|
if (checkFn && !checkFn(event)) {
|
|
return;
|
|
}
|
|
subject.removeEventListener(eventName, listener, capture);
|
|
resolve(event);
|
|
} catch (ex) {
|
|
try {
|
|
subject.removeEventListener(eventName, listener, capture);
|
|
} catch (ex2) {
|
|
// Maybe the provided object does not support removeEventListener.
|
|
}
|
|
reject(ex);
|
|
}
|
|
}, capture);
|
|
});
|
|
},
|
|
};
|