summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/popups
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/popups')
-rw-r--r--browser/base/content/test/popups/.eslintrc.js5
-rw-r--r--browser/base/content/test/popups/browser.ini33
-rw-r--r--browser/base/content/test/popups/browser_popupUI.js192
-rw-r--r--browser/base/content/test/popups/browser_popup_blocker.js119
-rw-r--r--browser/base/content/test/popups/browser_popup_blocker_frames.js97
-rw-r--r--browser/base/content/test/popups/browser_popup_blocker_identity_block.js241
-rw-r--r--browser/base/content/test/popups/browser_popup_blocker_iframes.js180
-rw-r--r--browser/base/content/test/popups/browser_popup_close_main_window.js84
-rw-r--r--browser/base/content/test/popups/browser_popup_frames.js125
-rw-r--r--browser/base/content/test/popups/head.js12
-rw-r--r--browser/base/content/test/popups/popup_blocker.html13
-rw-r--r--browser/base/content/test/popups/popup_blocker2.html10
-rw-r--r--browser/base/content/test/popups/popup_blocker_10_popups.html14
-rw-r--r--browser/base/content/test/popups/popup_blocker_a.html1
-rw-r--r--browser/base/content/test/popups/popup_blocker_b.html1
-rw-r--r--browser/base/content/test/popups/popup_blocker_frame.html27
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>