Loading dom/base/nsGlobalWindowOuter.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -5478,6 +5478,14 @@ nsGlobalWindowOuter::RevisePopupAbuseLevel(PopupControlState aControl) abuse = openOverridden; } // If this popup is allowed, let's block any other for this event, forcing // openBlocked state. if ((abuse == openAllowed || abuse == openControlled) && StaticPrefs::dom_block_multiple_popups() && !PopupWhitelisted()) { nsContentUtils::PushPopupControlState(openBlocked, true); } return abuse; } Loading Loading @@ -5514,7 +5522,7 @@ nsGlobalWindowOuter::FireAbuseEvents(const nsAString &aPopupURL, ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), nullptr, baseURL, getter_AddRefs(popupURI)); // fire an event chock full of informative URIs // fire an event block full of informative URIs FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName, aPopupWindowFeatures); } Loading dom/base/test/browser.ini +2 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,5 @@ skip-if = verify [browser_timeout_throttling_with_audio_playback.js] [browser_bug1303838.js] [browser_inputStream_structuredClone.js] [browser_multiple_popups.js] support-files = browser_multiple_popups.html dom/base/test/browser_multiple_popups.html 0 → 100644 +54 −0 Original line number Diff line number Diff line <!DOCTYPE html> <html> <body> <button onclick="openPopups();" id="openPopups">open popups</button> <button onclick="openNestedPopups();" id="openNestedPopups">open tested popups</button> <button onclick="openPopupAndClick();" id="openPopupAndClick">open popups and click</button> <button onclick="closeAllWindows();" id="closeAllWindows">close all windows</button> <input type="text" id="input" /> <script> let windows = []; function openPopups() { windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); } function openNestedPopups() { var w = window.open('empty.html', '_blank', 'width=100,height=100'); windows.push(w); windows.push(w.open('empty.html', '_blank', 'width=100,height=100')); } var recursion = false; function openPopupAndClick() { windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); if (!recursion) { recursion = true; document.getElementById("openPopupAndClick").click(); } } function closeAllWindows() { windows.forEach(w => { try { w.close(); } catch(e) {} }); } if (location.search.includes("openPopups")) { let id = setInterval(() => { if (document.getElementById('start')) { clearInterval(id); openPopups(); } }, 500); } document.getElementById("input").onmouseup = _ => { openPopups(); } </script> </body> </html> dom/base/test/browser_multiple_popups.js 0 → 100644 +362 −0 Original line number Diff line number Diff line /** * In this test, we check that the content can't open more than one popup at a * time (depending on "dom.allow_mulitple_popups" preference value). */ const TEST_DOMAIN = "http://example.net"; const TEST_PATH = "/browser/dom/base/test/"; const CHROME_DOMAIN = "chrome://mochitests/content"; requestLongerTimeout(2); function WindowObserver(count) { return new Promise(resolve => { let windowObserver = function(aSubject, aTopic, aData) { if (aTopic != "domwindowopened") { return; } if (--count == 0) { Services.ww.unregisterNotification(windowObserver); resolve(); } } Services.ww.registerNotification(windowObserver); }); } add_task(async _ => { info("All opened if the pref is off"); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", false], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s in a click event allowed because whitelisted domain."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("2 window.open()s in a mouseup event allowed because whitelisted domain."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("2 window.open()s in a single click event: only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s in a single mouseup event: only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s by non-event code: no windows allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); await ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { let count = 0; content.addEventListener("DOMPopupBlocked", function cb() { if (++count == 2) { content.removeEventListener("DOMPopupBlocked", cb); ok(true, "The popup has been blocked"); resolve(); } }); let p = content.document.createElement("p"); p.setAttribute('id', 'start'); content.document.body.appendChild(p); }); }); ok(true, "We had 0 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s by non-event code allowed by permission"); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let obs = new WindowObserver(2); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("1 window.open() executing another window.open(): only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); // We don't receive DOMPopupBlocked for nested windows. Let's use just the observer. let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openNestedPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("window.open() and .click() on the element opening the window."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopupAndClick", {}, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("All opened from chrome."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, CHROME_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); modules/libpref/init/StaticPrefList.h +7 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,13 @@ VARCACHE_PREF( RelaxedAtomicBool, false ) // Block multiple window.open() per single event. VARCACHE_PREF( "dom.block_multiple_popups", dom_block_multiple_popups, bool, true ) //--------------------------------------------------------------------------- // Clear-Site-Data prefs //--------------------------------------------------------------------------- Loading Loading
dom/base/nsGlobalWindowOuter.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -5478,6 +5478,14 @@ nsGlobalWindowOuter::RevisePopupAbuseLevel(PopupControlState aControl) abuse = openOverridden; } // If this popup is allowed, let's block any other for this event, forcing // openBlocked state. if ((abuse == openAllowed || abuse == openControlled) && StaticPrefs::dom_block_multiple_popups() && !PopupWhitelisted()) { nsContentUtils::PushPopupControlState(openBlocked, true); } return abuse; } Loading Loading @@ -5514,7 +5522,7 @@ nsGlobalWindowOuter::FireAbuseEvents(const nsAString &aPopupURL, ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), nullptr, baseURL, getter_AddRefs(popupURI)); // fire an event chock full of informative URIs // fire an event block full of informative URIs FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName, aPopupWindowFeatures); } Loading
dom/base/test/browser.ini +2 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,5 @@ skip-if = verify [browser_timeout_throttling_with_audio_playback.js] [browser_bug1303838.js] [browser_inputStream_structuredClone.js] [browser_multiple_popups.js] support-files = browser_multiple_popups.html
dom/base/test/browser_multiple_popups.html 0 → 100644 +54 −0 Original line number Diff line number Diff line <!DOCTYPE html> <html> <body> <button onclick="openPopups();" id="openPopups">open popups</button> <button onclick="openNestedPopups();" id="openNestedPopups">open tested popups</button> <button onclick="openPopupAndClick();" id="openPopupAndClick">open popups and click</button> <button onclick="closeAllWindows();" id="closeAllWindows">close all windows</button> <input type="text" id="input" /> <script> let windows = []; function openPopups() { windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); } function openNestedPopups() { var w = window.open('empty.html', '_blank', 'width=100,height=100'); windows.push(w); windows.push(w.open('empty.html', '_blank', 'width=100,height=100')); } var recursion = false; function openPopupAndClick() { windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); if (!recursion) { recursion = true; document.getElementById("openPopupAndClick").click(); } } function closeAllWindows() { windows.forEach(w => { try { w.close(); } catch(e) {} }); } if (location.search.includes("openPopups")) { let id = setInterval(() => { if (document.getElementById('start')) { clearInterval(id); openPopups(); } }, 500); } document.getElementById("input").onmouseup = _ => { openPopups(); } </script> </body> </html>
dom/base/test/browser_multiple_popups.js 0 → 100644 +362 −0 Original line number Diff line number Diff line /** * In this test, we check that the content can't open more than one popup at a * time (depending on "dom.allow_mulitple_popups" preference value). */ const TEST_DOMAIN = "http://example.net"; const TEST_PATH = "/browser/dom/base/test/"; const CHROME_DOMAIN = "chrome://mochitests/content"; requestLongerTimeout(2); function WindowObserver(count) { return new Promise(resolve => { let windowObserver = function(aSubject, aTopic, aData) { if (aTopic != "domwindowopened") { return; } if (--count == 0) { Services.ww.unregisterNotification(windowObserver); resolve(); } } Services.ww.registerNotification(windowObserver); }); } add_task(async _ => { info("All opened if the pref is off"); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", false], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s in a click event allowed because whitelisted domain."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("2 window.open()s in a mouseup event allowed because whitelisted domain."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("2 window.open()s in a single click event: only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s in a single mouseup event: only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s by non-event code: no windows allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); await ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { let count = 0; content.addEventListener("DOMPopupBlocked", function cb() { if (++count == 2) { content.removeEventListener("DOMPopupBlocked", cb); ok(true, "The popup has been blocked"); resolve(); } }); let p = content.document.createElement("p"); p.setAttribute('id', 'start'); content.document.body.appendChild(p); }); }); ok(true, "We had 0 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("2 window.open()s by non-event code allowed by permission"); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); const uri = Services.io.newURI(TEST_DOMAIN); const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); let obs = new WindowObserver(2); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); await new Promise(aResolve => { Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { Assert.equal(value, 0); aResolve(); }); }); }); add_task(async _ => { info("1 window.open() executing another window.open(): only the first one is allowed."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); // We don't receive DOMPopupBlocked for nested windows. Let's use just the observer. let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openNestedPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("window.open() and .click() on the element opening the window."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let p = ContentTask.spawn(browser, null, () => { return new content.Promise(resolve => { content.addEventListener("DOMPopupBlocked", () => { ok(true, "The popup has been blocked"); resolve(); }, {once:true}); }); }); let obs = new WindowObserver(1); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopupAndClick", {}, tab.linkedBrowser); await p; await obs; ok(true, "We had only 1 window."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); }); add_task(async _ => { info("All opened from chrome."); await SpecialPowers.pushPrefEnv({"set": [ ["dom.block_multiple_popups", true], ["dom.disable_open_during_load", true], ]}); let tab = BrowserTestUtils.addTab(gBrowser, CHROME_DOMAIN + TEST_PATH + "browser_multiple_popups.html") gBrowser.selectedTab = tab; let browser = gBrowser.getBrowserForTab(tab); await BrowserTestUtils.browserLoaded(browser); let obs = new WindowObserver(2); await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); await obs; ok(true, "We had 2 windows."); await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); BrowserTestUtils.removeTab(tab); });
modules/libpref/init/StaticPrefList.h +7 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,13 @@ VARCACHE_PREF( RelaxedAtomicBool, false ) // Block multiple window.open() per single event. VARCACHE_PREF( "dom.block_multiple_popups", dom_block_multiple_popups, bool, true ) //--------------------------------------------------------------------------- // Clear-Site-Data prefs //--------------------------------------------------------------------------- Loading