diff options
Diffstat (limited to 'browser/base/content/test/popups')
16 files changed, 1154 insertions, 0 deletions
diff --git a/browser/base/content/test/popups/.eslintrc.js b/browser/base/content/test/popups/.eslintrc.js new file mode 100644 index 0000000000..1779fd7f1c --- /dev/null +++ b/browser/base/content/test/popups/.eslintrc.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + extends: ["plugin:mozilla/browser-test"], +}; diff --git a/browser/base/content/test/popups/browser.ini b/browser/base/content/test/popups/browser.ini new file mode 100644 index 0000000000..aba7cf6695 --- /dev/null +++ b/browser/base/content/test/popups/browser.ini @@ -0,0 +1,33 @@ +[DEFAULT] +support-files = + head.js +[browser_popupUI.js] +[browser_popup_blocker.js] +support-files = + popup_blocker.html + popup_blocker_a.html + popup_blocker_b.html + popup_blocker_10_popups.html +skip-if = (os == 'linux') || (e10s && debug) # Frequent bug 1081925 and bug 1125520 failures +[browser_popup_frames.js] +support-files = + popup_blocker.html + popup_blocker_a.html + popup_blocker_b.html +[browser_popup_blocker_identity_block.js] +support-files = + popup_blocker2.html + popup_blocker_a.html +[browser_popup_close_main_window.js] +[browser_popup_blocker_frames.js] +support-files = + popup_blocker.html + popup_blocker_a.html + popup_blocker_b.html +[browser_popup_blocker_iframes.js] +support-files = + popup_blocker.html + popup_blocker_frame.html + popup_blocker_a.html + popup_blocker_b.html +skip-if = debug # This test triggers Bug 1578794 due to opening many popups. diff --git a/browser/base/content/test/popups/browser_popupUI.js b/browser/base/content/test/popups/browser_popupUI.js new file mode 100644 index 0000000000..6b65cee57a --- /dev/null +++ b/browser/base/content/test/popups/browser_popupUI.js @@ -0,0 +1,192 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +add_task(async function toolbar_ui_visibility() { + SpecialPowers.pushPrefEnv({ set: [["dom.disable_open_during_load", false]] }); + + let popupOpened = BrowserTestUtils.waitForNewWindow({ url: "about:blank" }); + BrowserTestUtils.openNewForegroundTab( + gBrowser, + "data:text/html,<html><script>popup=open('about:blank','','width=300,height=200')</script>" + ); + const win = await popupOpened; + const doc = win.document; + + ok(win.gURLBar, "location bar exists in the popup"); + isnot(win.gURLBar.clientWidth, 0, "location bar is visible in the popup"); + ok(win.gURLBar.readOnly, "location bar is read-only in the popup"); + isnot( + doc.getElementById("Browser:OpenLocation").getAttribute("disabled"), + "true", + "'open location' command is not disabled in the popup" + ); + + EventUtils.synthesizeKey("t", { accelKey: true }, win); + is( + win.gBrowser.browsers.length, + 1, + "Accel+T doesn't open a new tab in the popup" + ); + is( + gBrowser.browsers.length, + 3, + "Accel+T opened a new tab in the parent window" + ); + gBrowser.removeCurrentTab(); + + EventUtils.synthesizeKey("w", { accelKey: true }, win); + ok(win.closed, "Accel+W closes the popup"); + + if (!win.closed) { + win.close(); + } + gBrowser.removeCurrentTab(); +}); + +add_task(async function titlebar_buttons_visibility() { + if (!navigator.platform.startsWith("Win")) { + ok(true, "Testing only on Windows"); + return; + } + + const BUTTONS_MAY_VISIBLE = true; + const BUTTONS_NEVER_VISIBLE = false; + + // Always open a new window. + // With default behavior, it opens a new tab, that doesn't affect button + // visibility at all. + Services.prefs.setIntPref("browser.link.open_newwindow", 2); + + const drawInTitlebarValues = [ + [true, BUTTONS_MAY_VISIBLE], + [false, BUTTONS_NEVER_VISIBLE], + ]; + const windowFeaturesValues = [ + // Opens a popup + ["width=300,height=100", BUTTONS_NEVER_VISIBLE], + ["toolbar", BUTTONS_NEVER_VISIBLE], + ["menubar", BUTTONS_NEVER_VISIBLE], + ["menubar,toolbar", BUTTONS_NEVER_VISIBLE], + + // Opens a new window + ["", BUTTONS_MAY_VISIBLE], + ]; + const menuBarShownValues = [true, false]; + + for (const [drawInTitlebar, drawInTitlebarButtons] of drawInTitlebarValues) { + Services.prefs.setBoolPref("browser.tabs.drawInTitlebar", drawInTitlebar); + + for (const [ + windowFeatures, + windowFeaturesButtons, + ] of windowFeaturesValues) { + for (const menuBarShown of menuBarShownValues) { + CustomizableUI.setToolbarVisibility("toolbar-menubar", menuBarShown); + + const popupPromise = BrowserTestUtils.waitForNewWindow("about:blank"); + BrowserTestUtils.openNewForegroundTab( + gBrowser, + `data:text/html;charset=UTF-8,<html><script>window.open("about:blank","","${windowFeatures}")</script>` + ); + const popupWin = await popupPromise; + + const menubar = popupWin.document.querySelector("#toolbar-menubar"); + const menubarIsShown = + menubar.getAttribute("autohide") != "true" || + menubar.getAttribute("inactive") != "true"; + const buttonsInMenubar = menubar.querySelector( + ".titlebar-buttonbox-container" + ); + const buttonsInMenubarShown = + menubarIsShown && + popupWin.getComputedStyle(buttonsInMenubar).display != "none"; + + const buttonsInTabbar = popupWin.document.querySelector( + "#TabsToolbar .titlebar-buttonbox-container" + ); + const buttonsInTabbarShown = + popupWin.getComputedStyle(buttonsInTabbar).display != "none"; + + const params = `drawInTitlebar=${drawInTitlebar}, windowFeatures=${windowFeatures}, menuBarShown=${menuBarShown}`; + if ( + drawInTitlebarButtons == BUTTONS_MAY_VISIBLE && + windowFeaturesButtons == BUTTONS_MAY_VISIBLE + ) { + ok( + buttonsInMenubarShown || buttonsInTabbarShown, + `Titlebar buttons should be visible: ${params}` + ); + } else { + ok( + !buttonsInMenubarShown, + `Titlebar buttons should not be visible: ${params}` + ); + ok( + !buttonsInTabbarShown, + `Titlebar buttons should not be visible: ${params}` + ); + } + + const closedPopupPromise = BrowserTestUtils.windowClosed(popupWin); + popupWin.close(); + await closedPopupPromise; + gBrowser.removeCurrentTab(); + } + } + } + + CustomizableUI.setToolbarVisibility("toolbar-menubar", false); + Services.prefs.clearUserPref("browser.tabs.drawInTitlebar"); + Services.prefs.clearUserPref("browser.link.open_newwindow"); +}); + +// Test only `visibility` rule here, to verify bug 1636229 fix. +// Other styles and ancestors can be different for each OS. +function isVisible(element) { + const style = element.ownerGlobal.getComputedStyle(element); + return style.visibility == "visible"; +} + +async function testTabBarVisibility() { + SpecialPowers.pushPrefEnv({ set: [["dom.disable_open_during_load", false]] }); + + const popupOpened = BrowserTestUtils.waitForNewWindow({ url: "about:blank" }); + BrowserTestUtils.openNewForegroundTab( + gBrowser, + "data:text/html,<html><script>popup=open('about:blank','','width=300,height=200')</script>" + ); + const win = await popupOpened; + const doc = win.document; + + ok( + !isVisible(doc.getElementById("TabsToolbar")), + "tabbar should be hidden for popup" + ); + + const closedPopupPromise = BrowserTestUtils.windowClosed(win); + win.close(); + await closedPopupPromise; + + gBrowser.removeCurrentTab(); +} + +add_task(async function tabbar_visibility() { + await testTabBarVisibility(); +}); + +add_task(async function tabbar_visibility_with_theme() { + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + theme: {}, + }, + }); + + await extension.startup(); + + await testTabBarVisibility(); + + await extension.unload(); +}); diff --git a/browser/base/content/test/popups/browser_popup_blocker.js b/browser/base/content/test/popups/browser_popup_blocker.js new file mode 100644 index 0000000000..23cc01e46c --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_blocker.js @@ -0,0 +1,119 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const baseURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); + +function clearAllPermissionsByPrefix(aPrefix) { + for (let perm of Services.perms.all) { + if (perm.type.startsWith(aPrefix)) { + Services.perms.removePermission(perm); + } + } +} + +add_task(async function setup() { + // Enable the popup blocker. + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_during_load", true]], + }); +}); + +// Tests that we show a special message when popup blocking exceeds +// a certain maximum of popups per page. +add_task(async function test_maximum_reported_blocks() { + Services.prefs.setIntPref("privacy.popups.maxReported", 5); + + // Open the test page. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + baseURL + "popup_blocker_10_popups.html" + ); + + // Wait for the popup-blocked notification. + let notification = await TestUtils.waitForCondition(() => + gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked") + ); + + // Slightly hacky way to ensure we show the correct message in this case. + ok( + notification.messageText.textContent.includes("more than"), + "Notification label has 'more than'" + ); + ok( + notification.messageText.textContent.includes("5"), + "Notification label shows the maximum number of popups" + ); + + gBrowser.removeTab(tab); + + Services.prefs.clearUserPref("privacy.popups.maxReported"); +}); + +add_task(async function test_opening_blocked_popups() { + // Open the test page. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + baseURL + "popup_blocker.html" + ); + + // Wait for the popup-blocked notification. + let notification; + await TestUtils.waitForCondition( + () => + (notification = gBrowser + .getNotificationBox() + .getNotificationWithValue("popup-blocked")) + ); + + // Show the menu. + let popupShown = BrowserTestUtils.waitForEvent(window, "popupshown"); + let popupFilled = waitForBlockedPopups(2); + notification.querySelector("button").doCommand(); + let popup_event = await popupShown; + let menu = popup_event.target; + is(menu.id, "blockedPopupOptions", "Blocked popup menu shown"); + + await popupFilled; + + // Pressing "allow" should open all blocked popups. + let popupTabs = []; + function onTabOpen(event) { + popupTabs.push(event.target); + } + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen); + + // Press the button. + let allow = document.getElementById("blockedPopupAllowSite"); + allow.doCommand(); + await TestUtils.waitForCondition( + () => + popupTabs.length == 2 && + popupTabs.every( + aTab => aTab.linkedBrowser.currentURI.spec != "about:blank" + ) + ); + + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen); + + ok( + popupTabs[0].linkedBrowser.currentURI.spec.endsWith("popup_blocker_a.html"), + "Popup a" + ); + ok( + popupTabs[1].linkedBrowser.currentURI.spec.endsWith("popup_blocker_b.html"), + "Popup b" + ); + + // Clean up. + gBrowser.removeTab(tab); + for (let popup of popupTabs) { + gBrowser.removeTab(popup); + } + clearAllPermissionsByPrefix("popup"); + // Ensure the menu closes. + menu.hidePopup(); +}); diff --git a/browser/base/content/test/popups/browser_popup_blocker_frames.js b/browser/base/content/test/popups/browser_popup_blocker_frames.js new file mode 100644 index 0000000000..bcde4b5a64 --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_blocker_frames.js @@ -0,0 +1,97 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const baseURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); + +async function test_opening_blocked_popups(testURL) { + // Enable the popup blocker. + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_during_load", true]], + }); + + // Open the test page. + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, testURL); + + await SpecialPowers.spawn( + tab.linkedBrowser, + [baseURL + "popup_blocker.html"], + uri => { + let iframe = content.document.createElement("iframe"); + iframe.id = "popupframe"; + iframe.src = uri; + content.document.body.appendChild(iframe); + } + ); + + // Wait for the popup-blocked notification. + await TestUtils.waitForCondition( + () => + gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"), + "Waiting for the popup-blocked notification." + ); + + let popupTabs = []; + function onTabOpen(event) { + popupTabs.push(event.target); + } + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen); + + await SpecialPowers.pushPermissions([ + { type: "popup", allow: true, context: testURL }, + ]); + + await SpecialPowers.spawn( + tab.linkedBrowser, + [baseURL + "popup_blocker.html"], + uri => { + content.document.getElementById("popupframe").remove(); + let iframe = content.document.createElement("iframe"); + iframe.id = "popupframe"; + iframe.src = uri; + content.document.body.appendChild(iframe); + } + ); + + await TestUtils.waitForCondition( + () => + popupTabs.length == 2 && + popupTabs.every( + aTab => aTab.linkedBrowser.currentURI.spec != "about:blank" + ), + "Waiting for two tabs to be opened." + ); + + ok( + popupTabs[0].linkedBrowser.currentURI.spec.endsWith("popup_blocker_a.html"), + "Popup a" + ); + ok( + popupTabs[1].linkedBrowser.currentURI.spec.endsWith("popup_blocker_b.html"), + "Popup b" + ); + + await SpecialPowers.popPermissions(); + + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen); + + await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + content.document.getElementById("popupframe").remove(); + }); + + BrowserTestUtils.removeTab(tab); + for (let popup of popupTabs) { + gBrowser.removeTab(popup); + } +} + +add_task(async function() { + await test_opening_blocked_popups("http://example.com/"); +}); + +add_task(async function() { + await test_opening_blocked_popups("http://w3c-test.org/"); +}); diff --git a/browser/base/content/test/popups/browser_popup_blocker_identity_block.js b/browser/base/content/test/popups/browser_popup_blocker_identity_block.js new file mode 100644 index 0000000000..1ab9b1805e --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_blocker_identity_block.js @@ -0,0 +1,241 @@ +"use strict"; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { SitePermissions } = ChromeUtils.import( + "resource:///modules/SitePermissions.jsm" +); +const { PermissionTestUtils } = ChromeUtils.import( + "resource://testing-common/PermissionTestUtils.jsm" +); + +const baseURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); +const URL = baseURL + "popup_blocker2.html"; +const URI = Services.io.newURI(URL); +const PRINCIPAL = Services.scriptSecurityManager.createContentPrincipal( + URI, + {} +); + +function openIdentityPopup() { + let promise = BrowserTestUtils.waitForEvent( + window, + "popupshown", + true, + event => event.target == gIdentityHandler._identityPopup + ); + gIdentityHandler._identityBox.click(); + return promise; +} + +function closeIdentityPopup() { + let promise = BrowserTestUtils.waitForEvent( + gIdentityHandler._identityPopup, + "popuphidden" + ); + gIdentityHandler._identityPopup.hidePopup(); + return promise; +} + +add_task(async function enable_popup_blocker() { + // Enable popup blocker. + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_during_load", true]], + }); + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_click_delay", 0]], + }); +}); + +add_task(async function check_blocked_popup_indicator() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL); + + // Blocked popup indicator should not exist in the identity popup when there are no blocked popups. + await openIdentityPopup(); + Assert.equal(document.getElementById("blocked-popup-indicator-item"), null); + await closeIdentityPopup(); + + // Blocked popup notification icon should be hidden in the identity block when no popups are blocked. + let icon = gIdentityHandler._identityBox.querySelector( + ".blocked-permission-icon[data-permission-id='popup']" + ); + Assert.equal(icon.hasAttribute("showing"), false); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { + let open = content.document.getElementById("pop"); + open.click(); + }); + + // Wait for popup block. + await TestUtils.waitForCondition(() => + gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked") + ); + + // Check if blocked popup indicator text is visible in the identity popup. It should be visible. + document.getElementById("identity-icon").click(); + await openIdentityPopup(); + await TestUtils.waitForCondition( + () => document.getElementById("blocked-popup-indicator-item") !== null + ); + + // Check that the default state is correctly set to "Block". + let menulist = document.getElementById("identity-popup-popup-menulist"); + Assert.equal(menulist.value, "0"); + Assert.equal(menulist.label, "Block"); + + await closeIdentityPopup(); + + // Check if blocked popup icon is visible in the identity block. + Assert.equal(icon.getAttribute("showing"), "true"); + + gBrowser.removeTab(tab); +}); + +// Check if clicking on "Show blocked popups" shows blocked popups. +add_task(async function check_popup_showing() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { + let open = content.document.getElementById("pop"); + open.click(); + }); + + // Wait for popup block. + await TestUtils.waitForCondition(() => + gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked") + ); + + // Store the popup that opens in this array. + let popup; + function onTabOpen(event) { + popup = event.target; + } + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen); + + // Open identity popup and click on "Show blocked popups". + await openIdentityPopup(); + let e = document.getElementById("blocked-popup-indicator-item"); + let text = e.getElementsByTagName("label")[0]; + text.click(); + + await BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen"); + await TestUtils.waitForCondition( + () => popup.linkedBrowser.currentURI.spec != "about:blank" + ); + + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen); + + ok( + popup.linkedBrowser.currentURI.spec.endsWith("popup_blocker_a.html"), + "Popup a" + ); + + gBrowser.removeTab(popup); + gBrowser.removeTab(tab); +}); + +// Test if changing menulist values of blocked popup indicator changes permission state and popup behavior. +add_task(async function check_permission_state_change() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL); + + // Initially the permission state is BLOCK for popups (set by the prefs). + let state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser) + .state; + Assert.equal(state, SitePermissions.BLOCK); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { + let open = content.document.getElementById("pop"); + open.click(); + }); + + // Wait for popup block. + await TestUtils.waitForCondition(() => + gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked") + ); + + // Open identity popup and change permission state to allow. + await openIdentityPopup(); + let menulist = document.getElementById("identity-popup-popup-menulist"); + menulist.menupopup.openPopup(); // Open the allow/block menu + let menuitem = menulist.getElementsByTagName("menuitem")[0]; + menuitem.click(); + await closeIdentityPopup(); + + state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser).state; + Assert.equal(state, SitePermissions.ALLOW); + + // Store the popup that opens in this array. + let popup; + function onTabOpen(event) { + popup = event.target; + } + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen); + + // Check if a popup opens. + await Promise.all([ + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + let open = content.document.getElementById("pop"); + open.click(); + }), + BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen"), + ]); + await TestUtils.waitForCondition( + () => popup.linkedBrowser.currentURI.spec != "about:blank" + ); + + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen); + + ok( + popup.linkedBrowser.currentURI.spec.endsWith("popup_blocker_a.html"), + "Popup a" + ); + + gBrowser.removeTab(popup); + + // Open identity popup and change permission state to block. + await openIdentityPopup(); + menulist = document.getElementById("identity-popup-popup-menulist"); + menulist.menupopup.openPopup(); // Open the allow/block menu + menuitem = menulist.getElementsByTagName("menuitem")[1]; + menuitem.click(); + await closeIdentityPopup(); + + // Clicking on the "Block" menuitem should remove the permission object(same behavior as UNKNOWN state). + // We have already confirmed that popups are blocked when the permission state is BLOCK. + state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser).state; + Assert.equal(state, SitePermissions.BLOCK); + + gBrowser.removeTab(tab); +}); + +// Explicitly set the permission to the otherwise default state and check that +// the label still displays correctly. +add_task(async function check_explicit_default_permission() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL); + + // DENY only works if triggered through Services.perms (it's very edge-casey), + // since SitePermissions.jsm considers setting default permissions to be removal. + PermissionTestUtils.add(URI, "popup", Ci.nsIPermissionManager.DENY_ACTION); + + await openIdentityPopup(); + let menulist = document.getElementById("identity-popup-popup-menulist"); + Assert.equal(menulist.value, "0"); + Assert.equal(menulist.label, "Block"); + await closeIdentityPopup(); + + PermissionTestUtils.add(URI, "popup", Services.perms.ALLOW_ACTION); + + await openIdentityPopup(); + menulist = document.getElementById("identity-popup-popup-menulist"); + Assert.equal(menulist.value, "1"); + Assert.equal(menulist.label, "Allow"); + await closeIdentityPopup(); + + PermissionTestUtils.remove(URI, "popup"); + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/popups/browser_popup_blocker_iframes.js b/browser/base/content/test/popups/browser_popup_blocker_iframes.js new file mode 100644 index 0000000000..c3919cd497 --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_blocker_iframes.js @@ -0,0 +1,180 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +requestLongerTimeout(2); + +const testURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.org" +); + +const examplecomURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); + +const w3cURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://w3c-test.org" +); + +const examplenetURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.net" +); + +const prefixexamplecomURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://prefixexample.com" +); + +class TestCleanup { + constructor() { + this.tabs = []; + } + + count() { + return this.tabs.length; + } + + static setup() { + let cleaner = new TestCleanup(); + this.onTabOpen = event => { + cleaner.tabs.push(event.target); + }; + gBrowser.tabContainer.addEventListener("TabOpen", this.onTabOpen); + return cleaner; + } + + clean() { + gBrowser.tabContainer.removeEventListener("TabOpen", this.onTabOpen); + for (let tab of this.tabs) { + gBrowser.removeTab(tab); + } + } +} + +async function runTest(count, urls, permissions, delayedAllow) { + let cleaner = TestCleanup.setup(); + + // Enable the popup blocker. + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_during_load", true]], + }); + + await SpecialPowers.pushPermissions(permissions); + + // Open the test page. + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, testURL); + + let contexts = await SpecialPowers.spawn( + tab.linkedBrowser, + [...urls, !!delayedAllow], + async (url1, url2, url3, url4, delay) => { + let iframe1 = content.document.createElement("iframe"); + let iframe2 = content.document.createElement("iframe"); + iframe1.id = "iframe1"; + iframe2.id = "iframe2"; + iframe1.src = new URL( + `popup_blocker_frame.html?delayed=${delay}&base=${url3}`, + url1 + ); + iframe2.src = new URL( + `popup_blocker_frame.html?delayed=${delay}&base=${url4}`, + url2 + ); + + let promises = [ + new Promise(resolve => (iframe1.onload = resolve)), + new Promise(resolve => (iframe2.onload = resolve)), + ]; + + content.document.body.appendChild(iframe1); + content.document.body.appendChild(iframe2); + + await Promise.all(promises); + return [iframe1.browsingContext, iframe2.browsingContext]; + } + ); + + if (delayedAllow) { + await delayedAllow(); + await SpecialPowers.spawn(tab.linkedBrowser, contexts, async function( + bc1, + bc2 + ) { + bc1.window.postMessage("allow", "*"); + bc2.window.postMessage("allow", "*"); + }); + } + + await TestUtils.waitForCondition( + () => cleaner.count() == count, + `waiting for ${count} tabs, got ${cleaner.count()}` + ); + + ok(cleaner.count() == count, `should have ${count} tabs`); + + await SpecialPowers.popPermissions(); + cleaner.clean(); +} + +add_task(async function() { + let permission = { + type: "popup", + allow: true, + context: "", + }; + + let expected = []; + + let tests = [ + [examplecomURL, w3cURL, prefixexamplecomURL, examplenetURL], + [examplecomURL, examplecomURL, prefixexamplecomURL, examplenetURL], + [examplecomURL, examplecomURL, prefixexamplecomURL, prefixexamplecomURL], + [examplecomURL, w3cURL, prefixexamplecomURL, prefixexamplecomURL], + ]; + + permission.context = testURL; + expected = [5, 5, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [permission]); + } + + permission.context = examplecomURL; + expected = [3, 5, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [permission]); + } + + permission.context = prefixexamplecomURL; + expected = [3, 3, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [permission]); + } + + async function allowPopup() { + await SpecialPowers.pushPermissions([permission]); + } + + permission.context = testURL; + expected = [5, 5, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [], allowPopup); + } + + permission.context = examplecomURL; + expected = [3, 5, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [], allowPopup); + } + + permission.context = prefixexamplecomURL; + expected = [3, 3, 3, 3]; + for (let test in tests) { + await runTest(expected[test], tests[test], [], allowPopup); + } +}); diff --git a/browser/base/content/test/popups/browser_popup_close_main_window.js b/browser/base/content/test/popups/browser_popup_close_main_window.js new file mode 100644 index 0000000000..7698684a95 --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_close_main_window.js @@ -0,0 +1,84 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function muffleMainWindowType() { + let oldWinType = document.documentElement.getAttribute("windowtype"); + // Check if we've already done this to allow calling multiple times: + if (oldWinType != "navigator:testrunner") { + // Make the main test window not count as a browser window any longer + document.documentElement.setAttribute("windowtype", "navigator:testrunner"); + + registerCleanupFunction(() => { + document.documentElement.setAttribute("windowtype", oldWinType); + }); + } +} + +/** + * Check that if we close the 1 remaining window, we treat it as quitting on + * non-mac. + * + * Sets the window type for the main browser test window to something else to + * avoid having to actually close the main browser window. + */ +add_task(async function closing_last_window_equals_quitting() { + if (navigator.platform.startsWith("Mac")) { + ok(true, "Not testing on mac"); + return; + } + muffleMainWindowType(); + + let observed = 0; + function obs() { + observed++; + } + Services.obs.addObserver(obs, "browser-lastwindow-close-requested"); + let newWin = await BrowserTestUtils.openNewBrowserWindow(); + let closedPromise = BrowserTestUtils.windowClosed(newWin); + newWin.BrowserTryToCloseWindow(); + await closedPromise; + is(observed, 1, "Got a notification for closing the normal window."); + Services.obs.removeObserver(obs, "browser-lastwindow-close-requested"); +}); + +/** + * Check that if we close the 1 remaining window and also have a popup open, + * we don't treat it as quitting. + * + * Sets the window type for the main browser test window to something else to + * avoid having to actually close the main browser window. + */ +add_task(async function closing_last_window_equals_quitting() { + if (navigator.platform.startsWith("Mac")) { + ok(true, "Not testing on mac"); + return; + } + muffleMainWindowType(); + let observed = 0; + function obs() { + observed++; + } + Services.obs.addObserver(obs, "browser-lastwindow-close-requested"); + let newWin = await BrowserTestUtils.openNewBrowserWindow(); + let popupPromise = BrowserTestUtils.waitForNewWindow("https://example.com/"); + SpecialPowers.spawn(newWin.gBrowser.selectedBrowser, [], function() { + content.open("https://example.com/", "_blank", "height=500"); + }); + let popupWin = await popupPromise; + let closedPromise = BrowserTestUtils.windowClosed(newWin); + newWin.BrowserTryToCloseWindow(); + await closedPromise; + is(observed, 0, "Got no notification for closing the normal window."); + + closedPromise = BrowserTestUtils.windowClosed(popupWin); + popupWin.BrowserTryToCloseWindow(); + await closedPromise; + is( + observed, + 0, + "Got no notification now that we're closing the last window, as it's a popup." + ); + Services.obs.removeObserver(obs, "browser-lastwindow-close-requested"); +}); diff --git a/browser/base/content/test/popups/browser_popup_frames.js b/browser/base/content/test/popups/browser_popup_frames.js new file mode 100644 index 0000000000..37b306b0eb --- /dev/null +++ b/browser/base/content/test/popups/browser_popup_frames.js @@ -0,0 +1,125 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const baseURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); + +async function test_opening_blocked_popups(testURL) { + // Enable the popup blocker. + await SpecialPowers.pushPrefEnv({ + set: [["dom.disable_open_during_load", true]], + }); + + // Open the test page. + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, testURL); + + let popupframeBC = await SpecialPowers.spawn( + tab.linkedBrowser, + [baseURL + "popup_blocker.html"], + uri => { + let iframe = content.document.createElement("iframe"); + iframe.id = "popupframe"; + iframe.src = uri; + content.document.body.appendChild(iframe); + return iframe.browsingContext; + } + ); + + // Wait for the popup-blocked notification. + let notification; + await TestUtils.waitForCondition( + () => + (notification = gBrowser + .getNotificationBox() + .getNotificationWithValue("popup-blocked")), + "Waiting for the popup-blocked notification." + ); + + ok(notification, "Should have notification."); + + let pageHideHappened = BrowserTestUtils.waitForContentEvent( + tab.linkedBrowser, + "pagehide", + true + ); + await SpecialPowers.spawn(tab.linkedBrowser, [baseURL], async function(uri) { + let iframe = content.document.createElement("iframe"); + content.document.body.appendChild(iframe); + iframe.src = uri; + }); + + await pageHideHappened; + notification = gBrowser + .getNotificationBox() + .getNotificationWithValue("popup-blocked"); + ok(notification, "Should still have notification"); + + pageHideHappened = BrowserTestUtils.waitForContentEvent( + tab.linkedBrowser, + "pagehide", + true + ); + // Now navigate the subframe. + await SpecialPowers.spawn(popupframeBC, [], async function() { + content.document.location.href = "about:blank"; + }); + await pageHideHappened; + await TestUtils.waitForCondition( + () => + !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"), + "Notification should go away" + ); + ok( + !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"), + "Should no longer have notification" + ); + + // Remove the frame and add another one: + await SpecialPowers.spawn( + tab.linkedBrowser, + [baseURL + "popup_blocker.html"], + uri => { + content.document.getElementById("popupframe").remove(); + let iframe = content.document.createElement("iframe"); + iframe.id = "popupframe"; + iframe.src = uri; + content.document.body.appendChild(iframe); + } + ); + + // Wait for the popup-blocked notification. + await TestUtils.waitForCondition( + () => + (notification = gBrowser + .getNotificationBox() + .getNotificationWithValue("popup-blocked")) + ); + + ok(notification, "Should have notification."); + + await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + content.document.getElementById("popupframe").remove(); + }); + + await TestUtils.waitForCondition( + () => + !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked") + ); + ok( + !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"), + "Should no longer have notification" + ); + + BrowserTestUtils.removeTab(tab); +} + +add_task(async function() { + await test_opening_blocked_popups("http://example.com/"); +}); + +add_task(async function() { + await test_opening_blocked_popups("http://w3c-test.org/"); +}); diff --git a/browser/base/content/test/popups/head.js b/browser/base/content/test/popups/head.js new file mode 100644 index 0000000000..47e43e904c --- /dev/null +++ b/browser/base/content/test/popups/head.js @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +async function waitForBlockedPopups(numberOfPopups) { + let menupopup = document.getElementById("blockedPopupOptions"); + await BrowserTestUtils.waitForCondition(() => { + let popups = menupopup.querySelectorAll("[popupReportIndex]"); + return popups.length == numberOfPopups; + }, `Waiting for ${numberOfPopups} popups`); +} diff --git a/browser/base/content/test/popups/popup_blocker.html b/browser/base/content/test/popups/popup_blocker.html new file mode 100644 index 0000000000..8e2d958059 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker.html @@ -0,0 +1,13 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8"> + <title>Page creating two popups</title> + </head> + <body> + <script type="text/javascript"> + window.open("popup_blocker_a.html", "a"); + window.open("popup_blocker_b.html", "b"); + </script> + </body> +</html> diff --git a/browser/base/content/test/popups/popup_blocker2.html b/browser/base/content/test/popups/popup_blocker2.html new file mode 100644 index 0000000000..ec880c0821 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker2.html @@ -0,0 +1,10 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8"> + <title>Page creating a popup</title> + </head> + <body> + <button id="pop" onclick='window.setTimeout(() => {window.open("popup_blocker_a.html", "a");}, 10);'>Open Popup</button> + </body> +</html> diff --git a/browser/base/content/test/popups/popup_blocker_10_popups.html b/browser/base/content/test/popups/popup_blocker_10_popups.html new file mode 100644 index 0000000000..9dc288f472 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_10_popups.html @@ -0,0 +1,14 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8"> + <title>Page creating ten popups</title> + </head> + <body> + <script type="text/javascript"> + for (let i = 0; i < 10; i++) { + window.open("https://example.com"); + } + </script> + </body> +</html> diff --git a/browser/base/content/test/popups/popup_blocker_a.html b/browser/base/content/test/popups/popup_blocker_a.html new file mode 100644 index 0000000000..b6f94b5b26 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_a.html @@ -0,0 +1 @@ +<html><body>a</body></html> diff --git a/browser/base/content/test/popups/popup_blocker_b.html b/browser/base/content/test/popups/popup_blocker_b.html new file mode 100644 index 0000000000..954061e2ce --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_b.html @@ -0,0 +1 @@ +<html><body>b</body></html> diff --git a/browser/base/content/test/popups/popup_blocker_frame.html b/browser/base/content/test/popups/popup_blocker_frame.html new file mode 100644 index 0000000000..e29452fb63 --- /dev/null +++ b/browser/base/content/test/popups/popup_blocker_frame.html @@ -0,0 +1,27 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8"> + <title>Page with iframe that contains page that opens two popups</title> + </head> + <body> + <iframe id="iframe"></iframe> + <script type="text/javascript"> + let params = new URLSearchParams(location.search); + let base = params.get('base') || location.href; + let frame = document.getElementById('iframe'); + + function addPopupOpeningFrame() { + frame.src = new URL("popup_blocker.html", base); + } + + if (params.get('delayed') !== 'true') { + addPopupOpeningFrame(); + } else { + addEventListener("message", () => { + addPopupOpeningFrame(); + }, {once: true}); + } + </script> + </body> +</html> |