Bug 1331931 - Move the blocked popup icon into the identity block and add a blocked popup indicator item to the identity popup. r?johannh draft
authorPrathiksha <prathikshaprasadsuman@gmail.com>
Sun, 17 Sep 2017 18:35:10 +0530
changeset 684102 6c92780eac23ac8702b5b704a728e15ea0e5c38f
parent 683863 d1e995c8640a191cd127e87273ec96cb2fabffa9
child 736810 54470f52d1a2bbbf7d1c57de99fd682f8732a345
push id85553
push userbmo:prathikshaprasadsuman@gmail.com
push dateFri, 20 Oct 2017 20:13:41 +0000
reviewersjohannh
bugs1331931
milestone58.0a1
Bug 1331931 - Move the blocked popup icon into the identity block and add a blocked popup indicator item to the identity popup. r?johannh MozReview-Commit-ID: HxsG2Uz2PuZ
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/test/popups/browser.ini
browser/base/content/test/popups/browser_popup_blocker.js
browser/base/content/test/popups/browser_popup_blocker_identity_block.js
browser/base/content/test/popups/browser_popup_frames.js
browser/base/content/test/popups/popup_blocker2.html
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
browser/themes/shared/jar.inc.mn
browser/themes/shared/notification-icons.inc.css
browser/themes/shared/notification-icons/popup-subitem.svg
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -584,61 +584,33 @@ function findChildShell(aDocument, aDocS
     docShell = findChildShell(aDocument, docShell, aSoughtURI);
     if (docShell)
       return docShell;
   }
   return null;
 }
 
 var gPopupBlockerObserver = {
-  _reportButton: null,
-
-  onReportButtonMousedown(aEvent) {
-    // The button is part of the textbox that is considered the popup's anchor,
-    // thus consumeoutsideclicks="false" is ignored. Moreover On OS X the popup
-    // is hidden well before mousedown gets dispatched.
-    // Thus, if the popup is open and the user clicks on the button, it gets
-    // hidden before mousedown, and may then be unexpectedly reopened by click.
-    // To avoid this, we check if mousedown is in the same tick as popupHidden,
-    // and, in such a case, we don't handle the click event.
-    // Note we can't just openPopup in mousedown, cause this popup is shared by
-    // multiple anchors, and we could end up opening it just before the other
-    // anchor tries to hide it.
-    if (aEvent.button != 0 || aEvent.target != this._reportButton || this.isPopupHidingTick)
-      return;
-
-    this._reportButton.addEventListener("click", event => {
-      document.getElementById("blockedPopupOptions")
-              .openPopup(event.target, "after_end", 0, 2, false, false, event);
-    }, { once: true });
-  },
-
   handleEvent(aEvent) {
     if (aEvent.originalTarget != gBrowser.selectedBrowser)
       return;
 
-    if (!this._reportButton)
-      this._reportButton = document.getElementById("page-report-button");
+    gIdentityHandler.refreshIdentityBlock();
 
     if (!gBrowser.selectedBrowser.blockedPopups ||
         !gBrowser.selectedBrowser.blockedPopups.length) {
-      // Hide the icon in the location bar (if the location bar exists)
-      this._reportButton.hidden = true;
-
       // Hide the notification box (if it's visible).
       let notificationBox = gBrowser.getNotificationBox();
       let notification = notificationBox.getNotificationWithValue("popup-blocked");
       if (notification) {
         notificationBox.removeNotification(notification, false);
       }
       return;
     }
 
-    this._reportButton.hidden = false;
-
     // Only show the notification again if we've not already shown it. Since
     // notifications are per-browser, we don't need to worry about re-adding
     // it.
     if (!gBrowser.selectedBrowser.blockedPopups.reported) {
       if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage")) {
         var brandBundle = document.getElementById("bundle_brand");
         var brandShortName = brandBundle.getString("brandShortName");
         var popupCount = gBrowser.selectedBrowser.blockedPopups.length;
@@ -728,22 +700,17 @@ var gPopupBlockerObserver = {
     if (PrivateBrowsingUtils.isWindowPrivate(window))
       blockedPopupAllowSite.setAttribute("disabled", "true");
     else
       blockedPopupAllowSite.removeAttribute("disabled");
 
     let blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage");
     let showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
     blockedPopupDontShowMessage.setAttribute("checked", !showMessage);
-    if (aEvent.target.anchorNode.id == "page-report-button") {
-      aEvent.target.anchorNode.setAttribute("open", "true");
-      blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromLocationbar"));
-    } else {
-      blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromMessage"));
-    }
+    blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromMessage"));
 
     let blockedPopupsSeparator =
         document.getElementById("blockedPopupsSeparator");
     blockedPopupsSeparator.setAttribute("hidden", true);
 
     gBrowser.selectedBrowser.retrieveListOfBlockedPopups().then(blockedPopups => {
       let foundUsablePopupURI = false;
       if (blockedPopups) {
@@ -788,23 +755,16 @@ var gPopupBlockerObserver = {
       // Show the separator if we added any
       // showable popup addresses to the menu.
       if (foundUsablePopupURI)
         blockedPopupsSeparator.removeAttribute("hidden");
     }, null);
   },
 
   onPopupHiding(aEvent) {
-    if (aEvent.target.anchorNode.id == "page-report-button") {
-      aEvent.target.anchorNode.removeAttribute("open");
-
-      this.isPopupHidingTick = true;
-      setTimeout(() => this.isPopupHidingTick = false, 0);
-    }
-
     let item = aEvent.target.lastChild;
     while (item && item.getAttribute("observes") != "blockedPopupsSeparator") {
       let next = item.previousSibling;
       item.remove();
       item = next;
     }
   },
 
@@ -7658,16 +7618,24 @@ var gIdentityHandler = {
         hasGrantedPermissions = true;
       }
     }
 
     if (hasGrantedPermissions) {
       this._identityBox.classList.add("grantedPermissions");
     }
 
+    // Show blocked popup icon in the identity-box if popups are blocked
+    // irrespective of popup permission capability value.
+    if (gBrowser.selectedBrowser.blockedPopups &&
+        gBrowser.selectedBrowser.blockedPopups.length) {
+      let icon = permissionAnchors.popup;
+      icon.setAttribute("showing", "true");
+    }
+
     // Push the appropriate strings out to the UI
     this._connectionIcon.setAttribute("tooltiptext", tooltip);
 
     if (this._isExtensionPage) {
       let extensionName = extensionNameFromURI(this._uri);
       this._extensionIcon.setAttribute("tooltiptext",
         gNavigatorBundle.getFormattedString("identity.extension.tooltip", [extensionName]));
     }
@@ -8008,19 +7976,41 @@ var gIdentityHandler = {
               state: SitePermissions.ALLOW,
               scope: SitePermissions.SCOPE_REQUEST,
               inUse: true,
             });
           }
         }
       }
     }
+
+    let hasBlockedPopupIndicator = false;
     for (let permission of permissions) {
       let item = this._createPermissionItem(permission);
       this._permissionList.appendChild(item);
+
+      if (permission.id == "popup" &&
+          gBrowser.selectedBrowser.blockedPopups &&
+          gBrowser.selectedBrowser.blockedPopups.length) {
+        this._createBlockedPopupIndicator();
+        hasBlockedPopupIndicator = true;
+      }
+    }
+
+    if (gBrowser.selectedBrowser.blockedPopups &&
+        gBrowser.selectedBrowser.blockedPopups.length &&
+        !hasBlockedPopupIndicator) {
+      let permission = {
+        id: "popup",
+        state: SitePermissions.UNKNOWN,
+        scope: SitePermissions.SCOPE_PERSISTENT,
+      };
+      let item = this._createPermissionItem(permission);
+      this._permissionList.appendChild(item);
+      this._createBlockedPopupIndicator();
     }
 
     // Show a placeholder text if there's no permission and no reload hint.
     if (!this._permissionList.hasChildNodes() &&
         this._permissionReloadHint.hasAttribute("hidden")) {
       this._permissionEmptyHint.removeAttribute("hidden");
     } else {
       this._permissionEmptyHint.setAttribute("hidden", "true");
@@ -8040,16 +8030,51 @@ var gIdentityHandler = {
       classes += " in-use";
     img.setAttribute("class", classes);
 
     let nameLabel = document.createElement("label");
     nameLabel.setAttribute("flex", "1");
     nameLabel.setAttribute("class", "identity-popup-permission-label");
     nameLabel.textContent = SitePermissions.getPermissionLabel(aPermission.id);
 
+    if (aPermission.id == "popup") {
+      let menulist = document.createElement("menulist");
+      let menupopup = document.createElement("menupopup");
+      let block = document.createElement("vbox");
+      block.setAttribute("id", "identity-popup-popup-container");
+      menulist.setAttribute("class", "identity-popup-popup-menulist");
+      menulist.setAttribute("id", "identity-popup-popup-menulist");
+
+      for (let state of SitePermissions.getAvailableStates(aPermission.id)) {
+        let menuitem = document.createElement("menuitem");
+        if (state == SitePermissions.getDefault(aPermission.id)) {
+          menuitem.setAttribute("value", 0);
+        } else {
+          menuitem.setAttribute("value", state);
+        }
+        menuitem.setAttribute("label", SitePermissions.getMultichoiceStateLabel(state));
+        menupopup.appendChild(menuitem);
+      }
+
+      menulist.appendChild(menupopup);
+      menulist.setAttribute("value", aPermission.state);
+
+      // Avoiding listening to the "select" event on purpose. See Bug 1404262.
+      menulist.addEventListener("command", () => {
+        SitePermissions.set(gBrowser.currentURI, "popup", menulist.selectedItem.value);
+      });
+
+      container.appendChild(img);
+      container.appendChild(nameLabel);
+      container.appendChild(menulist);
+      block.appendChild(container);
+
+      return block;
+    }
+
     let stateLabel = document.createElement("label");
     stateLabel.setAttribute("flex", "1");
     stateLabel.setAttribute("class", "identity-popup-permission-state-label");
     let {state, scope} = aPermission;
     // If the user did not permanently allow this device but it is currently
     // used, set the variables to display a "temporarily allowed" info.
     if (state != SitePermissions.ALLOW && aPermission.inUse) {
       state = SitePermissions.ALLOW;
@@ -8121,17 +8146,46 @@ var gIdentityHandler = {
     });
 
     container.appendChild(img);
     container.appendChild(nameLabel);
     container.appendChild(stateLabel);
     container.appendChild(button);
 
     return container;
-  }
+  },
+
+  _createBlockedPopupIndicator() {
+    let indicator = document.createElement("hbox");
+    indicator.setAttribute("class", "identity-popup-permission-item");
+    indicator.setAttribute("align", "center");
+    indicator.setAttribute("id", "blocked-popup-indicator-item");
+
+    let icon = document.createElement("image");
+    icon.setAttribute("class", "popup-subitem identity-popup-permission-icon");
+
+    let text = document.createElement("label");
+    text.setAttribute("flex", "1");
+    text.setAttribute("class", "identity-popup-permission-label text-link");
+
+    let popupCount = gBrowser.selectedBrowser.blockedPopups.length;
+    let messageBase = gNavigatorBundle.getString("popupShowBlockedPopupsIndicatorText");
+    let message = PluralForm.get(popupCount, messageBase)
+                                 .replace("#1", popupCount);
+    text.setAttribute("value", message);
+
+    text.addEventListener("click", () => {
+      gPopupBlockerObserver.showAllBlockedPopups(gBrowser.selectedBrowser);
+    });
+
+    indicator.appendChild(icon);
+    indicator.appendChild(text);
+
+    document.getElementById("identity-popup-popup-container").appendChild(indicator);
+  },
 };
 
 /**
  * Fired on the "marionette-remote-control" system notification,
  * indicating if the browser session is under remote control.
  */
 const gRemoteControl = {
   observe(subject, topic, data) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -805,16 +805,18 @@
                   <image data-permission-id="indexedDB" class="blocked-permission-icon indexedDB-icon" role="button"
                          tooltiptext="&urlbar.indexedDBBlocked.tooltip;"/>
                   <image data-permission-id="microphone" class="blocked-permission-icon microphone-icon" role="button"
                          tooltiptext="&urlbar.microphoneBlocked.tooltip;"/>
                   <image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
                          tooltiptext="&urlbar.screenBlocked.tooltip;"/>
                   <image data-permission-id="persistent-storage" class="blocked-permission-icon persistent-storage-icon" role="button"
                          tooltiptext="&urlbar.persistentStorageBlocked.tooltip;"/>
+                  <image data-permission-id="popup" class="blocked-permission-icon popup-icon" role="button"
+                         tooltiptext="&urlbar.popupBlocked.tooltip;"/>
                 </box>
                 <box id="notification-popup-box"
                      hidden="true"
                      onmouseover="document.getElementById('identity-box').classList.add('no-hover');"
                      onmouseout="document.getElementById('identity-box').classList.remove('no-hover');"
                      align="center">
                   <image id="default-notification-icon" class="notification-anchor-icon" role="button"
                          tooltiptext="&urlbar.defaultNotificationAnchor.tooltip;"/>
@@ -865,22 +867,16 @@
                 <label id="switchtab" class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/>
                 <label id="extension" class="urlbar-display urlbar-display-extension" value="&urlbar.extension.label;"/>
               </box>
               <hbox id="page-action-buttons">
                 <hbox id="userContext-icons" hidden="true">
                   <label id="userContext-label"/>
                   <image id="userContext-indicator"/>
                 </hbox>
-                <image id="page-report-button"
-                       class="urlbar-icon urlbar-page-action"
-                       role="button"
-                       hidden="true"
-                       tooltiptext="&pageReportIcon.tooltip;"
-                       onmousedown="gPopupBlockerObserver.onReportButtonMousedown(event);"/>
                 <image id="reader-mode-button"
                        class="urlbar-icon urlbar-page-action"
                        role="button"
                        hidden="true"
                        onclick="ReaderParent.buttonClick(event);"/>
                 <toolbarbutton id="urlbar-zoom-button"
                        onclick="FullZoom.reset();"
                        tooltip="dynamic-shortcut-tooltip"
--- a/browser/base/content/test/popups/browser.ini
+++ b/browser/base/content/test/popups/browser.ini
@@ -5,8 +5,12 @@ support-files =
   popup_blocker_a.html
   popup_blocker_b.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
--- a/browser/base/content/test/popups/browser_popup_blocker.js
+++ b/browser/base/content/test/popups/browser_popup_blocker.js
@@ -71,26 +71,8 @@ add_task(async function test_opening_blo
   gBrowser.removeTab(tab);
   for (let popup of popupTabs) {
     gBrowser.removeTab(popup);
   }
   clearAllPermissionsByPrefix("popup");
   // Ensure the menu closes.
   menu.hidePopup();
 });
-
-add_task(async function check_icon_hides() {
-  // Enable the popup blocker.
-  await SpecialPowers.pushPrefEnv({set: [["dom.disable_open_during_load", true]]});
-
-  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, baseURL + "popup_blocker.html");
-
-  let button = document.getElementById("page-report-button");
-  await BrowserTestUtils.waitForCondition(() =>
-    gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"));
-  ok(!button.hidden, "Button should be visible");
-
-  let otherPageLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-  openLinkIn(baseURL, "current", {});
-  await otherPageLoaded;
-  ok(button.hidden, "Button should have hidden again after another page loaded.");
-  await BrowserTestUtils.removeTab(tab);
-});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/popups/browser_popup_blocker_identity_block.js
@@ -0,0 +1,167 @@
+"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/. */
+
+Components.utils.import("resource:///modules/SitePermissions.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+const baseURL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+const URL = baseURL + "popup_blocker2.html";
+const URI = Services.io.newURI(URL);
+
+function openIdentityPopup() {
+  let promise = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
+  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 ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
+    let open = content.document.getElementById("pop");
+    open.click();
+  });
+
+  // Wait for popup block.
+  await BrowserTestUtils.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 BrowserTestUtils.waitForCondition(() => document.getElementById("blocked-popup-indicator-item") !== null);
+  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 ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
+    let open = content.document.getElementById("pop");
+    open.click();
+  });
+
+  // Wait for popup block.
+  await BrowserTestUtils.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 BrowserTestUtils.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.get(URI, "popup", gBrowser).state;
+  Assert.equal(state, SitePermissions.BLOCK);
+
+  await ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
+    let open = content.document.getElementById("pop");
+    open.click();
+  });
+
+  // Wait for popup block.
+  await BrowserTestUtils.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");
+  let menuitem = menulist.getElementsByTagName("menuitem")[0];
+  menuitem.click();
+  await closeIdentityPopup();
+
+  state = SitePermissions.get(URI, "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 ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
+    let open = content.document.getElementById("pop");
+    open.click();
+  });
+
+  await BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  await BrowserTestUtils.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");
+  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.get(URI, "popup", gBrowser).state;
+  Assert.equal(state, SitePermissions.BLOCK);
+
+  gBrowser.removeTab(tab);
+});
--- a/browser/base/content/test/popups/browser_popup_frames.js
+++ b/browser/base/content/test/popups/browser_popup_frames.js
@@ -19,69 +19,59 @@ add_task(async function test_opening_blo
   });
 
   // Wait for the popup-blocked notification.
   let notification;
   await BrowserTestUtils.waitForCondition(() =>
     notification = gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"));
 
   ok(notification, "Should have notification.");
-  ok(!document.getElementById("page-report-button").hidden,
-     "URL bar popup indicator should not be hidden");
 
   await ContentTask.spawn(tab.linkedBrowser, baseURL, async function(uri) {
     let iframe = content.document.createElement("iframe");
     iframe.src = uri;
     let pageHideHappened = ContentTaskUtils.waitForEvent(this, "pagehide", true);
     content.document.body.appendChild(iframe);
     await pageHideHappened;
   });
 
   notification = gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked");
   ok(notification, "Should still have notification");
-  ok(!document.getElementById("page-report-button").hidden,
-     "URL bar popup indicator should still be visible");
 
   // Now navigate the subframe.
   await ContentTask.spawn(tab.linkedBrowser, null, async function() {
     let pageHideHappened = ContentTaskUtils.waitForEvent(this, "pagehide", true);
     content.document.getElementById("popupframe").contentDocument.location.href = "about:blank";
     await pageHideHappened;
   });
 
   await BrowserTestUtils.waitForCondition(() =>
     !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"));
   ok(!gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"),
      "Should no longer have notification");
-  ok(document.getElementById("page-report-button").hidden,
-     "URL bar popup indicator should be hidden");
 
   // Remove the frame and add another one:
   await ContentTask.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 BrowserTestUtils.waitForCondition(() =>
     notification = gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"));
 
   ok(notification, "Should have notification.");
-  ok(!document.getElementById("page-report-button").hidden,
-     "URL bar popup indicator should not be hidden");
 
   await ContentTask.spawn(tab.linkedBrowser, null, () => {
     content.document.getElementById("popupframe").remove();
   });
 
   await BrowserTestUtils.waitForCondition(() =>
     !gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"));
   ok(!gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked"),
      "Should no longer have notification");
-  ok(document.getElementById("page-report-button").hidden,
-     "URL bar popup indicator should be hidden");
 
   await BrowserTestUtils.removeTab(tab);
 });
 
new file mode 100644
--- /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>
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -224,16 +224,17 @@ These should match what Safari and other
 
 <!ENTITY urlbar.cameraBlocked.tooltip            "You have blocked your camera for this website.">
 <!ENTITY urlbar.microphoneBlocked.tooltip        "You have blocked your microphone for this website.">
 <!ENTITY urlbar.screenBlocked.tooltip            "You have blocked this website from sharing your screen.">
 <!ENTITY urlbar.geolocationBlocked.tooltip       "You have blocked location information for this website.">
 <!ENTITY urlbar.indexedDBBlocked.tooltip         "You have blocked data storage for this website.">
 <!ENTITY urlbar.webNotificationsBlocked.tooltip  "You have blocked notifications for this website.">
 <!ENTITY urlbar.persistentStorageBlocked.tooltip "You have blocked persistent storage for this website.">
+<!ENTITY urlbar.popupBlocked.tooltip             "You have blocked popups for this website.">
 
 <!ENTITY urlbar.openHistoryPopup.tooltip                "Show history">
 
 <!ENTITY searchItem.title             "Search">
 
 <!-- Toolbar items -->
 <!ENTITY homeButton.label             "Home">
 
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -259,19 +259,23 @@ lwthemeNeedsRestart.accesskey=R
 popupWarning.message=#1 prevented this site from opening a pop-up window.;#1 prevented this site from opening #2 pop-up windows.
 popupWarningButton=Options
 popupWarningButton.accesskey=O
 popupWarningButtonUnix=Preferences
 popupWarningButtonUnix.accesskey=P
 popupAllow=Allow pop-ups for %S
 popupBlock=Block pop-ups for %S
 popupWarningDontShowFromMessage=Don’t show this message when pop-ups are blocked
-popupWarningDontShowFromLocationbar=Don’t show info bar when pop-ups are blocked
 popupShowPopupPrefix=Show ‘%S’
 
+# LOCALIZATION NOTE (popupShowBlockedPopupsIndicatorText): Semicolon seperated list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 is the number of pop-ups blocked.
+popupShowBlockedPopupsIndicatorText=Show #1 blocked popup…;Show #1 blocked popups…
+
 # Bad Content Blocker Doorhanger Notification
 # %S is brandShortName
 badContentBlocked.blocked.message=%S is blocking content on this page.
 badContentBlocked.notblocked.message=%S is not blocking any content on this page.
 
 crashedpluginsMessage.title=The %S plugin has crashed.
 crashedpluginsMessage.reloadButton.label=Reload page
 crashedpluginsMessage.reloadButton.accesskey=R
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -74,16 +74,17 @@
   skin/classic/browser/notification-icons/microphone-detailed.svg           (../shared/notification-icons/microphone-detailed.svg)
   skin/classic/browser/notification-icons/microphone.svg                    (../shared/notification-icons/microphone.svg)
   skin/classic/browser/notification-icons/persistent-storage-blocked.svg    (../shared/notification-icons/persistent-storage-blocked.svg)
   skin/classic/browser/notification-icons/persistent-storage.svg            (../shared/notification-icons/persistent-storage.svg)
   skin/classic/browser/notification-icons/plugin-badge.svg                  (../shared/notification-icons/plugin-badge.svg)
   skin/classic/browser/notification-icons/plugin-blocked.svg                (../shared/notification-icons/plugin-blocked.svg)
   skin/classic/browser/notification-icons/plugin.svg                        (../shared/notification-icons/plugin.svg)
   skin/classic/browser/notification-icons/popup.svg                         (../shared/notification-icons/popup.svg)
+  skin/classic/browser/notification-icons/popup-subitem.svg                 (../shared/notification-icons/popup-subitem.svg)
   skin/classic/browser/notification-icons/screen-blocked.svg                (../shared/notification-icons/screen-blocked.svg)
   skin/classic/browser/notification-icons/screen.svg                        (../shared/notification-icons/screen.svg)
   skin/classic/browser/notification-icons/update.svg                        (../shared/notification-icons/update.svg)
 
   skin/classic/browser/tracking-protection-16.svg              (../shared/identity-block/tracking-protection-16.svg)
   skin/classic/browser/newtab/close.png                        (../shared/newtab/close.png)
   skin/classic/browser/newtab/controls.svg                     (../shared/newtab/controls.svg)
   skin/classic/browser/panel-icon-arrow-left.svg               (../shared/panel-icon-arrow-left.svg)
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -150,16 +150,25 @@ html|*#webRTC-previewVideo {
   margin-inline-start: 0;
 }
 
 /* This icon has a block sign in it, so we don't need a blocked version. */
 .popup-icon {
   list-style-image: url("chrome://browser/skin/notification-icons/popup.svg");
 }
 
+.popup-subitem {
+  list-style-image: url("chrome://browser/skin/notification-icons/popup-subitem.svg");
+  margin-inline-start: 30px;
+}
+
+.identity-popup-popup-menulist {
+  width: 72px;
+}
+
 /* EME */
 
 .popup-notification-icon[popupid="drmContentPlaying"],
 .drm-icon {
   list-style-image: url("chrome://browser/skin/drm-icon.svg");
 }
 
 #eme-notification-icon[firstplay=true] {
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/notification-icons/popup-subitem.svg
@@ -0,0 +1,6 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="context-fill" fill-opacity="context-fill-opacity">
+  <path d="M13.707 7.293l-3-3a1 1 0 0 0-1.414 1.414L10.586 7H6.012A.918.918 0 0 1 5 6V3a1 1 0 0 0-2 0v3a2.916 2.916 0 0 0 3 3h4.586l-1.293 1.293a1 1 0 1 0 1.414 1.414l3-3a1 1 0 0 0 0-1.414z"/>
+</svg>