browser_multiple_popups.js (7254B)
1 /** 2 * In this test, we check that the content can't open more than one popup at a 3 * time (depending on "dom.allow_mulitple_popups" preference value). 4 */ 5 6 const TEST_DOMAIN = "https://example.net"; 7 const TEST_PATH = "/browser/dom/base/test/"; 8 const CHROME_DOMAIN = "chrome://mochitests/content"; 9 10 requestLongerTimeout(2); 11 12 function promisePopups(count) { 13 let windows = []; 14 return new Promise(resolve => { 15 if (count == 0) { 16 resolve([]); 17 return; 18 } 19 20 let windowObserver = function (aSubject, aTopic, aData) { 21 if (aTopic != "domwindowopened") { 22 return; 23 } 24 windows.push(aSubject); 25 if (--count == 0) { 26 Services.ww.unregisterNotification(windowObserver); 27 SimpleTest.executeSoon(() => resolve(windows)); 28 } 29 }; 30 Services.ww.registerNotification(windowObserver); 31 }); 32 } 33 34 async function withTestPage(popupCount, optionsOrCallback, callback) { 35 let options = optionsOrCallback; 36 if (!callback) { 37 callback = optionsOrCallback; 38 options = {}; 39 } 40 41 await SpecialPowers.pushPrefEnv({ 42 set: [ 43 // Enable popup blocker 44 ["dom.disable_open_during_load", true], 45 ], 46 }); 47 48 let domain = options.chrome ? CHROME_DOMAIN : TEST_DOMAIN; 49 let tab = BrowserTestUtils.addTab( 50 gBrowser, 51 domain + TEST_PATH + "browser_multiple_popups.html" + (options.query || "") 52 ); 53 gBrowser.selectedTab = tab; 54 55 let browser = gBrowser.getBrowserForTab(tab); 56 await BrowserTestUtils.browserLoaded(browser); 57 58 let obs = promisePopups(popupCount); 59 60 await callback(browser); 61 62 let windows = await obs; 63 ok(true, `We had ${popupCount} windows.`); 64 for (let win of windows) { 65 // wait for browser.xhtml being loaded to prevent shutdown hang 66 if ( 67 win.document.readyState !== "complete" || 68 win.location.href == "about:blank" 69 ) { 70 await BrowserTestUtils.waitForEvent(win, "load"); 71 } 72 await BrowserTestUtils.closeWindow(win); 73 } 74 BrowserTestUtils.removeTab(tab); 75 } 76 77 function promisePopupsBlocked(browser, expectedCount) { 78 return SpecialPowers.spawn(browser, [expectedCount], count => { 79 return new content.Promise(resolve => { 80 content.addEventListener("DOMPopupBlocked", function cb() { 81 if (--count == 0) { 82 content.removeEventListener("DOMPopupBlocked", cb); 83 ok(true, "The popup has been blocked"); 84 resolve(); 85 } 86 }); 87 }); 88 }); 89 } 90 91 function startOpeningTwoPopups(browser) { 92 return SpecialPowers.spawn(browser.browsingContext, [], () => { 93 let p = content.document.createElement("p"); 94 p.setAttribute("id", "start"); 95 content.document.body.appendChild(p); 96 }); 97 } 98 99 add_task(async _ => { 100 info("2 window.open()s in a click event allowed because whitelisted domain."); 101 102 const uri = Services.io.newURI(TEST_DOMAIN); 103 const principal = Services.scriptSecurityManager.createContentPrincipal( 104 uri, 105 {} 106 ); 107 108 Services.perms.addFromPrincipal( 109 principal, 110 "popup", 111 Services.perms.ALLOW_ACTION 112 ); 113 114 await withTestPage(2, async function (browser) { 115 await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, browser); 116 }); 117 118 await new Promise(resolve => { 119 Services.clearData.deleteData( 120 Ci.nsIClearDataService.CLEAR_PERMISSIONS, 121 value => { 122 Assert.equal(value, 0); 123 resolve(); 124 } 125 ); 126 }); 127 }); 128 129 add_task(async _ => { 130 info( 131 "2 window.open()s in a mouseup event allowed because whitelisted domain." 132 ); 133 134 const uri = Services.io.newURI(TEST_DOMAIN); 135 const principal = Services.scriptSecurityManager.createContentPrincipal( 136 uri, 137 {} 138 ); 139 140 Services.perms.addFromPrincipal( 141 principal, 142 "popup", 143 Services.perms.ALLOW_ACTION 144 ); 145 146 await withTestPage(2, async function (browser) { 147 await BrowserTestUtils.synthesizeMouseAtCenter("#input", {}, browser); 148 }); 149 150 await new Promise(aResolve => { 151 Services.clearData.deleteData( 152 Ci.nsIClearDataService.CLEAR_PERMISSIONS, 153 value => { 154 Assert.equal(value, 0); 155 aResolve(); 156 } 157 ); 158 }); 159 }); 160 161 add_task(async _ => { 162 info( 163 "2 window.open()s in a single click event: only the first one is allowed." 164 ); 165 166 await withTestPage(1, async function (browser) { 167 let p = promisePopupsBlocked(browser, 1); 168 await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, browser); 169 await p; 170 }); 171 }); 172 173 add_task(async _ => { 174 info( 175 "2 window.open()s in a single mouseup event: only the first one is allowed." 176 ); 177 178 await withTestPage(1, async function (browser) { 179 let p = promisePopupsBlocked(browser, 1); 180 await BrowserTestUtils.synthesizeMouseAtCenter("#input", {}, browser); 181 await p; 182 }); 183 }); 184 185 add_task(async _ => { 186 info("2 window.open()s by non-event code: no windows allowed."); 187 188 await withTestPage(0, { query: "?openPopups" }, async function (browser) { 189 let p = promisePopupsBlocked(browser, 2); 190 await startOpeningTwoPopups(browser); 191 await p; 192 }); 193 }); 194 195 add_task(async _ => { 196 info("2 window.open()s by non-event code allowed by permission"); 197 const uri = Services.io.newURI(TEST_DOMAIN); 198 const principal = Services.scriptSecurityManager.createContentPrincipal( 199 uri, 200 {} 201 ); 202 203 Services.perms.addFromPrincipal( 204 principal, 205 "popup", 206 Services.perms.ALLOW_ACTION 207 ); 208 209 await withTestPage(2, { query: "?openPopups" }, async function (browser) { 210 await startOpeningTwoPopups(browser); 211 }); 212 213 await new Promise(aResolve => { 214 Services.clearData.deleteData( 215 Ci.nsIClearDataService.CLEAR_PERMISSIONS, 216 value => { 217 Assert.equal(value, 0); 218 aResolve(); 219 } 220 ); 221 }); 222 }); 223 224 add_task(async _ => { 225 info( 226 "1 window.open() executing another window.open(): only the first one is allowed." 227 ); 228 229 await withTestPage(1, async function (browser) { 230 await BrowserTestUtils.synthesizeMouseAtCenter( 231 "#openNestedPopups", 232 {}, 233 browser 234 ); 235 }); 236 }); 237 238 add_task(async _ => { 239 info("window.open() and .click() on the element opening the window."); 240 241 await withTestPage(1, async function (browser) { 242 let p = promisePopupsBlocked(browser, 1); 243 244 await BrowserTestUtils.synthesizeMouseAtCenter( 245 "#openPopupAndClick", 246 {}, 247 browser 248 ); 249 250 await p; 251 }); 252 }); 253 254 add_task(async _ => { 255 info("All opened from chrome."); 256 await withTestPage(2, { chrome: true }, async function (browser) { 257 await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, browser); 258 }); 259 }); 260 261 add_task(async function test_bug_1685056() { 262 info( 263 "window.open() from a blank iframe window during an event dispatched at the parent page: window should be allowed" 264 ); 265 266 await withTestPage(1, async function (browser) { 267 await BrowserTestUtils.synthesizeMouseAtCenter( 268 "#openPopupInFrame", 269 {}, 270 browser 271 ); 272 }); 273 }); 274 275 add_task(async function test_bug_1689853() { 276 info("window.open() from a js bookmark (LOAD_FLAGS_ALLOW_POPUPS)"); 277 await withTestPage(1, async function (browser) { 278 const URI = 279 "javascript:void(window.open('empty.html', '_blank', 'width=100,height=100'));"; 280 window.openTrustedLinkIn(URI, "current", { 281 allowPopups: true, 282 inBackground: false, 283 allowInheritPrincipal: true, 284 }); 285 }); 286 });