Files
tubestation/toolkit/content/tests/browser/head.js
Cristian Tuns 0a87ef3aaf Backed out 4 changesets (bug 1676068) for causing geckoview failures CLOSED TREE
Backed out changeset ee747c27b9bc (bug 1676068)
Backed out changeset 0876924c66e8 (bug 1676068)
Backed out changeset 30a8292a37ae (bug 1676068)
Backed out changeset 19a0b7a0987c (bug 1676068)
2022-12-01 19:44:47 -05:00

402 lines
11 KiB
JavaScript

"use strict";
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
/**
* Set the findbar value to the given text, start a search for that text, and
* return a promise that resolves when the find has completed.
*
* @param gBrowser tabbrowser to search in the current tab.
* @param searchText text to search for.
* @param highlightOn true if highlight mode should be enabled before searching.
* @returns Promise resolves when find is complete.
*/
async function promiseFindFinished(gBrowser, searchText, highlightOn = false) {
let findbar = await gBrowser.getFindBar();
findbar.startFind(findbar.FIND_NORMAL);
let highlightElement = findbar.getElement("highlight");
if (highlightElement.checked != highlightOn) {
highlightElement.click();
}
return new Promise(resolve => {
executeSoon(() => {
findbar._findField.value = searchText;
let resultListener;
// When highlighting is on the finder sends a second "FOUND" message after
// the search wraps. This causes timing problems with e10s. waitMore
// forces foundOrTimeout wait for the second "FOUND" message before
// resolving the promise.
let waitMore = highlightOn;
let findTimeout = setTimeout(() => foundOrTimedout(null), 5000);
let foundOrTimedout = function(aData) {
if (aData !== null && waitMore) {
waitMore = false;
return;
}
if (aData === null) {
info("Result listener not called, timeout reached.");
}
clearTimeout(findTimeout);
findbar.browser?.finder.removeResultListener(resultListener);
resolve();
};
resultListener = {
onFindResult: foundOrTimedout,
onCurrentSelection() {},
onMatchesCountResult() {},
onHighlightFinished() {},
};
findbar.browser.finder.addResultListener(resultListener);
findbar._find();
});
});
}
/**
* A wrapper for the findbar's method "close", which is not synchronous
* because of animation.
*/
function closeFindbarAndWait(findbar) {
return new Promise(resolve => {
if (findbar.hidden) {
resolve();
return;
}
findbar.addEventListener("transitionend", function cont(aEvent) {
if (aEvent.propertyName != "visibility") {
return;
}
findbar.removeEventListener("transitionend", cont);
resolve();
});
let close = findbar.getElement("find-closebutton");
close.doCommand();
});
}
function pushPrefs(...aPrefs) {
return new Promise(resolve => {
SpecialPowers.pushPrefEnv({ set: aPrefs }, resolve);
});
}
/**
* Used to check whether the audio unblocking icon is in the tab.
*/
async function waitForTabBlockEvent(tab, expectBlocked) {
if (tab.activeMediaBlocked == expectBlocked) {
ok(true, "The tab should " + (expectBlocked ? "" : "not ") + "be blocked");
} else {
info("Block state doens't match, wait for attributes changes.");
await BrowserTestUtils.waitForEvent(
tab,
"TabAttrModified",
false,
event => {
if (event.detail.changed.includes("activemedia-blocked")) {
is(
tab.activeMediaBlocked,
expectBlocked,
"The tab should " + (expectBlocked ? "" : "not ") + "be blocked"
);
return true;
}
return false;
}
);
}
}
/**
* Used to check whether the tab has soundplaying attribute.
*/
async function waitForTabPlayingEvent(tab, expectPlaying) {
if (tab.soundPlaying == expectPlaying) {
ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
} else {
info("Playing state doesn't match, wait for attributes changes.");
await BrowserTestUtils.waitForEvent(
tab,
"TabAttrModified",
false,
event => {
if (event.detail.changed.includes("soundplaying")) {
is(
tab.soundPlaying,
expectPlaying,
"The tab should " + (expectPlaying ? "" : "not ") + "be playing"
);
return true;
}
return false;
}
);
}
}
function disable_non_test_mouse(disable) {
let utils = window.windowUtils;
utils.disableNonTestMouseEvents(disable);
}
function hover_icon(icon, tooltip) {
disable_non_test_mouse(true);
let popupShownPromise = BrowserTestUtils.waitForEvent(tooltip, "popupshown");
EventUtils.synthesizeMouse(icon, 1, 1, { type: "mouseover" });
EventUtils.synthesizeMouse(icon, 2, 2, { type: "mousemove" });
EventUtils.synthesizeMouse(icon, 3, 3, { type: "mousemove" });
EventUtils.synthesizeMouse(icon, 4, 4, { type: "mousemove" });
return popupShownPromise;
}
function leave_icon(icon) {
EventUtils.synthesizeMouse(icon, 0, 0, { type: "mouseout" });
EventUtils.synthesizeMouseAtCenter(document.documentElement, {
type: "mousemove",
});
EventUtils.synthesizeMouseAtCenter(document.documentElement, {
type: "mousemove",
});
EventUtils.synthesizeMouseAtCenter(document.documentElement, {
type: "mousemove",
});
disable_non_test_mouse(false);
}
/**
* Helper class for testing datetime input picker widget
*/
class DateTimeTestHelper {
constructor() {
this.panel = gBrowser._getAndMaybeCreateDateTimePickerPanel();
this.panel.setAttribute("animate", false);
this.tab = null;
this.frame = null;
}
/**
* Opens a new tab with the URL of the test page, and make sure the picker is
* ready for testing.
*
* @param {String} pageUrl
* @param {bool} inFrame true if input is in the first child frame
* @param {String} openMethod "click" or "showPicker"
*/
async openPicker(pageUrl, inFrame, openMethod = "click") {
this.tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let bc = gBrowser.selectedBrowser;
if (inFrame) {
await SpecialPowers.spawn(bc, [], async function() {
const iframe = content.document.querySelector("iframe");
// Ensure the iframe's position is correct before doing any
// other operations
iframe.getBoundingClientRect();
});
bc = bc.browsingContext.children[0];
}
await SpecialPowers.spawn(bc, [], async function() {
// Ensure that screen coordinates are ok.
await SpecialPowers.contentTransformsReceived(content);
});
if (openMethod === "click") {
await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, bc);
} else if (openMethod === "showPicker") {
await SpecialPowers.spawn(bc, [], function() {
content.document.notifyUserGestureActivation();
content.document.querySelector("input").showPicker();
});
}
this.frame = this.panel.querySelector("#dateTimePopupFrame");
await this.waitForPickerReady();
}
promisePickerClosed() {
return new Promise(resolve => {
this.panel.addEventListener("popuphidden", resolve, { once: true });
});
}
promiseChange(selector = "input") {
return SpecialPowers.spawn(
this.tab.linkedBrowser,
[selector],
async selector => {
let input = content.document.querySelector(selector);
await ContentTaskUtils.waitForEvent(input, "change", false, e => {
ok(
content.window.windowUtils.isHandlingUserInput,
"isHandlingUserInput should be true"
);
return true;
});
}
);
}
async waitForPickerReady() {
let readyPromise;
let loadPromise = new Promise(resolve => {
let listener = () => {
if (
this.frame.browsingContext.currentURI.spec !=
"chrome://global/content/datepicker.xhtml"
) {
return;
}
this.frame.removeEventListener("load", listener, { capture: true });
// Add the PickerReady event listener directly inside the load event
// listener to avoid missing the event.
readyPromise = BrowserTestUtils.waitForEvent(
this.frame.contentDocument,
"PickerReady"
);
resolve();
};
this.frame.addEventListener("load", listener, { capture: true });
});
await loadPromise;
// Wait for picker elements to be ready
await readyPromise;
}
/**
* Find an element on the picker.
*
* @param {String} selector
* @return {DOMElement}
*/
getElement(selector) {
return this.frame.contentDocument.querySelector(selector);
}
/**
* Find the children of an element on the picker.
*
* @param {String} selector
* @return {Array<DOMElement>}
*/
getChildren(selector) {
return Array.from(this.getElement(selector).children);
}
/**
* Click on an element
*
* @param {DOMElement} element
*/
click(element) {
EventUtils.synthesizeMouseAtCenter(element, {}, this.frame.contentWindow);
}
/**
* Close the panel and the tab
*/
async tearDown() {
if (this.panel.state != "closed") {
let pickerClosePromise = this.promisePickerClosed();
this.panel.hidePopup();
await pickerClosePromise;
}
BrowserTestUtils.removeTab(this.tab);
this.tab = null;
}
/**
* Clean up after tests. Remove the frame to prevent leak.
*/
cleanup() {
this.frame.remove();
this.frame = null;
this.panel.removeAttribute("animate");
this.panel = null;
}
}
/**
* Used to listen events if you just need it once
*/
function once(target, name) {
var p = new Promise(function(resolve, reject) {
target.addEventListener(
name,
function() {
resolve();
},
{ once: true }
);
});
return p;
}
/**
* check if current wakelock is equal to expected state, if not, then wait until
* the wakelock changes its state to expected state.
* @param needLock
* the wakolock should be locked or not
* @param isForegroundLock
* when the lock is on, the wakelock should be in the foreground or not
*/
async function waitForExpectedWakeLockState(
topic,
{ needLock, isForegroundLock }
) {
const powerManagerService = Cc["@mozilla.org/power/powermanagerservice;1"];
const powerManager = powerManagerService.getService(
Ci.nsIPowerManagerService
);
const wakelockState = powerManager.getWakeLockState(topic);
let expectedLockState = "unlocked";
if (needLock) {
expectedLockState = isForegroundLock
? "locked-foreground"
: "locked-background";
}
if (wakelockState != expectedLockState) {
info(`wait until wakelock becomes ${expectedLockState}`);
await wakeLockObserved(
powerManager,
topic,
state => state == expectedLockState
);
}
is(
powerManager.getWakeLockState(topic),
expectedLockState,
`the wakelock state for '${topic}' is equal to '${expectedLockState}'`
);
}
function wakeLockObserved(powerManager, observeTopic, checkFn) {
return new Promise(resolve => {
function wakeLockListener() {}
wakeLockListener.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsIDOMMozWakeLockListener"]),
callback(topic, state) {
if (topic == observeTopic && checkFn(state)) {
powerManager.removeWakeLockListener(wakeLockListener.prototype);
resolve();
}
},
};
powerManager.addWakeLockListener(wakeLockListener.prototype);
});
}
function getTestWebBasedURL(fileName, { crossOrigin = false } = {}) {
const origin = crossOrigin ? "http://example.org" : "http://example.com";
return (
getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) +
fileName
);
}