head.js (7572B)
1 ChromeUtils.defineESModuleGetters(this, { 2 AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", 3 PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", 4 PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", 5 TabCrashHandler: "resource:///modules/ContentCrashHandlers.sys.mjs", 6 }); 7 8 /** 9 * Wait for a <notification> to be closed then call the specified callback. 10 */ 11 function waitForNotificationClose(notification, cb) { 12 let observer = new MutationObserver(function onMutatations(mutations) { 13 for (let mutation of mutations) { 14 for (let i = 0; i < mutation.removedNodes.length; i++) { 15 let node = mutation.removedNodes.item(i); 16 if (node != notification) { 17 continue; 18 } 19 observer.disconnect(); 20 cb(); 21 } 22 } 23 }); 24 observer.observe(notification.control.stack, { childList: true }); 25 } 26 27 function closeAllNotifications() { 28 if (!gNotificationBox.currentNotification) { 29 return Promise.resolve(); 30 } 31 32 return new Promise(resolve => { 33 for (let notification of gNotificationBox.allNotifications) { 34 waitForNotificationClose(notification, function () { 35 if (gNotificationBox.allNotifications.length === 0) { 36 resolve(); 37 } 38 }); 39 notification.close(); 40 } 41 }); 42 } 43 44 function whenDelayedStartupFinished(aWindow, aCallback) { 45 Services.obs.addObserver(function observer(aSubject, aTopic) { 46 if (aWindow == aSubject) { 47 Services.obs.removeObserver(observer, aTopic); 48 executeSoon(aCallback); 49 } 50 }, "browser-delayed-startup-finished"); 51 } 52 53 function openToolbarCustomizationUI(aCallback, aBrowserWin) { 54 if (!aBrowserWin) { 55 aBrowserWin = window; 56 } 57 58 aBrowserWin.gCustomizeMode.enter(); 59 60 aBrowserWin.gNavToolbox.addEventListener( 61 "customizationready", 62 function () { 63 executeSoon(function () { 64 aCallback(aBrowserWin); 65 }); 66 }, 67 { once: true } 68 ); 69 } 70 71 function closeToolbarCustomizationUI(aCallback, aBrowserWin) { 72 aBrowserWin.gNavToolbox.addEventListener( 73 "aftercustomization", 74 function () { 75 executeSoon(aCallback); 76 }, 77 { once: true } 78 ); 79 80 aBrowserWin.gCustomizeMode.exit(); 81 } 82 83 function waitForCondition(condition, nextTest, errorMsg, retryTimes) { 84 retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30; 85 var tries = 0; 86 var interval = setInterval(function () { 87 if (tries >= retryTimes) { 88 ok(false, errorMsg); 89 moveOn(); 90 } 91 var conditionPassed; 92 try { 93 conditionPassed = condition(); 94 } catch (e) { 95 ok(false, e + "\n" + e.stack); 96 conditionPassed = false; 97 } 98 if (conditionPassed) { 99 moveOn(); 100 } 101 tries++; 102 }, 100); 103 var moveOn = function () { 104 clearInterval(interval); 105 nextTest(); 106 }; 107 } 108 109 function promiseWaitForCondition(aConditionFn) { 110 return new Promise(resolve => { 111 waitForCondition(aConditionFn, resolve, "Condition didn't pass."); 112 }); 113 } 114 115 function promiseWaitForEvent( 116 object, 117 eventName, 118 capturing = false, 119 chrome = false 120 ) { 121 return new Promise(resolve => { 122 function listener(event) { 123 info("Saw " + eventName); 124 object.removeEventListener(eventName, listener, capturing, chrome); 125 resolve(event); 126 } 127 128 info("Waiting for " + eventName); 129 object.addEventListener(eventName, listener, capturing, chrome); 130 }); 131 } 132 133 /** 134 * Allows setting focus on a window, and waiting for that window to achieve 135 * focus. 136 * 137 * @param aWindow 138 * The window to focus and wait for. 139 * 140 * @returns {Promise<void>} 141 * Resolved when the window is focused. 142 */ 143 function promiseWaitForFocus(aWindow) { 144 return new Promise(resolve => { 145 waitForFocus(resolve, aWindow); 146 }); 147 } 148 149 function pushPrefs(...aPrefs) { 150 return SpecialPowers.pushPrefEnv({ set: aPrefs }); 151 } 152 153 function popPrefs() { 154 return SpecialPowers.popPrefEnv(); 155 } 156 157 function promiseWindowClosed(win) { 158 let promise = BrowserTestUtils.domWindowClosed(win); 159 win.close(); 160 return promise; 161 } 162 163 async function whenNewTabLoaded(aWindow, aCallback) { 164 aWindow.BrowserCommands.openTab(); 165 166 let expectedURL = AboutNewTab.newTabURL; 167 let browser = aWindow.gBrowser.selectedBrowser; 168 let loadPromise = BrowserTestUtils.browserLoaded(browser, false, expectedURL); 169 let alreadyLoaded = await SpecialPowers.spawn(browser, [expectedURL], url => { 170 let doc = content.document; 171 return doc && doc.readyState === "complete" && doc.location.href == url; 172 }); 173 if (!alreadyLoaded) { 174 await loadPromise; 175 } 176 aCallback(); 177 } 178 179 function is_hidden(element) { 180 var style = element.ownerGlobal.getComputedStyle(element); 181 if (style.display == "none") { 182 return true; 183 } 184 if (style.visibility != "visible") { 185 return true; 186 } 187 if (XULPopupElement.isInstance(element)) { 188 return ["hiding", "closed"].includes(element.state); 189 } 190 191 // Hiding a parent element will hide all its children 192 if (element.parentNode != element.ownerDocument) { 193 return is_hidden(element.parentNode); 194 } 195 196 return false; 197 } 198 199 function is_element_visible(element, msg) { 200 isnot(element, null, "Element should not be null, when checking visibility"); 201 ok(BrowserTestUtils.isVisible(element), msg || "Element should be visible"); 202 } 203 204 function is_element_hidden(element, msg) { 205 isnot(element, null, "Element should not be null, when checking visibility"); 206 ok(is_hidden(element), msg || "Element should be hidden"); 207 } 208 209 function promisePopupShown(popup) { 210 return BrowserTestUtils.waitForPopupEvent(popup, "shown"); 211 } 212 213 function promisePopupHidden(popup) { 214 return BrowserTestUtils.waitForPopupEvent(popup, "hidden"); 215 } 216 217 function promiseNotificationShown(notification) { 218 let win = notification.browser.ownerGlobal; 219 if (win.PopupNotifications.panel.state == "open") { 220 return Promise.resolve(); 221 } 222 let panelPromise = promisePopupShown(win.PopupNotifications.panel); 223 notification.reshow(); 224 return panelPromise; 225 } 226 227 /** 228 * Resolves when a bookmark with the given uri is added. 229 */ 230 function promiseOnBookmarkItemAdded(aExpectedURI) { 231 return new Promise((resolve, reject) => { 232 let listener = events => { 233 is(events.length, 1, "Should only receive one event."); 234 info("Added a bookmark to " + events[0].url); 235 PlacesUtils.observers.removeListener(["bookmark-added"], listener); 236 if (events[0].url == aExpectedURI.spec) { 237 resolve(); 238 } else { 239 reject(new Error("Added an unexpected bookmark")); 240 } 241 }; 242 info("Waiting for a bookmark to be added"); 243 PlacesUtils.observers.addListener(["bookmark-added"], listener); 244 }); 245 } 246 247 async function loadBadCertPage(url, feltPrivacy = false) { 248 let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser); 249 BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url); 250 await loaded; 251 252 await SpecialPowers.spawn( 253 gBrowser.selectedBrowser, 254 [feltPrivacy], 255 async isFeltPrivacy => { 256 if (isFeltPrivacy) { 257 let netErrorCard = 258 content.document.querySelector("net-error-card").wrappedJSObject; 259 await netErrorCard.getUpdateComplete(); 260 netErrorCard.advancedButton.click(); 261 await ContentTaskUtils.waitForCondition(() => { 262 return ( 263 netErrorCard.exceptionButton && 264 !netErrorCard.exceptionButton.disabled 265 ); 266 }, "Waiting for exception button"); 267 netErrorCard.exceptionButton.click(); 268 } else { 269 content.document.getElementById("exceptionDialogButton").click(); 270 } 271 } 272 ); 273 await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); 274 }