bug 1531924 - remove unnecessary nsIBadCertListener2 in Firefox for Android and improve adding certificate error overrides r=snorp
authorDana Keeler <dkeeler@mozilla.com>
Wed, 06 Mar 2019 20:46:32 +0000
changeset 520581 3898fa37cfda0fa56faea0217b5b1a4b23e5ce8f
parent 520580 b954e5d0324ab00a6ccc5fa605181b18a0bab2d5
child 520582 6551636084e0652d785f4f9ff277cbe83bdf8cd7
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1531924
milestone67.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 1531924 - remove unnecessary nsIBadCertListener2 in Firefox for Android and improve adding certificate error overrides r=snorp Before this patch, Firefox for Android (and GeckoView) would make an extra (unnecessary) XHR to gather the information it needed to add a certificate error override. However, the docShell already has the required information (via failedChannel.securityInfo), so this patch makes it so. Differential Revision: https://phabricator.services.mozilla.com/D21791
mobile/android/chrome/content/browser.js
mobile/android/chrome/geckoview/ErrorPageEventHandler.js
mobile/android/modules/SSLExceptions.jsm
mobile/android/modules/moz.build
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -54,19 +54,16 @@ ChromeUtils.defineModuleGetter(this, "Sa
                                "resource://gre/modules/Sanitizer.jsm");
 
 ChromeUtils.defineModuleGetter(this, "Prompt",
                                "resource://gre/modules/Prompt.jsm");
 
 ChromeUtils.defineModuleGetter(this, "HelperApps",
                                "resource://gre/modules/HelperApps.jsm");
 
-ChromeUtils.defineModuleGetter(this, "SSLExceptions",
-                               "resource://gre/modules/SSLExceptions.jsm");
-
 ChromeUtils.defineModuleGetter(this, "FormHistory",
                                "resource://gre/modules/FormHistory.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 if (AppConstants.MOZ_ENABLE_PROFILER_SPS) {
@@ -5043,28 +5040,37 @@ var ErrorPageEventHandler = {
 
         // If the event came from an ssl error page, it is probably either the "Add
         // Exception…" or "Get me out of here!" button
         if (errorDoc.documentURI.startsWith("about:certerror?e=nssBadCert")) {
           let perm = errorDoc.getElementById("permanentExceptionButton");
           let temp = errorDoc.getElementById("temporaryExceptionButton");
           if (target == temp || target == perm) {
             // Handle setting an cert exception and reloading the page
-            try {
-              // Add a new SSL exception for this URL
-              let uri = Services.io.newURI(errorDoc.location.href);
-              let sslExceptions = new SSLExceptions();
-
-              if (target == perm)
-                sslExceptions.addPermanentException(uri, errorDoc.defaultView);
-              else
-                sslExceptions.addTemporaryException(uri, errorDoc.defaultView);
-            } catch (e) {
-              dump("Failed to set cert exception: " + e + "\n");
+            let uri = Services.io.newURI(errorDoc.location.href);
+            let docShell = BrowserApp.selectedBrowser.docShell;
+            let securityInfo = docShell.failedChannel.securityInfo;
+            securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
+            let cert = securityInfo.serverCert;
+            let overrideService = Cc["@mozilla.org/security/certoverride;1"]
+                                    .getService(Ci.nsICertOverrideService);
+            let flags = 0;
+            if (securityInfo.isUntrusted) {
+              flags |= overrideService.ERROR_UNTRUSTED;
             }
+            if (securityInfo.isDomainMismatch) {
+              flags |= overrideService.ERROR_MISMATCH;
+            }
+            if (securityInfo.isNotValidAtThisTime) {
+              flags |= overrideService.ERROR_TIME;
+            }
+            let temporary = (target == temp) ||
+                            PrivateBrowsingUtils.isWindowPrivate(errorDoc.defaultView);
+            overrideService.rememberValidityOverride(uri.asciiHost, uri.port, cert, flags,
+                                                     temporary);
             errorDoc.location.reload();
           } else if (target == errorDoc.getElementById("getMeOutOfHereButton")) {
             errorDoc.location = "about:home";
           }
         } else if (errorDoc.documentURI.startsWith("about:blocked")) {
           // The event came from a button on a malware/phishing block page
           // First check whether it's malware, phishing or unwanted, so that we
           // can use the right strings/links
--- a/mobile/android/chrome/geckoview/ErrorPageEventHandler.js
+++ b/mobile/android/chrome/geckoview/ErrorPageEventHandler.js
@@ -1,22 +1,20 @@
 /* -*- 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/. */
 
 const {GeckoViewUtils} = ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
+const {PrivateBrowsingUtils} = ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const {debug, warn} = GeckoViewUtils.initLogging("ErrorPageEventHandler"); // eslint-disable-line no-unused-vars
 
-ChromeUtils.defineModuleGetter(this, "SSLExceptions",
-                               "resource://gre/modules/SSLExceptions.jsm");
-
 XPCOMUtils.defineLazyModuleGetters(this, {
   Services: "resource://gre/modules/Services.jsm",
 });
 
 var EXPORTED_SYMBOLS = ["ErrorPageEventHandler"];
 
 var ErrorPageEventHandler = {
   handleEvent: function(aEvent) {
@@ -30,29 +28,38 @@ var ErrorPageEventHandler = {
         let errorDoc = target.ownerDocument;
 
         // If the event came from an ssl error page, it is probably either the "Add
         // Exception…" or "Get me out of here!" button
         if (errorDoc.documentURI.startsWith("about:certerror?e=nssBadCert")) {
           let perm = errorDoc.getElementById("permanentExceptionButton");
           let temp = errorDoc.getElementById("temporaryExceptionButton");
           if (target == temp || target == perm) {
-            // Handle setting a cert exception and reloading the page
-            try {
-              // Add a new SSL exception for this URL
-              let uri = Services.io.newURI(errorDoc.location.href);
-              let sslExceptions = new SSLExceptions();
-
-              if (target == perm)
-                sslExceptions.addPermanentException(uri, errorDoc.defaultView);
-              else
-                sslExceptions.addTemporaryException(uri, errorDoc.defaultView);
-            } catch (e) {
-              warn `Failed to set cert exception: ${e}`;
+            // Handle setting an cert exception and reloading the page
+            let uri = Services.io.newURI(errorDoc.location.href);
+            let docShell = BrowserApp.selectedBrowser.docShell;
+            let securityInfo = docShell.failedChannel.securityInfo;
+            securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
+            let cert = securityInfo.serverCert;
+            let overrideService = Cc["@mozilla.org/security/certoverride;1"]
+                                    .getService(Ci.nsICertOverrideService);
+            let flags = 0;
+            if (securityInfo.isUntrusted) {
+              flags |= overrideService.ERROR_UNTRUSTED;
             }
+            if (securityInfo.isDomainMismatch) {
+              flags |= overrideService.ERROR_MISMATCH;
+            }
+            if (securityInfo.isNotValidAtThisTime) {
+              flags |= overrideService.ERROR_TIME;
+            }
+            let temporary = (target == temp) ||
+                            PrivateBrowsingUtils.isWindowPrivate(errorDoc.defaultView);
+            overrideService.rememberValidityOverride(uri.asciiHost, uri.port, cert, flags,
+                                                     temporary);
             errorDoc.location.reload();
           } else if (target == errorDoc.getElementById("getMeOutOfHereButton")) {
             errorDoc.location = "about:home";
           }
         }
         break;
       }
     }
deleted file mode 100644
--- a/mobile/android/modules/SSLExceptions.jsm
+++ /dev/null
@@ -1,113 +0,0 @@
-/* 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";
-
-const {PrivateBrowsingUtils} = ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGlobalGetters(this, ["XMLHttpRequest"]);
-
-var EXPORTED_SYMBOLS = ["SSLExceptions"];
-
-/**
-  A class to add exceptions to override SSL certificate problems. The functionality
-  itself is borrowed from exceptionDialog.js.
-*/
-function SSLExceptions() {
-  this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
-                          .getService(Ci.nsICertOverrideService);
-}
-
-
-SSLExceptions.prototype = {
-  _overrideService: null,
-  _secInfo: null,
-
-  getInterface: function SSLE_getInterface(aIID) {
-    return this.QueryInterface(aIID);
-  },
-  QueryInterface: ChromeUtils.generateQI(["nsIBadCertListener2"]),
-
-  /**
-    To collect the SSL status we intercept the certificate error here
-    and store the status for later use.
-  */
-  notifyCertProblem: function SSLE_notifyCertProblem(socketInfo,
-                                                     secInfo,
-                                                     targetHost) {
-    this._secInfo = secInfo;
-    return true; // suppress error UI
-  },
-
-  /**
-    Attempt to download the certificate for the location specified to get the SSLState
-    for the certificate and the errors.
-   */
-  _checkCert: function SSLE_checkCert(aURI) {
-    this._secInfo = null;
-
-    let req = new XMLHttpRequest();
-    try {
-      if (aURI) {
-        req.open("GET", aURI.prePath, false);
-        req.channel.notificationCallbacks = this;
-        req.send(null);
-      }
-    } catch (e) {
-      // We *expect* exceptions if there are problems with the certificate
-      // presented by the site.  Log it, just in case, but we can proceed here,
-      // with appropriate sanity checks
-      Cu.reportError("Attempted to connect to a site with a bad certificate in the add exception dialog. " +
-                     "This results in a (mostly harmless) exception being thrown. " +
-                     "Logged for information purposes only: " + e);
-    }
-
-    return this._secInfo;
-  },
-
-  /**
-    Internal method to create an override.
-  */
-  _addOverride: function SSLE_addOverride(aURI, aWindow, aTemporary) {
-    let secInfo = this._checkCert(aURI);
-    let certificate = secInfo.serverCert;
-
-    let flags = 0;
-
-    // in private browsing do not store exceptions permanently ever
-    if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
-      aTemporary = true;
-    }
-
-    if (secInfo.isUntrusted)
-      flags |= this._overrideService.ERROR_UNTRUSTED;
-    if (secInfo.isDomainMismatch)
-      flags |= this._overrideService.ERROR_MISMATCH;
-    if (secInfo.isNotValidAtThisTime)
-      flags |= this._overrideService.ERROR_TIME;
-
-    this._overrideService.rememberValidityOverride(
-      aURI.asciiHost,
-      aURI.port,
-      certificate,
-      flags,
-      aTemporary);
-  },
-
-  /**
-    Creates a permanent exception to override all overridable errors for
-    the given URL.
-  */
-  addPermanentException: function SSLE_addPermanentException(aURI, aWindow) {
-    this._addOverride(aURI, aWindow, false);
-  },
-
-  /**
-    Creates a temporary exception to override all overridable errors for
-    the given URL.
-  */
-  addTemporaryException: function SSLE_addTemporaryException(aURI, aWindow) {
-    this._addOverride(aURI, aWindow, true);
-  },
-};
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -37,12 +37,11 @@ EXTRA_JS_MODULES += [
     'Notifications.jsm',
     'PageActions.jsm',
     'Prompt.jsm',
     'RuntimePermissions.jsm',
     'Sanitizer.jsm',
     'SelectHelper.jsm',
     'SharedPreferences.jsm',
     'Snackbars.jsm',
-    'SSLExceptions.jsm',
     'WebrtcUI.jsm',
     'WebsiteMetadata.jsm'
 ]