mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	This moves everything except DOMUpdateBlockedPopups, where the current forwarding handler is helpful because it avoids loading this module entirely until/unless we actually get blocked popups. Differential Revision: https://phabricator.services.mozilla.com/D217500
		
			
				
	
	
		
			311 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			311 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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/. */
 | 
						|
 | 
						|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
 | 
						|
 | 
						|
const gInitializedWindows = new WeakSet();
 | 
						|
 | 
						|
export var PopupBlockerObserver = {
 | 
						|
  handleEvent(event) {
 | 
						|
    switch (event.type) {
 | 
						|
      case "DOMUpdateBlockedPopups":
 | 
						|
        this.onDOMUpdateBlockedPopups(event);
 | 
						|
        break;
 | 
						|
      case "command":
 | 
						|
        this.onCommand(event);
 | 
						|
        break;
 | 
						|
      case "popupshowing":
 | 
						|
        this.fillPopupList(event);
 | 
						|
        break;
 | 
						|
      case "popuphiding":
 | 
						|
        this.onPopupHiding(event);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  onCommand(event) {
 | 
						|
    if (event.target.hasAttribute("popupReportIndex")) {
 | 
						|
      PopupBlockerObserver.showBlockedPopup(event);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (event.target.id) {
 | 
						|
      case "blockedPopupAllowSite":
 | 
						|
        this.toggleAllowPopupsForSite(event);
 | 
						|
        break;
 | 
						|
      case "blockedPopupEdit":
 | 
						|
        this.editPopupSettings(event);
 | 
						|
        break;
 | 
						|
      case "blockedPopupDontShowMessage":
 | 
						|
        this.dontShowMessage(event);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  ensureInitializedForWindow(win) {
 | 
						|
    if (gInitializedWindows.has(win)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    gInitializedWindows.add(win);
 | 
						|
    let popup = win.document.getElementById("blockedPopupOptions");
 | 
						|
    popup.addEventListener("command", this);
 | 
						|
    popup.addEventListener("popupshowing", this);
 | 
						|
    popup.addEventListener("popuphiding", this);
 | 
						|
  },
 | 
						|
 | 
						|
  async onDOMUpdateBlockedPopups(aEvent) {
 | 
						|
    let window = aEvent.originalTarget.ownerGlobal;
 | 
						|
    let { gBrowser, gPermissionPanel } = window;
 | 
						|
    if (aEvent.originalTarget != gBrowser.selectedBrowser) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    gPermissionPanel.refreshPermissionIcons();
 | 
						|
 | 
						|
    let popupCount =
 | 
						|
      gBrowser.selectedBrowser.popupBlocker.getBlockedPopupCount();
 | 
						|
 | 
						|
    if (!popupCount) {
 | 
						|
      // 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;
 | 
						|
    }
 | 
						|
 | 
						|
    // 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.popupBlocker.shouldShowNotification) {
 | 
						|
      this.ensureInitializedForWindow(window);
 | 
						|
      if (Services.prefs.getBoolPref("privacy.popups.showBrowserMessage")) {
 | 
						|
        const label = {
 | 
						|
          "l10n-id":
 | 
						|
            popupCount < this.maxReportedPopups
 | 
						|
              ? "popup-warning-message"
 | 
						|
              : "popup-warning-exceeded-message",
 | 
						|
          "l10n-args": { popupCount },
 | 
						|
        };
 | 
						|
 | 
						|
        let notificationBox = gBrowser.getNotificationBox();
 | 
						|
        let notification =
 | 
						|
          notificationBox.getNotificationWithValue("popup-blocked") ||
 | 
						|
          (await this.notificationPromise);
 | 
						|
        if (notification) {
 | 
						|
          notification.label = label;
 | 
						|
        } else {
 | 
						|
          const image = "chrome://browser/skin/notification-icons/popup.svg";
 | 
						|
          const priority = notificationBox.PRIORITY_INFO_MEDIUM;
 | 
						|
          try {
 | 
						|
            this.notificationPromise = notificationBox.appendNotification(
 | 
						|
              "popup-blocked",
 | 
						|
              { label, image, priority },
 | 
						|
              [
 | 
						|
                {
 | 
						|
                  "l10n-id": "popup-warning-button",
 | 
						|
                  popup: "blockedPopupOptions",
 | 
						|
                  callback: null,
 | 
						|
                },
 | 
						|
              ]
 | 
						|
            );
 | 
						|
            await this.notificationPromise;
 | 
						|
          } catch (err) {
 | 
						|
            console.warn(err);
 | 
						|
          } finally {
 | 
						|
            this.notificationPromise = null;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // Record the fact that we've reported this blocked popup, so we don't
 | 
						|
      // show it again.
 | 
						|
      gBrowser.selectedBrowser.popupBlocker.didShowNotification();
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  toggleAllowPopupsForSite(aEvent) {
 | 
						|
    let window = aEvent.originalTarget.ownerGlobal;
 | 
						|
    let { gBrowser } = window;
 | 
						|
    var pm = Services.perms;
 | 
						|
    var shouldBlock = aEvent.target.getAttribute("block") == "true";
 | 
						|
    var perm = shouldBlock ? pm.DENY_ACTION : pm.ALLOW_ACTION;
 | 
						|
    pm.addFromPrincipal(gBrowser.contentPrincipal, "popup", perm);
 | 
						|
 | 
						|
    if (!shouldBlock) {
 | 
						|
      gBrowser.selectedBrowser.popupBlocker.unblockAllPopups();
 | 
						|
    }
 | 
						|
 | 
						|
    gBrowser.getNotificationBox().removeCurrentNotification();
 | 
						|
  },
 | 
						|
 | 
						|
  fillPopupList(aEvent) {
 | 
						|
    let window = aEvent.originalTarget.ownerGlobal;
 | 
						|
    let { gBrowser, document } = window;
 | 
						|
    // XXXben - rather than using |currentURI| here, which breaks down on multi-framed sites
 | 
						|
    //          we should really walk the blockedPopups and create a list of "allow for <host>"
 | 
						|
    //          menuitems for the common subset of hosts present in the report, this will
 | 
						|
    //          make us frame-safe.
 | 
						|
    //
 | 
						|
    // XXXjst - Note that when this is fixed to work with multi-framed sites,
 | 
						|
    //          also back out the fix for bug 343772 where
 | 
						|
    //          nsGlobalWindow::CheckOpenAllow() was changed to also
 | 
						|
    //          check if the top window's location is allow-listed.
 | 
						|
    let browser = gBrowser.selectedBrowser;
 | 
						|
    var uriOrPrincipal = browser.contentPrincipal.isContentPrincipal
 | 
						|
      ? browser.contentPrincipal
 | 
						|
      : browser.currentURI;
 | 
						|
    var blockedPopupAllowSite = document.getElementById(
 | 
						|
      "blockedPopupAllowSite"
 | 
						|
    );
 | 
						|
    try {
 | 
						|
      blockedPopupAllowSite.removeAttribute("hidden");
 | 
						|
      let uriHost = uriOrPrincipal.asciiHost
 | 
						|
        ? uriOrPrincipal.host
 | 
						|
        : uriOrPrincipal.spec;
 | 
						|
      var pm = Services.perms;
 | 
						|
      if (
 | 
						|
        pm.testPermissionFromPrincipal(browser.contentPrincipal, "popup") ==
 | 
						|
        pm.ALLOW_ACTION
 | 
						|
      ) {
 | 
						|
        // Offer an item to block popups for this site, if an allow-list entry exists
 | 
						|
        // already for it.
 | 
						|
        document.l10n.setAttributes(
 | 
						|
          blockedPopupAllowSite,
 | 
						|
          "popups-infobar-block",
 | 
						|
          { uriHost }
 | 
						|
        );
 | 
						|
        blockedPopupAllowSite.setAttribute("block", "true");
 | 
						|
      } else {
 | 
						|
        // Offer an item to allow popups for this site
 | 
						|
        document.l10n.setAttributes(
 | 
						|
          blockedPopupAllowSite,
 | 
						|
          "popups-infobar-allow",
 | 
						|
          { uriHost }
 | 
						|
        );
 | 
						|
        blockedPopupAllowSite.removeAttribute("block");
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      blockedPopupAllowSite.hidden = true;
 | 
						|
    }
 | 
						|
 | 
						|
    let blockedPopupDontShowMessage = document.getElementById(
 | 
						|
      "blockedPopupDontShowMessage"
 | 
						|
    );
 | 
						|
    let showMessage = Services.prefs.getBoolPref(
 | 
						|
      "privacy.popups.showBrowserMessage"
 | 
						|
    );
 | 
						|
    blockedPopupDontShowMessage.setAttribute("checked", !showMessage);
 | 
						|
 | 
						|
    let blockedPopupsSeparator = document.getElementById(
 | 
						|
      "blockedPopupsSeparator"
 | 
						|
    );
 | 
						|
    blockedPopupsSeparator.hidden = true;
 | 
						|
 | 
						|
    browser.popupBlocker.getBlockedPopups().then(blockedPopups => {
 | 
						|
      let foundUsablePopupURI = false;
 | 
						|
      if (blockedPopups) {
 | 
						|
        for (let i = 0; i < blockedPopups.length; i++) {
 | 
						|
          let blockedPopup = blockedPopups[i];
 | 
						|
 | 
						|
          // popupWindowURI will be null if the file picker popup is blocked.
 | 
						|
          // xxxdz this should make the option say "Show file picker" and do it (Bug 590306)
 | 
						|
          if (!blockedPopup.popupWindowURISpec) {
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          var popupURIspec = blockedPopup.popupWindowURISpec;
 | 
						|
 | 
						|
          // Sometimes the popup URI that we get back from the blockedPopup
 | 
						|
          // isn't useful (for instance, netscape.com's popup URI ends up
 | 
						|
          // being "http://www.netscape.com", which isn't really the URI of
 | 
						|
          // the popup they're trying to show).  This isn't going to be
 | 
						|
          // useful to the user, so we won't create a menu item for it.
 | 
						|
          if (
 | 
						|
            popupURIspec == "" ||
 | 
						|
            popupURIspec == "about:blank" ||
 | 
						|
            popupURIspec == "<self>" ||
 | 
						|
            popupURIspec == uriOrPrincipal.spec
 | 
						|
          ) {
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          // Because of the short-circuit above, we may end up in a situation
 | 
						|
          // in which we don't have any usable popup addresses to show in
 | 
						|
          // the menu, and therefore we shouldn't show the separator.  However,
 | 
						|
          // since we got past the short-circuit, we must've found at least
 | 
						|
          // one usable popup URI and thus we'll turn on the separator later.
 | 
						|
          foundUsablePopupURI = true;
 | 
						|
 | 
						|
          var menuitem = document.createXULElement("menuitem");
 | 
						|
          document.l10n.setAttributes(menuitem, "popup-show-popup-menuitem", {
 | 
						|
            popupURI: popupURIspec,
 | 
						|
          });
 | 
						|
          menuitem.setAttribute("popupReportIndex", i);
 | 
						|
          menuitem.setAttribute(
 | 
						|
            "popupInnerWindowId",
 | 
						|
            blockedPopup.innerWindowId
 | 
						|
          );
 | 
						|
          menuitem.browsingContext = blockedPopup.browsingContext;
 | 
						|
          menuitem.popupReportBrowser = browser;
 | 
						|
          aEvent.target.appendChild(menuitem);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // Show the separator if we added any
 | 
						|
      // showable popup addresses to the menu.
 | 
						|
      if (foundUsablePopupURI) {
 | 
						|
        blockedPopupsSeparator.removeAttribute("hidden");
 | 
						|
      }
 | 
						|
    }, null);
 | 
						|
  },
 | 
						|
 | 
						|
  onPopupHiding(aEvent) {
 | 
						|
    let item = aEvent.target.lastElementChild;
 | 
						|
    while (item && item.id != "blockedPopupsSeparator") {
 | 
						|
      let next = item.previousElementSibling;
 | 
						|
      item.remove();
 | 
						|
      item = next;
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  showBlockedPopup(aEvent) {
 | 
						|
    let target = aEvent.target;
 | 
						|
    let browsingContext = target.browsingContext;
 | 
						|
    let innerWindowId = target.getAttribute("popupInnerWindowId");
 | 
						|
    let popupReportIndex = target.getAttribute("popupReportIndex");
 | 
						|
    let browser = target.popupReportBrowser;
 | 
						|
    browser.popupBlocker.unblockPopup(
 | 
						|
      browsingContext,
 | 
						|
      innerWindowId,
 | 
						|
      popupReportIndex
 | 
						|
    );
 | 
						|
  },
 | 
						|
 | 
						|
  editPopupSettings(aEvent) {
 | 
						|
    let window = aEvent.originalTarget.ownerGlobal;
 | 
						|
    let { openPreferences } = window;
 | 
						|
    openPreferences("privacy-permissions-block-popups");
 | 
						|
  },
 | 
						|
 | 
						|
  dontShowMessage(aEvent) {
 | 
						|
    let window = aEvent.originalTarget.ownerGlobal;
 | 
						|
    let { gBrowser } = window;
 | 
						|
    var showMessage = Services.prefs.getBoolPref(
 | 
						|
      "privacy.popups.showBrowserMessage"
 | 
						|
    );
 | 
						|
    Services.prefs.setBoolPref(
 | 
						|
      "privacy.popups.showBrowserMessage",
 | 
						|
      !showMessage
 | 
						|
    );
 | 
						|
    gBrowser.getNotificationBox().removeCurrentNotification();
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
XPCOMUtils.defineLazyPreferenceGetter(
 | 
						|
  PopupBlockerObserver,
 | 
						|
  "maxReportedPopups",
 | 
						|
  "privacy.popups.maxReported"
 | 
						|
);
 |