head.js (5105B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 ChromeUtils.defineESModuleGetters(this, { 5 EnterprisePolicyTesting: 6 "resource://testing-common/EnterprisePolicyTesting.sys.mjs", 7 ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs", 8 PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", 9 TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs", 10 sinon: "resource://testing-common/Sinon.sys.mjs", 11 }); 12 13 async function promisePageActionPanelOpen(win = window, eventDict = {}) { 14 await BrowserTestUtils.waitForCondition(() => { 15 // Wait for the main page action button to become visible. It's hidden for 16 // some URIs, so depending on when this is called, it may not yet be quite 17 // visible. It's up to the caller to make sure it will be visible. 18 info("Waiting for main page action button to have non-0 size"); 19 let bounds = win.windowUtils.getBoundsWithoutFlushing( 20 win.BrowserPageActions.mainButtonNode 21 ); 22 return bounds.width > 0 && bounds.height > 0; 23 }); 24 25 // Wait for the panel to become open, by clicking the button if necessary. 26 info("Waiting for main page action panel to be open"); 27 if (win.BrowserPageActions.panelNode.state == "open") { 28 return; 29 } 30 let shownPromise = promisePageActionPanelShown(win); 31 EventUtils.synthesizeMouseAtCenter( 32 win.BrowserPageActions.mainButtonNode, 33 eventDict, 34 win 35 ); 36 await shownPromise; 37 info("Wait for items in the panel to become visible."); 38 await promisePageActionViewChildrenVisible( 39 win.BrowserPageActions.mainViewNode, 40 win 41 ); 42 } 43 44 function promisePageActionPanelShown(win = window) { 45 return promisePanelShown(win.BrowserPageActions.panelNode, win); 46 } 47 48 function promisePageActionPanelHidden(win = window) { 49 return promisePanelHidden(win.BrowserPageActions.panelNode, win); 50 } 51 52 function promisePanelShown(panelIDOrNode, win = window) { 53 return promisePanelEvent(panelIDOrNode, "popupshown", win); 54 } 55 56 function promisePanelHidden(panelIDOrNode, win = window) { 57 return promisePanelEvent(panelIDOrNode, "popuphidden", win); 58 } 59 60 function promisePanelEvent(panelIDOrNode, eventType, win = window) { 61 return new Promise(resolve => { 62 let panel = panelIDOrNode; 63 if (typeof panel == "string") { 64 panel = win.document.getElementById(panelIDOrNode); 65 if (!panel) { 66 throw new Error(`Panel with ID "${panelIDOrNode}" does not exist.`); 67 } 68 } 69 if ( 70 (eventType == "popupshown" && panel.state == "open") || 71 (eventType == "popuphidden" && panel.state == "closed") 72 ) { 73 executeSoon(() => resolve(panel)); 74 return; 75 } 76 panel.addEventListener( 77 eventType, 78 () => { 79 executeSoon(() => resolve(panel)); 80 }, 81 { once: true } 82 ); 83 }); 84 } 85 86 async function promisePageActionViewChildrenVisible( 87 panelViewNode, 88 win = window 89 ) { 90 info( 91 "promisePageActionViewChildrenVisible waiting for a child node to be visible" 92 ); 93 await new Promise(win.requestAnimationFrame); 94 let dwu = win.windowUtils; 95 return TestUtils.waitForCondition(() => { 96 let bodyNode = panelViewNode.firstElementChild; 97 for (let childNode of bodyNode.children) { 98 let bounds = dwu.getBoundsWithoutFlushing(childNode); 99 if (bounds.width > 0 && bounds.height > 0) { 100 return true; 101 } 102 } 103 return false; 104 }); 105 } 106 107 function promiseAddonUninstalled(addonId) { 108 return new Promise(resolve => { 109 let listener = {}; 110 listener.onUninstalled = addon => { 111 if (addon.id == addonId) { 112 AddonManager.removeAddonListener(listener); 113 resolve(); 114 } 115 }; 116 AddonManager.addAddonListener(listener); 117 }); 118 } 119 120 async function promiseAnimationFrame(win = window) { 121 await new Promise(resolve => win.requestAnimationFrame(resolve)); 122 await win.promiseDocumentFlushed(() => {}); 123 } 124 125 async function promisePopupNotShown(id, win = window) { 126 let deferred = Promise.withResolvers(); 127 function listener() { 128 deferred.reject("Unexpected popupshown"); 129 } 130 let panel = win.document.getElementById(id); 131 panel.addEventListener("popupshown", listener); 132 try { 133 await Promise.race([ 134 deferred.promise, 135 new Promise(resolve => { 136 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 137 win.setTimeout(resolve, 300); 138 }), 139 ]); 140 } finally { 141 panel.removeEventListener("popupshown", listener); 142 } 143 } 144 145 // TODO (Bug 1700780): Why is this necessary? Without this trick the test 146 // fails intermittently on Ubuntu. 147 function promiseStableResize(expectedWidth, win = window) { 148 let deferred = Promise.withResolvers(); 149 let id; 150 function listener() { 151 win.clearTimeout(id); 152 info(`Got resize event: ${win.innerWidth} x ${win.innerHeight}`); 153 if (win.innerWidth <= expectedWidth) { 154 id = win.setTimeout(() => { 155 win.removeEventListener("resize", listener); 156 deferred.resolve(); 157 }, 100); 158 } 159 } 160 win.addEventListener("resize", listener); 161 win.resizeTo(expectedWidth, win.outerHeight); 162 return deferred.promise; 163 }