/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ ChromeUtils.defineESModuleGetters(this, { EnterprisePolicyTesting: "resource://testing-common/EnterprisePolicyTesting.sys.mjs", ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs", PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs", sinon: "resource://testing-common/Sinon.sys.mjs", }); async function promisePageActionPanelOpen(win = window, eventDict = {}) { await BrowserTestUtils.waitForCondition(() => { // Wait for the main page action button to become visible. It's hidden for // some URIs, so depending on when this is called, it may not yet be quite // visible. It's up to the caller to make sure it will be visible. info("Waiting for main page action button to have non-0 size"); let bounds = win.windowUtils.getBoundsWithoutFlushing( win.BrowserPageActions.mainButtonNode ); return bounds.width > 0 && bounds.height > 0; }); // Wait for the panel to become open, by clicking the button if necessary. info("Waiting for main page action panel to be open"); if (win.BrowserPageActions.panelNode.state == "open") { return; } let shownPromise = promisePageActionPanelShown(win); EventUtils.synthesizeMouseAtCenter( win.BrowserPageActions.mainButtonNode, eventDict, win ); await shownPromise; info("Wait for items in the panel to become visible."); await promisePageActionViewChildrenVisible( win.BrowserPageActions.mainViewNode, win ); } function promisePageActionPanelShown(win = window) { return promisePanelShown(win.BrowserPageActions.panelNode, win); } function promisePageActionPanelHidden(win = window) { return promisePanelHidden(win.BrowserPageActions.panelNode, win); } function promisePanelShown(panelIDOrNode, win = window) { return promisePanelEvent(panelIDOrNode, "popupshown", win); } function promisePanelHidden(panelIDOrNode, win = window) { return promisePanelEvent(panelIDOrNode, "popuphidden", win); } function promisePanelEvent(panelIDOrNode, eventType, win = window) { return new Promise(resolve => { let panel = panelIDOrNode; if (typeof panel == "string") { panel = win.document.getElementById(panelIDOrNode); if (!panel) { throw new Error(`Panel with ID "${panelIDOrNode}" does not exist.`); } } if ( (eventType == "popupshown" && panel.state == "open") || (eventType == "popuphidden" && panel.state == "closed") ) { executeSoon(() => resolve(panel)); return; } panel.addEventListener( eventType, () => { executeSoon(() => resolve(panel)); }, { once: true } ); }); } async function promisePageActionViewChildrenVisible( panelViewNode, win = window ) { info( "promisePageActionViewChildrenVisible waiting for a child node to be visible" ); await new Promise(win.requestAnimationFrame); let dwu = win.windowUtils; return TestUtils.waitForCondition(() => { let bodyNode = panelViewNode.firstElementChild; for (let childNode of bodyNode.children) { let bounds = dwu.getBoundsWithoutFlushing(childNode); if (bounds.width > 0 && bounds.height > 0) { return true; } } return false; }); } function promiseAddonUninstalled(addonId) { return new Promise(resolve => { let listener = {}; listener.onUninstalled = addon => { if (addon.id == addonId) { AddonManager.removeAddonListener(listener); resolve(); } }; AddonManager.addAddonListener(listener); }); } async function promiseAnimationFrame(win = window) { await new Promise(resolve => win.requestAnimationFrame(resolve)); await win.promiseDocumentFlushed(() => {}); } async function promisePopupNotShown(id, win = window) { let deferred = PromiseUtils.defer(); function listener(e) { deferred.reject("Unexpected popupshown"); } let panel = win.document.getElementById(id); panel.addEventListener("popupshown", listener); try { await Promise.race([ deferred.promise, new Promise(resolve => { /* eslint-disable mozilla/no-arbitrary-setTimeout */ win.setTimeout(resolve, 300); }), ]); } finally { panel.removeEventListener("popupshown", listener); } } // TODO (Bug 1700780): Why is this necessary? Without this trick the test // fails intermittently on Ubuntu. function promiseStableResize(expectedWidth, win = window) { let deferred = PromiseUtils.defer(); let id; function listener() { win.clearTimeout(id); info(`Got resize event: ${win.innerWidth} x ${win.innerHeight}`); if (win.innerWidth <= expectedWidth) { id = win.setTimeout(() => { win.removeEventListener("resize", listener); deferred.resolve(); }, 100); } } win.addEventListener("resize", listener); win.resizeTo(expectedWidth, win.outerHeight); return deferred.promise; }