mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-16 12:17:34 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
1329
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
Normal file
1329
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
Normal file
File diff suppressed because it is too large
Load diff
128
testing/mochitest/BrowserTestUtils/ContentTask.jsm
Normal file
128
testing/mochitest/BrowserTestUtils/ContentTask.jsm
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80 filetype=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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"ContentTask"
|
||||
];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const FRAME_SCRIPT = "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js";
|
||||
|
||||
/**
|
||||
* Keeps track of whether the frame script was already loaded.
|
||||
*/
|
||||
var gFrameScriptLoaded = false;
|
||||
|
||||
/**
|
||||
* Mapping from message id to associated promise.
|
||||
*/
|
||||
var gPromises = new Map();
|
||||
|
||||
/**
|
||||
* Incrementing integer to generate unique message id.
|
||||
*/
|
||||
var gMessageID = 1;
|
||||
|
||||
/**
|
||||
* This object provides the public module functions.
|
||||
*/
|
||||
this.ContentTask = {
|
||||
/**
|
||||
* _testScope saves the current testScope from
|
||||
* browser-test.js. This is used to implement SimpleTest functions
|
||||
* like ok() and is() in the content process. The scope is only
|
||||
* valid for tasks spawned in the current test, so we keep track of
|
||||
* the ID of the first task spawned in this test (_scopeValidId).
|
||||
*/
|
||||
_testScope: null,
|
||||
_scopeValidId: 0,
|
||||
|
||||
/**
|
||||
* Creates and starts a new task in a browser's content.
|
||||
*
|
||||
* @param browser A xul:browser
|
||||
* @param arg A single serializable argument that will be passed to the
|
||||
* task when executed on the content process.
|
||||
* @param task
|
||||
* - A generator or function which will be serialized and sent to
|
||||
* the remote browser to be executed. Unlike Task.spawn, this
|
||||
* argument may not be an iterator as it will be serialized and
|
||||
* sent to the remote browser.
|
||||
* @return A promise object where you can register completion callbacks to be
|
||||
* called when the task terminates.
|
||||
* @resolves With the final returned value of the task if it executes
|
||||
* successfully.
|
||||
* @rejects An error message if execution fails.
|
||||
*/
|
||||
spawn: function ContentTask_spawn(browser, arg, task) {
|
||||
// Load the frame script if needed.
|
||||
if (!gFrameScriptLoaded) {
|
||||
Services.mm.loadFrameScript(FRAME_SCRIPT, true);
|
||||
gFrameScriptLoaded = true;
|
||||
}
|
||||
|
||||
let deferred = {};
|
||||
deferred.promise = new Promise((resolve, reject) => {
|
||||
deferred.resolve = resolve;
|
||||
deferred.reject = reject;
|
||||
});
|
||||
|
||||
let id = gMessageID++;
|
||||
gPromises.set(id, deferred);
|
||||
|
||||
browser.messageManager.sendAsyncMessage(
|
||||
"content-task:spawn",
|
||||
{
|
||||
id: id,
|
||||
runnable: task.toString(),
|
||||
arg: arg,
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
setTestScope(scope) {
|
||||
this._testScope = scope;
|
||||
this._scopeValidId = gMessageID;
|
||||
},
|
||||
};
|
||||
|
||||
var ContentMessageListener = {
|
||||
receiveMessage(aMessage) {
|
||||
let id = aMessage.data.id;
|
||||
|
||||
if (id < ContentTask._scopeValidId) {
|
||||
throw new Error("test result returned after test finished");
|
||||
}
|
||||
|
||||
if (aMessage.name == "content-task:complete") {
|
||||
let deferred = gPromises.get(id);
|
||||
gPromises.delete(id);
|
||||
|
||||
if (aMessage.data.error) {
|
||||
deferred.reject(aMessage.data.error);
|
||||
} else {
|
||||
deferred.resolve(aMessage.data.result);
|
||||
}
|
||||
} else if (aMessage.name == "content-task:test-result") {
|
||||
let data = aMessage.data;
|
||||
ContentTask._testScope.ok(data.condition, data.name, null, data.stack);
|
||||
} else if (aMessage.name == "content-task:test-info") {
|
||||
ContentTask._testScope.info(aMessage.data.name);
|
||||
} else if (aMessage.name == "content-task:test-todo") {
|
||||
ContentTask._testScope.todo(aMessage.data.expr, aMessage.data.name);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Services.mm.addMessageListener("content-task:complete", ContentMessageListener);
|
||||
Services.mm.addMessageListener("content-task:test-result", ContentMessageListener);
|
||||
Services.mm.addMessageListener("content-task:test-info", ContentMessageListener);
|
||||
120
testing/mochitest/BrowserTestUtils/ContentTaskUtils.jsm
Normal file
120
testing/mochitest/BrowserTestUtils/ContentTaskUtils.jsm
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* 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, wantsUntrusted = false) {
|
||||
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, wantsUntrusted);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
"use strict";
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
||||
|
||||
function AboutPage(aboutHost, chromeURL, uriFlags) {
|
||||
this.chromeURL = chromeURL;
|
||||
this.aboutHost = aboutHost;
|
||||
this.classID = Components.ID(generateUUID().number);
|
||||
this.description = "BrowserTestUtils: " + aboutHost;
|
||||
this.uriFlags = uriFlags;
|
||||
}
|
||||
|
||||
AboutPage.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||
getURIFlags(aURI) { // eslint-disable-line no-unused-vars
|
||||
return this.uriFlags;
|
||||
},
|
||||
|
||||
newChannel(aURI, aLoadInfo) {
|
||||
let newURI = Services.io.newURI(this.chromeURL, null, null);
|
||||
let channel = Services.io.newChannelFromURIWithLoadInfo(newURI,
|
||||
aLoadInfo);
|
||||
channel.originalURI = aURI;
|
||||
|
||||
if (this.uriFlags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) {
|
||||
channel.owner = null;
|
||||
}
|
||||
return channel;
|
||||
},
|
||||
|
||||
createInstance(outer, iid) {
|
||||
if (outer !== null) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
register() {
|
||||
Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(
|
||||
this.classID, this.description,
|
||||
"@mozilla.org/network/protocol/about;1?what=" + this.aboutHost, this);
|
||||
},
|
||||
|
||||
unregister() {
|
||||
Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(
|
||||
this.classID, this);
|
||||
}
|
||||
};
|
||||
|
||||
const gRegisteredPages = new Map();
|
||||
|
||||
addMessageListener("browser-test-utils:about-registration:register", msg => {
|
||||
let {aboutModule, pageURI, flags} = msg.data;
|
||||
if (gRegisteredPages.has(aboutModule)) {
|
||||
gRegisteredPages.get(aboutModule).unregister();
|
||||
}
|
||||
let moduleObj = new AboutPage(aboutModule, pageURI, flags);
|
||||
moduleObj.register();
|
||||
gRegisteredPages.set(aboutModule, moduleObj);
|
||||
sendAsyncMessage("browser-test-utils:about-registration:registered", aboutModule);
|
||||
});
|
||||
|
||||
addMessageListener("browser-test-utils:about-registration:unregister", msg => {
|
||||
let aboutModule = msg.data;
|
||||
let moduleObj = gRegisteredPages.get(aboutModule);
|
||||
if (moduleObj) {
|
||||
moduleObj.unregister();
|
||||
gRegisteredPages.delete(aboutModule);
|
||||
}
|
||||
sendAsyncMessage("browser-test-utils:about-registration:unregistered", aboutModule);
|
||||
});
|
||||
71
testing/mochitest/BrowserTestUtils/content/content-task.js
Normal file
71
testing/mochitest/BrowserTestUtils/content/content-task.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* 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";
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm", this);
|
||||
Cu.import("resource://testing-common/ContentTaskUtils.jsm", this);
|
||||
const AssertCls = Cu.import("resource://testing-common/Assert.jsm", null).Assert;
|
||||
|
||||
addMessageListener("content-task:spawn", function (msg) {
|
||||
let id = msg.data.id;
|
||||
let source = msg.data.runnable || "()=>{}";
|
||||
|
||||
function getStack(aStack) {
|
||||
let frames = [];
|
||||
for (let frame = aStack; frame; frame = frame.caller) {
|
||||
frames.push(frame.filename + ":" + frame.name + ":" + frame.lineNumber);
|
||||
}
|
||||
return frames.join("\n");
|
||||
}
|
||||
|
||||
var Assert = new AssertCls((err, message, stack) => {
|
||||
sendAsyncMessage("content-task:test-result", {
|
||||
id: id,
|
||||
condition: !err,
|
||||
name: err ? err.message : message,
|
||||
stack: getStack(err ? err.stack : stack)
|
||||
});
|
||||
});
|
||||
|
||||
var ok = Assert.ok.bind(Assert);
|
||||
var is = Assert.equal.bind(Assert);
|
||||
var isnot = Assert.notEqual.bind(Assert);
|
||||
|
||||
function todo(expr, name) {
|
||||
sendAsyncMessage("content-task:test-todo", {id, expr, name});
|
||||
}
|
||||
|
||||
function info(name) {
|
||||
sendAsyncMessage("content-task:test-info", {id, name});
|
||||
}
|
||||
|
||||
try {
|
||||
let runnablestr = `
|
||||
(() => {
|
||||
return (${source});
|
||||
})();`
|
||||
|
||||
let runnable = eval(runnablestr);
|
||||
let iterator = runnable.call(this, msg.data.arg);
|
||||
Task.spawn(iterator).then((val) => {
|
||||
sendAsyncMessage("content-task:complete", {
|
||||
id: id,
|
||||
result: val,
|
||||
});
|
||||
}, (e) => {
|
||||
sendAsyncMessage("content-task:complete", {
|
||||
id: id,
|
||||
error: e.toString(),
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
sendAsyncMessage("content-task:complete", {
|
||||
id: id,
|
||||
error: e.toString(),
|
||||
});
|
||||
}
|
||||
});
|
||||
16
testing/mochitest/BrowserTestUtils/content/content-utils.js
Normal file
16
testing/mochitest/BrowserTestUtils/content/content-utils.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* 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";
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
addEventListener("load", function(event) {
|
||||
let subframe = event.target != content.document;
|
||||
sendAsyncMessage("browser-test-utils:loadEvent",
|
||||
{subframe: subframe, url: event.target.documentURI});
|
||||
}, true);
|
||||
|
||||
11
testing/mochitest/BrowserTestUtils/moz.build
Normal file
11
testing/mochitest/BrowserTestUtils/moz.build
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TESTING_JS_MODULES += [
|
||||
'BrowserTestUtils.jsm',
|
||||
'ContentTask.jsm',
|
||||
'ContentTaskUtils.jsm',
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue