Bug 1591474 - Port BlockedSite to JSWindowActors r=Gijs
authorJames Jahns <jahnsjam@msu.edu>
Mon, 18 Nov 2019 12:06:23 +0000
changeset 502401 7d5484728cf0e34482efccdcadb16482ee05f8f0
parent 502400 ff1c407a4421c71c1c60b2456d323dbd59747e67
child 502402 71bcb50a0a8c3298af53e98cd741700f5c3392d2
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1591474
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1591474 - Port BlockedSite to JSWindowActors r=Gijs These actors appear in about:blocked sites. Differential Revision: https://phabricator.services.mozilla.com/D51176
browser/actors/BlockedSiteChild.jsm
browser/actors/BlockedSiteParent.jsm
browser/actors/moz.build
browser/base/content/browser.js
browser/components/BrowserGlue.jsm
--- a/browser/actors/BlockedSiteChild.jsm
+++ b/browser/actors/BlockedSiteChild.jsm
@@ -2,19 +2,16 @@
 /* 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 { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var EXPORTED_SYMBOLS = ["BlockedSiteChild"];
 
-const { ActorChild } = ChromeUtils.import(
-  "resource://gre/modules/ActorChild.jsm"
-);
 ChromeUtils.defineModuleGetter(
   this,
   "E10SUtils",
   "resource://gre/modules/E10SUtils.jsm"
 );
 
 ChromeUtils.defineModuleGetter(
   this,
@@ -54,38 +51,36 @@ function getSiteBlockedErrorDetails(docS
         provider: classifiedChannel.matchedProvider,
         uri: reportUri.asciiSpec,
       };
     }
   }
   return blockedInfo;
 }
 
-class BlockedSiteChild extends ActorChild {
+class BlockedSiteChild extends JSWindowActorChild {
   receiveMessage(msg) {
     if (msg.name == "DeceptiveBlockedDetails") {
-      this.mm.sendAsyncMessage("DeceptiveBlockedDetails:Result", {
-        blockedInfo: getSiteBlockedErrorDetails(this.mm.docShell),
-      });
+      return getSiteBlockedErrorDetails(this.docShell);
     }
+    return null;
   }
 
   handleEvent(event) {
     if (event.type == "AboutBlockedLoaded") {
       this.onAboutBlockedLoaded(event);
     } else if (event.type == "click" && event.button == 0) {
       this.onClick(event);
     }
   }
 
   onAboutBlockedLoaded(aEvent) {
-    let global = this.mm;
     let content = aEvent.target.ownerGlobal;
 
-    let blockedInfo = getSiteBlockedErrorDetails(global.docShell);
+    let blockedInfo = getSiteBlockedErrorDetails(this.docShell);
     let provider = blockedInfo.provider || "";
 
     let doc = content.document;
 
     /**
      * Set error description link in error details.
      * For example, the "reported as a deceptive site" link for
      * blocked phishing pages.
@@ -196,17 +191,16 @@ class BlockedSiteChild extends ActorChil
     if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
       reason = "malware";
     } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
       reason = "unwanted";
     } else if (/e=harmfulBlocked/.test(ownerDoc.documentURI)) {
       reason = "harmful";
     }
 
-    this.mm.sendAsyncMessage("Browser:SiteBlockedError", {
+    this.sendAsyncMessage("Browser:SiteBlockedError", {
       location: ownerDoc.location.href,
       reason,
       elementId: event.target.getAttribute("id"),
-      isTopFrame: ownerDoc.defaultView.parent === ownerDoc.defaultView,
-      blockedInfo: getSiteBlockedErrorDetails(ownerDoc.defaultView.docShell),
+      blockedInfo: getSiteBlockedErrorDetails(this.docShell),
     });
   }
 }
new file mode 100644
--- /dev/null
+++ b/browser/actors/BlockedSiteParent.jsm
@@ -0,0 +1,73 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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/. */
+
+var EXPORTED_SYMBOLS = ["BlockedSiteParent"];
+var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+class BlockedSiteParent extends JSWindowActorParent {
+  receiveMessage(msg) {
+    switch (msg.name) {
+      case "Browser:SiteBlockedError":
+        this._onAboutBlocked(
+          msg.data.elementId,
+          msg.data.reason,
+          this.browsingContext === this.browsingContext.top,
+          msg.data.blockedInfo
+        );
+        break;
+    }
+  }
+
+  _onAboutBlocked(elementId, reason, isTopFrame, blockedInfo) {
+    let browser = this.browsingContext.top.embedderElement;
+    if (!browser) {
+      return;
+    }
+    let { BrowserOnClick } = browser.ownerGlobal;
+    // Depending on what page we are displaying here (malware/phishing/unwanted)
+    // use the right strings and links for each.
+    let bucketName = "";
+    let sendTelemetry = false;
+    if (reason === "malware") {
+      sendTelemetry = true;
+      bucketName = "WARNING_MALWARE_PAGE_";
+    } else if (reason === "phishing") {
+      sendTelemetry = true;
+      bucketName = "WARNING_PHISHING_PAGE_";
+    } else if (reason === "unwanted") {
+      sendTelemetry = true;
+      bucketName = "WARNING_UNWANTED_PAGE_";
+    } else if (reason === "harmful") {
+      sendTelemetry = true;
+      bucketName = "WARNING_HARMFUL_PAGE_";
+    }
+    let secHistogram = Services.telemetry.getHistogramById(
+      "URLCLASSIFIER_UI_EVENTS"
+    );
+    let nsISecTel = Ci.IUrlClassifierUITelemetry;
+    bucketName += isTopFrame ? "TOP_" : "FRAME_";
+
+    switch (elementId) {
+      case "goBackButton":
+        if (sendTelemetry) {
+          secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
+        }
+        browser.ownerGlobal.getMeOutOfHere(this.browsingContext);
+        break;
+      case "ignore_warning_link":
+        if (Services.prefs.getBoolPref("browser.safebrowsing.allowOverride")) {
+          if (sendTelemetry) {
+            secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
+          }
+          BrowserOnClick.ignoreWarningLink(
+            reason,
+            blockedInfo,
+            this.browsingContext
+          );
+        }
+        break;
+    }
+  }
+}
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -20,16 +20,17 @@ with Files("PluginChild.jsm"):
     BUG_COMPONENT = ("Core", "Plug-ins")
 
 with Files("WebRTCChild.jsm"):
     BUG_COMPONENT = ("Firefox", "Site Permissions")
 
 FINAL_TARGET_FILES.actors += [
     'AboutReaderChild.jsm',
     'BlockedSiteChild.jsm',
+    'BlockedSiteParent.jsm',
     'BrowserTabChild.jsm',
     'BrowserTabParent.jsm',
     'ClickHandlerChild.jsm',
     'ContentMetaChild.jsm',
     'ContentMetaParent.jsm',
     'ContentSearchChild.jsm',
     'ContextMenuChild.jsm',
     'ContextMenuParent.jsm',
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1803,17 +1803,16 @@ var gBrowserInit = {
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
 
     // These routines add message listeners. They must run before
     // loading the frame script to ensure that we don't miss any
     // message sent between when the frame script is loaded and when
     // the listener is registered.
     LanguageDetectionListener.init();
-    BrowserOnClick.init();
     CaptivePortalWatcher.init();
     ZoomUI.init(window);
 
     let mm = window.getGroupMessageManager("browsers");
     mm.loadFrameScript("chrome://browser/content/tab-content.js", true, true);
 
     window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
 
@@ -2442,18 +2441,16 @@ var gBrowserInit = {
     PlacesToolbarHelper.uninit();
 
     BookmarkingUI.uninit();
 
     TabletModeUpdater.uninit();
 
     gTabletModePageCounter.finish();
 
-    BrowserOnClick.uninit();
-
     CaptivePortalWatcher.uninit();
 
     SidebarUI.uninit();
 
     DownloadsButton.uninit();
 
     gAccessibilityServiceIndicator.uninit();
 
@@ -3493,100 +3490,34 @@ const SEC_ERROR_UNKNOWN_ISSUER = SEC_ERR
 const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
 
 /**
  * Handle command events bubbling up from error page content
  * or from about:newtab or from remote error pages that invoke
  * us via async messaging.
  */
 var BrowserOnClick = {
-  init() {
-    let mm = window.messageManager;
-    mm.addMessageListener("Browser:SiteBlockedError", this);
-  },
-
-  uninit() {
-    let mm = window.messageManager;
-    mm.removeMessageListener("Browser:SiteBlockedError", this);
-  },
-
-  receiveMessage(msg) {
-    switch (msg.name) {
-      case "Browser:SiteBlockedError":
-        this.onAboutBlocked(
-          msg.data.elementId,
-          msg.data.reason,
-          msg.data.isTopFrame,
-          msg.data.location,
-          msg.data.blockedInfo
-        );
-        break;
-    }
-  },
-
-  onAboutBlocked(elementId, reason, isTopFrame, location, blockedInfo) {
-    // Depending on what page we are displaying here (malware/phishing/unwanted)
-    // use the right strings and links for each.
-    let bucketName = "";
-    let sendTelemetry = false;
-    if (reason === "malware") {
-      sendTelemetry = true;
-      bucketName = "WARNING_MALWARE_PAGE_";
-    } else if (reason === "phishing") {
-      sendTelemetry = true;
-      bucketName = "WARNING_PHISHING_PAGE_";
-    } else if (reason === "unwanted") {
-      sendTelemetry = true;
-      bucketName = "WARNING_UNWANTED_PAGE_";
-    } else if (reason === "harmful") {
-      sendTelemetry = true;
-      bucketName = "WARNING_HARMFUL_PAGE_";
-    }
-    let secHistogram = Services.telemetry.getHistogramById(
-      "URLCLASSIFIER_UI_EVENTS"
-    );
-    let nsISecTel = Ci.IUrlClassifierUITelemetry;
-    bucketName += isTopFrame ? "TOP_" : "FRAME_";
-
-    switch (elementId) {
-      case "goBackButton":
-        if (sendTelemetry) {
-          secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
-        }
-        getMeOutOfHere();
-        break;
-      case "ignore_warning_link":
-        if (Services.prefs.getBoolPref("browser.safebrowsing.allowOverride")) {
-          if (sendTelemetry) {
-            secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
-          }
-          this.ignoreWarningLink(reason, blockedInfo);
-        }
-        break;
-    }
-  },
-
-  ignoreWarningLink(reason, blockedInfo) {
+  ignoreWarningLink(reason, blockedInfo, browsingContext) {
     let triggeringPrincipal = E10SUtils.deserializePrincipal(
       blockedInfo.triggeringPrincipal,
       _createNullPrincipalFromTabUserContextId()
     );
     // Allow users to override and continue through to the site,
     // but add a notify bar as a reminder, so that they don't lose
     // track after, e.g., tab switching.
-    gBrowser.loadURI(gBrowser.currentURI.spec, {
+    browsingContext.loadURI(blockedInfo.uri, {
       triggeringPrincipal,
       flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
     });
 
-    // We can't use gBrowser.contentPrincipal which is principal of about:blocked
+    // We can't use browser.contentPrincipal which is principal of about:blocked
     // Create one from uri with current principal origin attributes
     let principal = Services.scriptSecurityManager.createContentPrincipal(
-      gBrowser.currentURI,
-      gBrowser.contentPrincipal.originAttributes
+      Services.io.newURI(blockedInfo.uri),
+      browsingContext.currentWindowGlobal.documentPrincipal.originAttributes
     );
     Services.perms.addFromPrincipal(
       principal,
       "safe-browsing",
       Ci.nsIPermissionManager.ALLOW_ACTION,
       Ci.nsIPermissionManager.EXPIRE_SESSION
     );
 
@@ -3594,17 +3525,17 @@ var BrowserOnClick = {
       {
         label: gNavigatorBundle.getString(
           "safebrowsing.getMeOutOfHereButton.label"
         ),
         accessKey: gNavigatorBundle.getString(
           "safebrowsing.getMeOutOfHereButton.accessKey"
         ),
         callback() {
-          getMeOutOfHere();
+          getMeOutOfHere(browsingContext);
         },
       },
     ];
 
     let title;
     if (reason === "malware") {
       let reportUrl = gSafeBrowsing.getReportURL("MalwareMistake", blockedInfo);
       title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
@@ -3657,18 +3588,18 @@ var BrowserOnClick = {
 
 /**
  * Re-direct the browser to a known-safe page.  This function is
  * used when, for example, the user browses to a known malware page
  * and is presented with about:blocked.  The "Get me out of here!"
  * button should take the user to the default start page so that even
  * when their own homepage is infected, we can get them somewhere safe.
  */
-function getMeOutOfHere() {
-  gBrowser.loadURI(getDefaultHomePage(), {
+function getMeOutOfHere(browsingContext) {
+  browsingContext.top.loadURI(getDefaultHomePage(), {
     triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), // Also needs to load homepage
   });
 }
 
 /**
  * Return the default start page for the cases when the user's own homepage is
  * infected, so we can get them somewhere safe.
  */
@@ -8418,46 +8349,51 @@ function checkEmptyPageOrigin(
   }
   // ... so for those that don't have them, enforce that the page has the
   // system principal (this matches e.g. on about:newtab).
 
   return contentPrincipal.isSystemPrincipal;
 }
 
 function ReportFalseDeceptiveSite() {
-  let docURI = gBrowser.selectedBrowser.documentURI;
-  let isPhishingPage =
-    docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
-
-  if (isPhishingPage) {
-    let mm = gBrowser.selectedBrowser.messageManager;
-    let onMessage = message => {
-      mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
-      let reportUrl = gSafeBrowsing.getReportURL(
-        "PhishMistake",
-        message.data.blockedInfo
-      );
-      if (reportUrl) {
-        openTrustedLinkIn(reportUrl, "tab");
-      } else {
-        let bundle = Services.strings.createBundle(
-          "chrome://browser/locale/safebrowsing/safebrowsing.properties"
+  let contextsToVisit = [gBrowser.selectedBrowser.browsingContext];
+  while (contextsToVisit.length) {
+    let currentContext = contextsToVisit.pop();
+    let global = currentContext.currentWindowGlobal;
+
+    if (!global) {
+      continue;
+    }
+    let docURI = global.documentURI;
+    // Ensure the page is an about:blocked pagae before handling.
+    if (docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked")) {
+      let actor = global.getActor("BlockedSite");
+      actor.sendQuery("DeceptiveBlockedDetails").then(data => {
+        let reportUrl = gSafeBrowsing.getReportURL(
+          "PhishMistake",
+          data.blockedInfo
         );
-        Services.prompt.alert(
-          window,
-          bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
-          bundle.formatStringFromName("errorReportFalseDeceptiveMessage", [
-            message.data.blockedInfo.provider,
-          ])
-        );
-      }
-    };
-    mm.addMessageListener("DeceptiveBlockedDetails:Result", onMessage);
-
-    mm.sendAsyncMessage("DeceptiveBlockedDetails");
+        if (reportUrl) {
+          openTrustedLinkIn(reportUrl, "tab");
+        } else {
+          let bundle = Services.strings.createBundle(
+            "chrome://browser/locale/safebrowsing/safebrowsing.properties"
+          );
+          Services.prompt.alert(
+            window,
+            bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
+            bundle.formatStringFromName("errorReportFalseDeceptiveMessage", [
+              data.blockedInfo.provider,
+            ])
+          );
+        }
+      });
+    }
+
+    contextsToVisit.push(...currentContext.getChildren());
   }
 }
 
 /**
  * Format a URL
  * eg:
  * echo formatURL("https://addons.mozilla.org/%LOCALE%/%APP%/%VERSION%/");
  * > https://addons.mozilla.org/en-US/firefox/3.0a1/
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -36,16 +36,31 @@ XPCOMUtils.defineLazyServiceGetter(
 const PREF_PDFJS_ENABLED_CACHE_STATE = "pdfjs.enabledCache.state";
 
 /**
  * Fission-compatible JSWindowActor implementations.
  * Detailed documentation of these is in dom/docs/Fission.rst,
  * available at https://firefox-source-docs.mozilla.org/dom/Fission.html#jswindowactor
  */
 let ACTORS = {
+  BlockedSite: {
+    parent: {
+      moduleURI: "resource:///actors/BlockedSiteParent.jsm",
+    },
+    child: {
+      moduleURI: "resource:///actors/BlockedSiteChild.jsm",
+      events: {
+        AboutBlockedLoaded: { wantUntrusted: true },
+        click: {},
+      },
+    },
+    matches: ["about:blocked?*"],
+    allFrames: true,
+  },
+
   BrowserTab: {
     parent: {
       moduleURI: "resource:///actors/BrowserTabParent.jsm",
     },
     child: {
       moduleURI: "resource:///actors/BrowserTabChild.jsm",
 
       events: {
@@ -295,29 +310,16 @@ let LEGACY_ACTORS = {
         DOMContentLoaded: {},
         pageshow: { mozSystemGroup: true },
         pagehide: { mozSystemGroup: true },
       },
       messages: ["Reader:ToggleReaderMode", "Reader:PushState"],
     },
   },
 
-  BlockedSite: {
-    child: {
-      module: "resource:///actors/BlockedSiteChild.jsm",
-      events: {
-        AboutBlockedLoaded: { wantUntrusted: true },
-        click: {},
-      },
-      matches: ["about:blocked?*"],
-      allFrames: true,
-      messages: ["DeceptiveBlockedDetails"],
-    },
-  },
-
   ClickHandler: {
     child: {
       module: "resource:///actors/ClickHandlerChild.jsm",
       events: {
         click: { capture: true, mozSystemGroup: true },
         auxclick: { capture: true, mozSystemGroup: true },
       },
     },