bug 1284946 - remove usages-related APIs from nsIX509Cert r=Cykesiopka,Felipe,jcj
authorDavid Keeler <dkeeler@mozilla.com>
Wed, 06 Jul 2016 14:45:36 -0700
changeset 305432 3d09e38954064b41dbc0a9387b5c5a205bf21e15
parent 305431 595bfede9d26e9dba03495fdcf29d4423a996146
child 305433 af5a866739e96c1c9399e79c17ddea87e4a9c013
push id30463
push usercbook@mozilla.com
push dateTue, 19 Jul 2016 14:02:45 +0000
treeherdermozilla-central@37cc0da01187 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCykesiopka, Felipe, jcj
bugs1284946
milestone50.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 1284946 - remove usages-related APIs from nsIX509Cert r=Cykesiopka,Felipe,jcj nsIX509Cert provided the APIs getUsagesArray, requestUsagesArrayAsync, and getUsagesString. These APIs were problematic in that the synchronous ones would cause certificate verification to block the main thread and the asynchronous one was needlessly indirect in its definition (it made use of two additional special-case xpidl types) and needlessly complex in its implementation (it required nsNSSComponent to manually manage a background thread without the aid of recent improvements in that area (e.g. CryptoTask)). Furthermore, these APIs would return string descriptions of the usages the certificate in question had been verified for rather than using more concrete identifiers or values. This paradigm is usable but imprecise. The new nsIX509CertDB API asyncVerifyCertAtTime is much more expressive, enforces off-main-thread computation, and makes use of CryptoTask for a simple implementation. Using this API, previous uses of the old nsIX509Cert APIs can be replaced. As an additional benefit, this removes a ton of obsolete C++ code. MozReview-Commit-ID: KXVTcjAKehu
security/manager/locales/en-US/chrome/pipnss/pipnss.properties
security/manager/pki/resources/content/viewCertDetails.js
security/manager/ssl/moz.build
security/manager/ssl/nsCertTree.cpp
security/manager/ssl/nsCertVerificationThread.cpp
security/manager/ssl/nsCertVerificationThread.h
security/manager/ssl/nsIX509Cert.idl
security/manager/ssl/nsNSSCertificate.cpp
security/manager/ssl/nsNSSCertificateFakeTransport.cpp
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/nsNSSComponent.h
security/manager/ssl/nsUsageArrayHelper.cpp
security/manager/ssl/nsUsageArrayHelper.h
security/manager/ssl/tests/mochitest/browser/browser.ini
security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
security/manager/ssl/tests/mochitest/browser/ca.pem
security/manager/ssl/tests/mochitest/browser/ca.pem.certspec
security/manager/ssl/tests/mochitest/browser/code-ee.pem
security/manager/ssl/tests/mochitest/browser/code-ee.pem.certspec
security/manager/ssl/tests/mochitest/browser/ee-from-expired-ca.pem
security/manager/ssl/tests/mochitest/browser/ee-from-expired-ca.pem.certspec
security/manager/ssl/tests/mochitest/browser/ee-from-untrusted-ca.pem
security/manager/ssl/tests/mochitest/browser/ee-from-untrusted-ca.pem.certspec
security/manager/ssl/tests/mochitest/browser/email-ee.pem
security/manager/ssl/tests/mochitest/browser/email-ee.pem.certspec
security/manager/ssl/tests/mochitest/browser/expired-ca.pem
security/manager/ssl/tests/mochitest/browser/expired-ca.pem.certspec
security/manager/ssl/tests/mochitest/browser/invalid.pem
security/manager/ssl/tests/mochitest/browser/invalid.pem.certspec
security/manager/ssl/tests/mochitest/browser/md5-ee.pem
security/manager/ssl/tests/mochitest/browser/md5-ee.pem.certspec
security/manager/ssl/tests/mochitest/browser/moz.build
security/manager/ssl/tests/mochitest/browser/revoked.pem
security/manager/ssl/tests/mochitest/browser/revoked.pem.certspec
security/manager/ssl/tests/mochitest/browser/ssl-ee.pem
security/manager/ssl/tests/mochitest/browser/ssl-ee.pem.certspec
security/manager/ssl/tests/mochitest/browser/unknown-issuer.pem
security/manager/ssl/tests/mochitest/browser/unknown-issuer.pem.certspec
security/manager/ssl/tests/mochitest/browser/untrusted-ca.pem
security/manager/ssl/tests/mochitest/browser/untrusted-ca.pem.certspec
testing/mochitest/browser.eslintrc
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -39,18 +39,16 @@ Fips140SlotDescription=FIPS 140 Cryptogr
 InternalToken=Software Security Device
 # End of size restriction.
 VerifySSLClient=SSL Client Certificate
 VerifySSLServer=SSL Server Certificate
 VerifySSLCA=SSL Certificate Authority
 VerifyEmailSigner=Email Signer Certificate
 VerifyEmailRecip=Email Recipient Certificate
 VerifyObjSign=Object Signer
-VerifyCAVerifier=CA Verifier
-VerifyStatusResponder=Status Responder Certificate
 HighGrade=High Grade
 MediumGrade=Medium Grade
 # LOCALIZATION NOTE (nick_template): $1s is the common name from a cert (e.g. "Mozilla"), $2s is the CA name (e.g. VeriSign)
 nick_template=%1$s’s %2$s ID
 #These are the strings set for the ASN1 objects in a certificate.
 CertDumpCertificate=Certificate
 CertDumpVersion=Version
 # LOCALIZATION NOTE (CertDumpVersionValue): %S is a version number (e.g. "3" in "Version 3")
@@ -233,24 +231,16 @@ CertDumpECsect233r1=SECG elliptic curve 
 CertDumpECsect239k1=SECG elliptic curve sect239k1
 CertDumpECsect283k1=SECG elliptic curve sect283k1 (aka NIST K-283)
 CertDumpECsect283r1=SECG elliptic curve sect283r1 (aka NIST B-283)
 CertDumpECsect409k1=SECG elliptic curve sect409k1 (aka NIST K-409)
 CertDumpECsect409r1=SECG elliptic curve sect409r1 (aka NIST B-409)
 CertDumpECsect571k1=SECG elliptic curve sect571k1 (aka NIST K-571)
 CertDumpECsect571r1=SECG elliptic curve sect571r1 (aka NIST B-571)
 CertDumpRawBytesHeader=Size: %S Bytes / %S Bits
-VerifySSLClient_p=Client
-VerifySSLServer_p=Server
-VerifySSLCA_p=SSL CA
-VerifyEmailSigner_p=Sign
-VerifyEmailRecip_p=Encrypt
-VerifyObjSign_p=Object Signer
-VerifyCAVerifier_p=CA Verifier
-VerifyStatusResponder_p=Status Responder
 PK11BadPassword=The password entered was incorrect.
 SuccessfulP12Backup=Successfully backed up your security certificate(s) and private key(s).
 SuccessfulP12Restore=Successfully restored your security certificate(s) and private key(s).
 PKCS12DecodeErr=Failed to decode the file.  Either it is not in PKCS #12 format, has been corrupted, or the password you entered was incorrect.
 PKCS12UnknownErrRestore=Failed to restore the PKCS #12 file for unknown reasons.
 PKCS12UnknownErrBackup=Failed to create the PKCS #12 backup file for unknown reasons.
 PKCS12UnknownErr=The PKCS #12 operation failed for unknown reasons.
 PKCS12InfoNoSmartcardBackup=It is not possible to back up certificates from a hardware security device such as a smart card.
@@ -297,28 +287,16 @@ CertInfoIssuedFor=Issued to:
 CertInfoIssuedBy=Issued by:
 CertInfoValid=Valid
 CertInfoFrom=from
 CertInfoTo=to
 CertInfoPurposes=Purposes
 CertInfoEmail=Email
 CertInfoStoredIn=Stored in:
 P12DefaultNickname=Imported Certificate
-VerifyExpired=<Expired>
-VerifyRevoked=<Revoked>
-VerifyNotTrusted=<Not Trusted>
-VerifyIssuerNotTrusted=<Issuer Not Trusted>
-VerifyIssuerUnknown=<Issuer Unknown>
-VerifyInvalidCA=<Invalid CA>
-VerifyDisabledAlgorithm=<Signature Algorithm Not Secure>
-VerifyUnknown=<Unknown>
-CertUser=Your Cert
-CertCA=CA (Certificate Authority)
-CertSSL=SSL Server
-CertEmail=Peer S/MIME
 CertUnknown=Unknown
 CertNoNickname=(no nickname)
 CertNoEmailAddress=(no email address)
 NicknameExpired=(expired)
 NicknameNotYetValid=(not yet valid)
 CaCertExists=This certificate is already installed as a certificate authority.
 NotACACert=This is not a certificate authority certificate, so it can’t be imported into the certificate authority list.
 NotImportingUnverifiedCert=This certificate can’t be verified and will not be imported. The certificate issuer might be unknown or untrusted, the certificate might have expired or been revoked, or the certificate might not have been approved.
--- a/security/manager/pki/resources/content/viewCertDetails.js
+++ b/security/manager/pki/resources/content/viewCertDetails.js
@@ -1,24 +1,27 @@
 /* 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 nsIX509Cert = Components.interfaces.nsIX509Cert;
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+
+const nsIX509Cert = Ci.nsIX509Cert;
 const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
-const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
+const nsIX509CertDB = Ci.nsIX509CertDB;
 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
-const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
-const nsIASN1Object = Components.interfaces.nsIASN1Object;
-const nsIASN1Sequence = Components.interfaces.nsIASN1Sequence;
-const nsIASN1PrintableItem = Components.interfaces.nsIASN1PrintableItem;
-const nsIASN1Tree = Components.interfaces.nsIASN1Tree;
+const nsIPK11TokenDB = Ci.nsIPK11TokenDB;
+const nsIASN1Object = Ci.nsIASN1Object;
+const nsIASN1Sequence = Ci.nsIASN1Sequence;
+const nsIASN1PrintableItem = Ci.nsIASN1PrintableItem;
+const nsIASN1Tree = Ci.nsIASN1Tree;
 const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1";
-const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
+const nsIDialogParamBlock = Ci.nsIDialogParamBlock;
 
 var bundle;
 
 function doPrompt(msg)
 {
   let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
     getService(Components.interfaces.nsIPromptService);
   prompts.alert(window, null, msg);
@@ -49,21 +52,20 @@ function AddCertChain(node, chain)
   }
 }
 
 /**
  * Adds a "verified usage" of a cert to the "General" tab of the cert viewer.
  *
  * @param {String} usage
  *        Verified usage to add.
- * @param {Node} verifyInfoBox
- *        Parent node to append to.
  */
-function AddUsage(usage, verifyInfoBox)
+function AddUsage(usage)
 {
+  let verifyInfoBox = document.getElementById("verify_info_box");
   let text = document.createElement("textbox");
   text.setAttribute("value", usage);
   text.setAttribute("style", "margin: 2px 5px");
   text.setAttribute("readonly", "true");
   text.setAttribute("class", "scrollfield");
   verifyInfoBox.appendChild(text);
 }
 
@@ -88,17 +90,150 @@ function setWindowName()
   //
   //  Set the cert attributes for viewing
   //
 
   //  The chain of trust
   AddCertChain("treesetDump", cert.getChain());
   DisplayGeneralDataFromCert(cert);
   BuildPrettyPrint(cert);
-  cert.requestUsagesArrayAsync(new listener());
+
+  asyncDetermineUsages(cert);
+}
+
+// Certificate usages we care about in the certificate viewer.
+const certificateUsageSSLClient              = 0x0001;
+const certificateUsageSSLServer              = 0x0002;
+const certificateUsageSSLCA                  = 0x0008;
+const certificateUsageEmailSigner            = 0x0010;
+const certificateUsageEmailRecipient         = 0x0020;
+const certificateUsageObjectSigner           = 0x0040;
+
+// A map from the name of a certificate usage to the value of the usage.
+// Useful for printing debugging information and for enumerating all supported
+// usages.
+const certificateUsages = {
+  certificateUsageSSLClient,
+  certificateUsageSSLServer,
+  certificateUsageSSLCA,
+  certificateUsageEmailSigner,
+  certificateUsageEmailRecipient,
+  certificateUsageObjectSigner,
+};
+
+// Map of certificate usage name to localization identifier.
+const certificateUsageToStringBundleName = {
+  certificateUsageSSLClient: "VerifySSLClient",
+  certificateUsageSSLServer: "VerifySSLServer",
+  certificateUsageSSLCA: "VerifySSLCA",
+  certificateUsageEmailSigner: "VerifyEmailSigner",
+  certificateUsageEmailRecipient: "VerifyEmailRecip",
+  certificateUsageObjectSigner: "VerifyObjSign",
+};
+
+const PRErrorCodeSuccess = 0;
+
+const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
+const SEC_ERROR_EXPIRED_CERTIFICATE                     = SEC_ERROR_BASE + 11;
+const SEC_ERROR_REVOKED_CERTIFICATE                     = SEC_ERROR_BASE + 12;
+const SEC_ERROR_UNKNOWN_ISSUER                          = SEC_ERROR_BASE + 13;
+const SEC_ERROR_UNTRUSTED_ISSUER                        = SEC_ERROR_BASE + 20;
+const SEC_ERROR_UNTRUSTED_CERT                          = SEC_ERROR_BASE + 21;
+const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE              = SEC_ERROR_BASE + 30;
+const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED       = SEC_ERROR_BASE + 176;
+
+/**
+ * Kicks off asynchronous verifications of the given certificate to determine
+ * what usages it is currently valid for. Updates the usage display area when
+ * complete.
+ *
+ * @param {nsIX509Cert} cert
+ *        The certificate to determine valid usages for.
+ */
+function asyncDetermineUsages(cert) {
+  let promises = [];
+  let now = Date.now() / 1000;
+  let certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                 .getService(Ci.nsIX509CertDB);
+  Object.keys(certificateUsages).forEach(usageString => {
+    promises.push(new Promise((resolve, reject) => {
+      let usage = certificateUsages[usageString];
+      certdb.asyncVerifyCertAtTime(cert, usage, 0, null, now,
+        (aPRErrorCode, aVerifiedChain, aHasEVPolicy) => {
+          resolve({ usageString: usageString, errorCode: aPRErrorCode });
+        });
+    }));
+  });
+  Promise.all(promises).then(displayUsages);
+}
+
+/**
+ * Updates the usage display area given the results from asyncDetermineUsages.
+ *
+ * @param {Array} results
+ *        An array of objects with the properties "usageString" and "errorCode".
+ *        usageString is a string that is a key in the certificateUsages map.
+ *        errorCode is either an NSPR error code or PRErrorCodeSuccess (which is
+ *        a pseudo-NSPR error code with the value 0 that indicates success).
+ */
+function displayUsages(results) {
+  document.getElementById("verify_pending").setAttribute("hidden", "true");
+  let verified = document.getElementById("verified");
+  let someSuccess = results.some(result =>
+    result.errorCode == PRErrorCodeSuccess
+  );
+  if (someSuccess) {
+    let verifystr = bundle.getString("certVerified");
+    verified.textContent = verifystr;
+    let pipnssBundle = Services.strings.createBundle(
+      "chrome://pipnss/locale/pipnss.properties");
+    results.forEach(result => {
+      if (result.errorCode != PRErrorCodeSuccess) {
+        return;
+      }
+      let bundleName = certificateUsageToStringBundleName[result.usageString];
+      let usage = pipnssBundle.GetStringFromName(bundleName);
+      AddUsage(usage);
+    });
+  } else {
+    const errorRankings = [
+      { error: SEC_ERROR_REVOKED_CERTIFICATE,
+        bundleString: "certNotVerified_CertRevoked" },
+      { error: SEC_ERROR_UNTRUSTED_CERT,
+        bundleString: "certNotVerified_CertNotTrusted" },
+      { error: SEC_ERROR_UNTRUSTED_ISSUER,
+        bundleString: "certNotVerified_IssuerNotTrusted" },
+      { error: SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
+        bundleString: "certNotVerified_AlgorithmDisabled" },
+      { error: SEC_ERROR_EXPIRED_CERTIFICATE,
+        bundleString: "certNotVerified_CertExpired" },
+      { error: SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE,
+        bundleString: "certNotVerified_CAInvalid" },
+      { error: SEC_ERROR_UNKNOWN_ISSUER,
+        bundleString: "certNotVerified_IssuerUnknown" },
+    ];
+    let verifystr;
+    for (let errorRanking of errorRankings) {
+      let errorPresent = results.some(result =>
+        result.errorCode == errorRanking.error
+      );
+      if (errorPresent) {
+        verifystr = bundle.getString(errorRanking.bundleString);
+        break;
+      }
+    }
+    if (!verifystr) {
+      verifystr = bundle.getString("certNotVerified_Unknown");
+    }
+    verified.textContent = verifystr;
+  }
+  // Notify that we are done determining the certificate's valid usages (this
+  // should be treated as an implementation detail that enables tests to run
+  // efficiently - other code in the browser probably shouldn't rely on this).
+  Services.obs.notifyObservers(window, "ViewCertDetails:CertUsagesDone", null);
 }
 
 function addChildrenToTree(parentTree, label, value, addTwistie)
 {
   let treeChild1 = document.createElement("treechildren");
   let treeElement = addTreeItemToTreeChild(treeChild1, label, value,
                                            addTwistie);
   parentTree.appendChild(treeChild1);
@@ -149,92 +284,16 @@ function addAttributeFromCert(nodeName, 
 {
   var node = document.getElementById(nodeName);
   if (!value) {
     value = bundle.getString('notPresent');
   }
   node.setAttribute('value', value);
 }
 
-
-
-function listener() {
-}
-
-listener.prototype.QueryInterface =
-  function(iid) {
-    if (iid.equals(Components.interfaces.nsISupports) ||
-        iid.equals(Components.interfaces.nsICertVerificationListener)) {
-      return this;
-    }
-
-    throw new Error(Components.results.NS_ERROR_NO_INTERFACE);
-  };
-
-listener.prototype.notify =
-  function(cert, result) {
-    DisplayVerificationData(cert, result);
-  };
-
-function DisplayVerificationData(cert, result)
-{
-  document.getElementById("verify_pending").setAttribute("hidden", "true");
-
-  if (!result || !cert) {
-    return; // no results could be produced
-  }
-
-  if (!(cert instanceof Components.interfaces.nsIX509Cert)) {
-    return;
-  }
-
-  //  Verification and usage
-  var verifystr = "";
-  var o1 = {};
-  var o2 = {};
-  var o3 = {};
-
-  if (!(result instanceof Components.interfaces.nsICertVerificationResult)) {
-    return;
-  }
-
-  result.getUsagesArrayResult(o1, o2, o3);
-
-  var verifystate = o1.value;
-  var count = o2.value;
-  var usageList = o3.value;
-  if (verifystate == cert.VERIFIED_OK) {
-    verifystr = bundle.getString('certVerified');
-  } else if (verifystate == cert.CERT_REVOKED) {
-    verifystr = bundle.getString('certNotVerified_CertRevoked');
-  } else if (verifystate == cert.CERT_EXPIRED) {
-    verifystr = bundle.getString('certNotVerified_CertExpired');
-  } else if (verifystate == cert.CERT_NOT_TRUSTED) {
-    verifystr = bundle.getString('certNotVerified_CertNotTrusted');
-  } else if (verifystate == cert.ISSUER_NOT_TRUSTED) {
-    verifystr = bundle.getString('certNotVerified_IssuerNotTrusted');
-  } else if (verifystate == cert.ISSUER_UNKNOWN) {
-    verifystr = bundle.getString('certNotVerified_IssuerUnknown');
-  } else if (verifystate == cert.INVALID_CA) {
-    verifystr = bundle.getString('certNotVerified_CAInvalid');
-  } else if (verifystate == cert.SIGNATURE_ALGORITHM_DISABLED) {
-    verifystr = bundle.getString('certNotVerified_AlgorithmDisabled');
-  } else { /* if (verifystate == cert.NOT_VERIFIED_UNKNOWN || == USAGE_NOT_ALLOWED) */
-    verifystr = bundle.getString('certNotVerified_Unknown');
-  }
-  let verified = document.getElementById("verified");
-  verified.textContent = verifystr;
-  if (count > 0) {
-    var verifyInfoBox = document.getElementById('verify_info_box');
-    for (let i = 0; i < count; i++) {
-      AddUsage(usageList[i], verifyInfoBox);
-    }
-  }
-}
-
 /**
  * Displays information about a cert in the "General" tab of the cert viewer.
  *
  * @param {nsIX509Cert} cert
  *        Cert to display information about.
  */
 function DisplayGeneralDataFromCert(cert)
 {
--- a/security/manager/ssl/moz.build
+++ b/security/manager/ssl/moz.build
@@ -88,17 +88,16 @@ UNIFIED_SOURCES += [
     'CertBlocklist.cpp',
     'ContentSignatureVerifier.cpp',
     'CryptoTask.cpp',
     'CSTrustDomain.cpp',
     'DataStorage.cpp',
     'LocalCertService.cpp',
     'nsCertOverrideService.cpp',
     'nsCertPicker.cpp',
-    'nsCertVerificationThread.cpp',
     'nsClientAuthRemember.cpp',
     'nsCrypto.cpp',
     'nsCryptoHash.cpp',
     'nsDataSignatureVerifier.cpp',
     'nsKeygenHandler.cpp',
     'nsKeygenHandlerContent.cpp',
     'nsKeygenThread.cpp',
     'nsKeyModule.cpp',
@@ -127,17 +126,16 @@ UNIFIED_SOURCES += [
     'nsSDR.cpp',
     'nsSecureBrowserUIImpl.cpp',
     'nsSecurityHeaderParser.cpp',
     'NSSErrorsService.cpp',
     'nsSiteSecurityService.cpp',
     'nsSSLSocketProvider.cpp',
     'nsSSLStatus.cpp',
     'nsTLSSocketProvider.cpp',
-    'nsUsageArrayHelper.cpp',
     'PSMContentListener.cpp',
     'PSMRunnable.cpp',
     'PublicKeyPinningService.cpp',
     'RootCertificateTelemetryUtils.cpp',
     'SharedSSLState.cpp',
     'SSLServerCertVerification.cpp',
     'TransportSecurityInfo.cpp',
     'WeakCryptoOverride.cpp',
--- a/security/manager/ssl/nsCertTree.cpp
+++ b/security/manager/ssl/nsCertTree.cpp
@@ -1099,119 +1099,45 @@ nsCertTree::GetCellText(int32_t row, nsI
           _retval = nick;
         }
       }
     }
   } else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) {
     rv = cert->GetTokenName(_retval);
   } else if (NS_LITERAL_STRING("emailcol").Equals(colID) && cert) {
     rv = cert->GetEmailAddress(_retval);
-  } else if (NS_LITERAL_STRING("purposecol").Equals(colID) && mNSSComponent && cert) {
-    uint32_t verified;
-
-    nsAutoString theUsages;
-    rv = cert->GetUsagesString(false, &verified, theUsages); // allow OCSP
-    if (NS_FAILED(rv)) {
-      verified = nsIX509Cert::NOT_VERIFIED_UNKNOWN;
-    }
-
-    switch (verified) {
-      case nsIX509Cert::VERIFIED_OK:
-        _retval = theUsages;
-        break;
-
-      case nsIX509Cert::CERT_REVOKED:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyRevoked", _retval);
-        break;
-      case nsIX509Cert::CERT_EXPIRED:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyExpired", _retval);
-        break;
-      case nsIX509Cert::CERT_NOT_TRUSTED:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyNotTrusted", _retval);
-        break;
-      case nsIX509Cert::ISSUER_NOT_TRUSTED:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerNotTrusted", _retval);
-        break;
-      case nsIX509Cert::ISSUER_UNKNOWN:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerUnknown", _retval);
-        break;
-      case nsIX509Cert::INVALID_CA:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyInvalidCA", _retval);
-        break;
-      case nsIX509Cert::SIGNATURE_ALGORITHM_DISABLED:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyDisabledAlgorithm", _retval);
-        break;
-      case nsIX509Cert::NOT_VERIFIED_UNKNOWN:
-      case nsIX509Cert::USAGE_NOT_ALLOWED:
-      default:
-        rv = mNSSComponent->GetPIPNSSBundleString("VerifyUnknown", _retval);
-        break;
-    }
   } else if (NS_LITERAL_STRING("issuedcol").Equals(colID) && cert) {
     nsCOMPtr<nsIX509CertValidity> validity;
 
     rv = cert->GetValidity(getter_AddRefs(validity));
     if (NS_SUCCEEDED(rv)) {
       validity->GetNotBeforeLocalDay(_retval);
     }
   } else if (NS_LITERAL_STRING("expiredcol").Equals(colID) && cert) {
     nsCOMPtr<nsIX509CertValidity> validity;
 
     rv = cert->GetValidity(getter_AddRefs(validity));
     if (NS_SUCCEEDED(rv)) {
       validity->GetNotAfterLocalDay(_retval);
     }
   } else if (NS_LITERAL_STRING("serialnumcol").Equals(colID) && cert) {
     rv = cert->GetSerialNumber(_retval);
-
-
-  } else if (NS_LITERAL_STRING("overridetypecol").Equals(colID)) {
-    // default to classic permanent-trust
-    nsCertOverride::OverrideBits ob = nsCertOverride::ob_Untrusted;
-    if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
-      ob = certdi->mOverrideBits;
-    }
-    nsAutoCString temp;
-    nsCertOverride::convertBitsToString(ob, temp);
-    _retval = NS_ConvertUTF8toUTF16(temp);
   } else if (NS_LITERAL_STRING("sitecol").Equals(colID)) {
     if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
       nsAutoCString hostPort;
       nsCertOverrideService::GetHostWithPort(certdi->mAsciiHost, certdi->mPort, hostPort);
       _retval = NS_ConvertUTF8toUTF16(hostPort);
     }
     else {
       _retval = NS_LITERAL_STRING("*");
     }
   } else if (NS_LITERAL_STRING("lifetimecol").Equals(colID)) {
     const char *stringID = 
       (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
     rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
-  } else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) {
-    uint32_t type = nsIX509Cert::UNKNOWN_CERT;
-    rv = cert->GetCertType(&type);
-
-    switch (type) {
-    case nsIX509Cert::USER_CERT:
-        rv = mNSSComponent->GetPIPNSSBundleString("CertUser", _retval);
-	break;
-    case nsIX509Cert::CA_CERT:
-        rv = mNSSComponent->GetPIPNSSBundleString("CertCA", _retval);
-	break;
-    case nsIX509Cert::SERVER_CERT:
-        rv = mNSSComponent->GetPIPNSSBundleString("CertSSL", _retval);
-	break;
-    case nsIX509Cert::EMAIL_CERT:
-        rv = mNSSComponent->GetPIPNSSBundleString("CertEmail", _retval);
-	break;
-    default:
-        rv = mNSSComponent->GetPIPNSSBundleString("CertUnknown", _retval);
-	break;
-    }
-
   } else {
     return NS_ERROR_FAILURE;
   }
   if (mCellText) {
     nsCOMPtr<nsISupportsString> text(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     text->SetData(_retval);
     mCellText->ReplaceElementAt(text, arrayIndex, false);
deleted file mode 100644
--- a/security/manager/ssl/nsCertVerificationThread.cpp
+++ /dev/null
@@ -1,182 +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/. */
-
-#include "nsCertVerificationThread.h"
-#include "nsThreadUtils.h"
-#include "nsProxyRelease.h"
-
-using namespace mozilla;
-
-nsCertVerificationThread *nsCertVerificationThread::verification_thread_singleton;
-
-NS_IMPL_ISUPPORTS(nsCertVerificationResult, nsICertVerificationResult)
-
-namespace {
-class DispatchCertVerificationResult : public Runnable
-{
-public:
-  DispatchCertVerificationResult(const nsMainThreadPtrHandle<nsICertVerificationListener>& aListener,
-                                 nsIX509Cert* aCert,
-                                 nsICertVerificationResult* aResult)
-    : mListener(aListener)
-    , mCert(aCert)
-    , mResult(aResult)
-  { }
-
-  NS_IMETHOD Run() {
-    mListener->Notify(mCert, mResult);
-    return NS_OK;
-  }
-
-private:
-  nsMainThreadPtrHandle<nsICertVerificationListener> mListener;
-  nsCOMPtr<nsIX509Cert> mCert;
-  nsCOMPtr<nsICertVerificationResult> mResult;
-};
-} // namespace
-
-void nsCertVerificationJob::Run()
-{
-  if (!mListener || !mCert)
-    return;
-
-  uint32_t verified;
-  uint32_t count;
-  char16_t **usages;
-
-  nsCOMPtr<nsICertVerificationResult> ires;
-  RefPtr<nsCertVerificationResult> vres(new nsCertVerificationResult);
-  if (vres)
-  {
-    nsresult rv = mCert->GetUsagesArray(false, // do not ignore OCSP
-                                        &verified,
-                                        &count,
-                                        &usages);
-    vres->mRV = rv;
-    if (NS_SUCCEEDED(rv))
-    {
-      vres->mVerified = verified;
-      vres->mCount = count;
-      vres->mUsages = usages;
-    }
-
-    ires = vres;
-  }
-
-  nsCOMPtr<nsIRunnable> r = new DispatchCertVerificationResult(mListener, mCert, ires);
-  NS_DispatchToMainThread(r);
-}
-
-nsCertVerificationThread::nsCertVerificationThread()
-: mJobQ(nullptr)
-{
-  NS_ASSERTION(!verification_thread_singleton, 
-               "nsCertVerificationThread is a singleton, caller attempts"
-               " to create another instance!");
-  
-  verification_thread_singleton = this;
-}
-
-nsCertVerificationThread::~nsCertVerificationThread()
-{
-  verification_thread_singleton = nullptr;
-}
-
-nsresult nsCertVerificationThread::addJob(nsBaseVerificationJob *aJob)
-{
-  if (!aJob || !verification_thread_singleton)
-    return NS_ERROR_FAILURE;
-  
-  if (!verification_thread_singleton->mThreadHandle)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  MutexAutoLock threadLock(verification_thread_singleton->mMutex);
-
-  verification_thread_singleton->mJobQ.Push(aJob);
-  verification_thread_singleton->mCond.NotifyAll();
-  
-  return NS_OK;
-}
-
-void nsCertVerificationThread::Run(void)
-{
-  while (true) {
-
-    nsBaseVerificationJob *job = nullptr;
-
-    {
-      MutexAutoLock threadLock(verification_thread_singleton->mMutex);
-
-      while (!exitRequested(threadLock) &&
-             0 == verification_thread_singleton->mJobQ.GetSize()) {
-        // no work to do ? let's wait a moment
-
-        mCond.Wait();
-      }
-      
-      if (exitRequested(threadLock))
-        break;
-      
-      job = static_cast<nsBaseVerificationJob*>(mJobQ.PopFront());
-    }
-
-    if (job)
-    {
-      job->Run();
-      delete job;
-    }
-  }
-  
-  {
-    MutexAutoLock threadLock(verification_thread_singleton->mMutex);
-
-    while (verification_thread_singleton->mJobQ.GetSize()) {
-      nsCertVerificationJob *job = 
-        static_cast<nsCertVerificationJob*>(mJobQ.PopFront());
-      delete job;
-    }
-    postStoppedEventToMainThread(threadLock);
-  }
-}
-
-nsCertVerificationResult::nsCertVerificationResult()
-: mRV(NS_OK),
-  mVerified(0),
-  mCount(0),
-  mUsages(0)
-{
-}
-
-nsCertVerificationResult::~nsCertVerificationResult()
-{
-  if (mUsages)
-  {
-    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mUsages);
-  }
-}
-
-NS_IMETHODIMP
-nsCertVerificationResult::GetUsagesArrayResult(uint32_t *aVerified,
-                                               uint32_t *aCount,
-                                               char16_t ***aUsages)
-{
-  if (NS_FAILED(mRV))
-    return mRV;
-  
-  // transfer ownership
-  
-  *aVerified = mVerified;
-  *aCount = mCount;
-  *aUsages = mUsages;
-  
-  mVerified = 0;
-  mCount = 0;
-  mUsages = 0;
-  
-  nsresult rv = mRV;
-  
-  mRV = NS_ERROR_FAILURE; // this object works only once...
-  
-  return rv;
-}
deleted file mode 100644
--- a/security/manager/ssl/nsCertVerificationThread.h
+++ /dev/null
@@ -1,29 +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/. */
-
-#ifndef _NSCERTVERIFICATIONTHREAD_H_
-#define _NSCERTVERIFICATIONTHREAD_H_
-
-#include "nsCOMPtr.h"
-#include "nsDeque.h"
-#include "nsPSMBackgroundThread.h"
-#include "nsVerificationJob.h"
-
-class nsCertVerificationThread : public nsPSMBackgroundThread
-{
-private:
-  nsDeque mJobQ;
-
-  virtual void Run(void);
-
-public:
-  nsCertVerificationThread();
-  ~nsCertVerificationThread();
-
-  static nsCertVerificationThread *verification_thread_singleton;
-  
-  static nsresult addJob(nsBaseVerificationJob *aJob);
-};
-
-#endif
--- a/security/manager/ssl/nsIX509Cert.idl
+++ b/security/manager/ssl/nsIX509Cert.idl
@@ -164,80 +164,32 @@ interface nsIX509Cert : nsISupports {
 
   /**
    *  True if the certificate is self-signed. CA issued
    *  certificates are always self-signed.
    */
   readonly attribute boolean isSelfSigned;
 
   /**
-   *  Constants for certificate verification results.
-   */
-  const unsigned long VERIFIED_OK          =      0;
-  const unsigned long NOT_VERIFIED_UNKNOWN = 1 << 0;
-  const unsigned long CERT_REVOKED         = 1 << 1;
-  const unsigned long CERT_EXPIRED         = 1 << 2;
-  const unsigned long CERT_NOT_TRUSTED     = 1 << 3;
-  const unsigned long ISSUER_NOT_TRUSTED   = 1 << 4;
-  const unsigned long ISSUER_UNKNOWN       = 1 << 5;
-  const unsigned long INVALID_CA           = 1 << 6;
-  const unsigned long USAGE_NOT_ALLOWED    = 1 << 7;
-  const unsigned long SIGNATURE_ALGORITHM_DISABLED = 1 << 8;
-
-  /**
    *  Constants for specifying the chain mode when exporting a certificate
    */
   const unsigned long CMS_CHAIN_MODE_CertOnly = 1;
   const unsigned long CMS_CHAIN_MODE_CertChain = 2;
   const unsigned long CMS_CHAIN_MODE_CertChainWithRoot = 3;
 
   /**
    *  Obtain a list of certificates that contains this certificate
    *  and the issuing certificates of all involved issuers,
    *  up to the root issuer.
    *
    *  @return The chain of certifficates including the issuers.
    */
   nsIArray getChain();
 
   /**
-   *  Obtain an array of human readable strings describing
-   *  the certificate's certified usages.
-   *
-   *  @param localOnly Do not hit the network, even if revocation information
-   *                   downloading is currently activated.
-   *  @param verified The certificate verification result, see constants.
-   *  @param count The number of human readable usages returned.
-   *  @param usages The array of human readable usages.
-   */
-  void getUsagesArray(in boolean localOnly,
-                      out uint32_t verified,
-                      out uint32_t count,
-                      [array, size_is(count)] out wstring usages);
-
-  /**
-   *  Async version of nsIX509Cert::getUsagesArray()
-   *
-   *  Will not block, will request results asynchronously,
-   *  availability of results will be notified on the main thread.
-   */
-  void requestUsagesArrayAsync(in nsICertVerificationListener cvl);
-
-  /**
-   *  Obtain a single comma separated human readable string describing
-   *  the certificate's certified usages.
-   *
-   *  @param localOnly Do not hit the network, even if revocation information
-   *                   downloading is currently activated.
-   *  @param verified The certificate verification result, see constants.
-   *  @param purposes The string listing the usages.
-   */
-  void getUsagesString(in boolean localOnly, out uint32_t verified, out AString usages);
-
-  /**
    * A comma separated list of localized strings representing the contents of
    * the certificate's key usage extension, if present. The empty string if the
    * certificate doesn't have the key usage extension, or has an empty extension.
    */
   readonly attribute AString keyUsages;
 
   /**
    *  This is the attribute which describes the ASN1 layout
@@ -302,48 +254,8 @@ interface nsIX509Cert : nsISupports {
                        tokenNames);
 
   /**
    * Either delete the certificate from all cert databases,
    * or mark it as untrusted.
    */
   void markForPermDeletion();
 };
-
-[scriptable, uuid(2fd0a785-9f2d-4327-8871-8c3e0783891d)]
-interface nsICertVerificationResult : nsISupports {
-
-  /**
-   *  This interface reflects a container of
-   *  verification results. Call will not block.
-   *
-   *  Obtain an array of human readable strings describing
-   *  the certificate's certified usages.
-   *
-   *  Mirrors the results produced by
-   *  nsIX509Cert::getUsagesArray()
-   *
-   *  As of today, this function is a one-shot object,
-   *  only the first call will succeed.
-   *  This allows an optimization in the implementation,
-   *  ownership of result data will be transfered to caller.
-   *
-   *  @param cert The certificate that was verified.
-   *  @param verified The certificate verification result,
-   *         see constants in nsIX509Cert.
-   *  @param count The number of human readable usages returned.
-   *  @param usages The array of human readable usages.
-   */
-  void getUsagesArrayResult(out uint32_t verified,
-                            out uint32_t count,
-                            [array, size_is(count)] out wstring usages);
-};
-
-[scriptable, uuid(6684bce9-50db-48e1-81b7-98102bf81357)]
-interface nsICertVerificationListener : nsISupports {
-
-  /**
-   *  Notify that results are ready, that have been requested
-   *  using nsIX509Cert::requestUsagesArrayAsync()
-   */
-  void notify(in nsIX509Cert verifiedCert,
-              in nsICertVerificationResult result);
-};
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -11,17 +11,16 @@
 #include "certdb.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/unused.h"
 #include "nsArray.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
-#include "nsCertVerificationThread.h"
 #include "nsICertificateDialogs.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIURI.h"
 #include "nsIX509Cert.h"
 #include "nsNSSASN1Object.h"
@@ -30,17 +29,16 @@
 #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
 #include "nsPK11TokenDB.h"
 #include "nsPKCS12Blob.h"
 #include "nsProxyRelease.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
-#include "nsUsageArrayHelper.h"
 #include "nsXULAppAPI.h"
 #include "nspr.h"
 #include "nssb64.h"
 #include "pkix/pkixnss.h"
 #include "pkix/pkixtypes.h"
 #include "pkix/Result.h"
 #include "plbase64.h"
 #include "prerror.h"
@@ -1269,100 +1267,16 @@ nsNSSCertificate::GetValidity(nsIX509Cer
   }
 
   nsCOMPtr<nsIX509CertValidity> validity = new nsX509CertValidity(mCert);
   validity.forget(aValidity);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNSSCertificate::GetUsagesArray(bool localOnly,
-                                 uint32_t* _verified,
-                                 uint32_t* _count,
-                                 char16_t*** _usages)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  nsresult rv;
-  const int max_usages = 13;
-  char16_t* tmpUsages[max_usages];
-  const char* suffix = "";
-  uint32_t tmpCount;
-  nsUsageArrayHelper uah(mCert.get());
-  rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount,
-                          tmpUsages);
-  NS_ENSURE_SUCCESS(rv,rv);
-  if (tmpCount > 0) {
-    *_usages = (char16_t**) moz_xmalloc(sizeof(char16_t*) * tmpCount);
-    if (!*_usages)
-      return NS_ERROR_OUT_OF_MEMORY;
-    for (uint32_t i=0; i<tmpCount; i++) {
-      (*_usages)[i] = tmpUsages[i];
-    }
-    *_count = tmpCount;
-    return NS_OK;
-  }
-  *_usages = (char16_t**) moz_xmalloc(sizeof(char16_t*));
-  if (!*_usages)
-    return NS_ERROR_OUT_OF_MEMORY;
-  *_count = 0;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSCertificate::RequestUsagesArrayAsync(
-  nsICertVerificationListener* aResultListener)
-{
-  NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD);
-
-  if (!aResultListener)
-    return NS_ERROR_FAILURE;
-
-  nsCertVerificationJob* job = new nsCertVerificationJob;
-
-  job->mCert = this;
-  job->mListener =
-    new nsMainThreadPtrHolder<nsICertVerificationListener>(aResultListener);
-
-  nsresult rv = nsCertVerificationThread::addJob(job);
-  if (NS_FAILED(rv))
-    delete job;
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsNSSCertificate::GetUsagesString(bool localOnly, uint32_t* _verified,
-                                  nsAString& _usages)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  nsresult rv;
-  const int max_usages = 13;
-  char16_t* tmpUsages[max_usages];
-  const char* suffix = "_p";
-  uint32_t tmpCount;
-  nsUsageArrayHelper uah(mCert.get());
-  rv = uah.GetUsagesArray(suffix, localOnly, max_usages, _verified, &tmpCount,
-                          tmpUsages);
-  NS_ENSURE_SUCCESS(rv,rv);
-  _usages.Truncate();
-  for (uint32_t i=0; i<tmpCount; i++) {
-    if (i>0) _usages.Append(',');
-    _usages.Append(tmpUsages[i]);
-    free(tmpUsages[i]);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsNSSCertificate::GetASN1Structure(nsIASN1Object** aASN1Structure)
 {
   NS_ENSURE_ARG_POINTER(aASN1Structure);
   return CreateASN1Struct(aASN1Structure);
 }
 
 NS_IMETHODIMP
 nsNSSCertificate::Equals(nsIX509Cert* other, bool* result)
--- a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
+++ b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
@@ -180,31 +180,16 @@ nsNSSCertificateFakeTransport::GetRawDER
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetValidity(nsIX509CertValidity**)
 {
   NS_NOTREACHED("Unimplemented on content process");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNSSCertificateFakeTransport::GetUsagesArray(bool, uint32_t*, uint32_t*,
-                                              char16_t***)
-{
-  NS_NOTREACHED("Unimplemented on content process");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsNSSCertificateFakeTransport::GetUsagesString(bool, uint32_t*, nsAString&)
-{
-  NS_NOTREACHED("Unimplemented on content process");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetKeyUsages(nsAString&)
 {
   MOZ_ASSERT_UNREACHABLE("Unimplemented on content process");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetASN1Structure(nsIASN1Object**)
@@ -358,24 +343,16 @@ nsNSSCertificateFakeTransport::GetIsSelf
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetIsBuiltInRoot(bool* aIsBuiltInRoot)
 {
   NS_NOTREACHED("Unimplemented on content process");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNSSCertificateFakeTransport::RequestUsagesArrayAsync(
-  nsICertVerificationListener*)
-{
-  NS_NOTREACHED("Unimplemented on content process");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetAllTokenNames(unsigned int*, char16_t***)
 {
   NS_NOTREACHED("Unimplemented on content process");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 CERTCertificate*
 nsNSSCertificateFakeTransport::GetCert()
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -18,17 +18,16 @@
 #include "mozilla/PublicSSL.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsCRT.h"
-#include "nsCertVerificationThread.h"
 #include "nsClientAuthRemember.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICertOverrideService.h"
 #include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsIPrompt.h"
 #include "nsIProperties.h"
@@ -245,63 +244,31 @@ GetRevocationBehaviorFromPrefs(/*out*/ C
   *certShortLifetimeInDays =
     Preferences::GetUint("security.pki.cert_short_lifetime_in_days",
                          static_cast<uint32_t>(0));
 
   SSL_ClearSessionCache();
 }
 
 nsNSSComponent::nsNSSComponent()
-  :mutex("nsNSSComponent.mutex"),
-   mNSSInitialized(false),
+  : mutex("nsNSSComponent.mutex")
+  , mNSSInitialized(false)
 #ifndef MOZ_NO_SMART_CARDS
-   mThreadList(nullptr),
+  , mThreadList(nullptr)
 #endif
-   mCertVerificationThread(nullptr)
 {
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ctor\n"));
 
   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
   ++mInstanceCount;
 }
 
-void
-nsNSSComponent::deleteBackgroundThreads()
-{
-  if (mCertVerificationThread)
-  {
-    mCertVerificationThread->requestExit();
-    delete mCertVerificationThread;
-    mCertVerificationThread = nullptr;
-  }
-}
-
-void
-nsNSSComponent::createBackgroundThreads()
-{
-  NS_ASSERTION(!mCertVerificationThread,
-               "Cert verification thread already created.");
-
-  mCertVerificationThread = new nsCertVerificationThread;
-  nsresult rv = mCertVerificationThread->startThread(
-    NS_LITERAL_CSTRING("Cert Verify"));
-
-  if (NS_FAILED(rv)) {
-    delete mCertVerificationThread;
-    mCertVerificationThread = nullptr;
-  }
-}
-
 nsNSSComponent::~nsNSSComponent()
 {
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor\n"));
-  NS_ASSERTION(!mCertVerificationThread,
-               "Cert verification thread should have been cleaned up.");
-
-  deleteBackgroundThreads();
 
   // All cleanup code requiring services needs to happen in xpcom_shutdown
 
   ShutdownNSS();
   SharedSSLState::GlobalCleanup();
   RememberCertErrorsTable::Cleanup();
   --mInstanceCount;
   nsNSSShutDownList::shutdown();
@@ -1940,23 +1907,16 @@ nsNSSComponent::Init()
   if (NS_FAILED(rv)) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
             ("nsNSSComponent::InitializeNSS() failed\n"));
     return rv;
   }
 
   RememberCertErrorsTable::Init();
 
-  createBackgroundThreads();
-  if (!mCertVerificationThread) {
-    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
-            ("nsNSSComponent::createBackgroundThreads() failed\n"));
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   return RegisterObservers();
 }
 
 // nsISupports Implementation for the class
 NS_IMPL_ISUPPORTS(nsNSSComponent,
                   nsINSSComponent,
                   nsIObserver)
 
@@ -1964,24 +1924,17 @@ static const char* const PROFILE_BEFORE_
 
 NS_IMETHODIMP
 nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
                         const char16_t* someData)
 {
   if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("receiving profile change topic\n"));
     DoProfileBeforeChange();
-  } else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
-
-    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent: XPCom shutdown observed\n"));
-
-    // Cleanup code that requires services, it's too late in destructor.
-    deleteBackgroundThreads();
-  }
-  else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+  } else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
     nsNSSShutDownPreventionLock locker;
     bool clearSessionCache = true;
     NS_ConvertUTF16toUTF8  prefName(someData);
 
     if (prefName.EqualsLiteral("security.tls.version.min") ||
         prefName.EqualsLiteral("security.tls.version.max")) {
       (void) setEnabledTLSVersions();
     } else if (prefName.EqualsLiteral("security.ssl.require_safe_negotiation")) {
@@ -2112,17 +2065,16 @@ nsNSSComponent::RegisterObservers()
             ("nsNSSComponent: couldn't get observer service\n"));
     return NS_ERROR_FAILURE;
   }
 
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent: adding observers\n"));
   // Using false for the ownsweak parameter means the observer service will
   // keep a strong reference to this component. As a result, this will live at
   // least as long as the observer service.
-  observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
 
   return NS_OK;
 }
 
 void
 nsNSSComponent::DoProfileBeforeChange()
 {
--- a/security/manager/ssl/nsNSSComponent.h
+++ b/security/manager/ssl/nsNSSComponent.h
@@ -100,17 +100,16 @@ public:
 
   virtual ::already_AddRefed<mozilla::psm::SharedCertVerifier>
     GetDefaultCertVerifier() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINSSComponent, NS_INSSCOMPONENT_IID)
 
 class nsNSSShutDownList;
-class nsCertVerificationThread;
 
 // Implementation of the PSM component interface.
 class nsNSSComponent final : public nsINSSComponent
                            , public nsIObserver
 {
 public:
   NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
 
@@ -210,20 +209,16 @@ private:
   SmartCardThreadList* mThreadList;
 #endif
 
 #ifdef DEBUG
   nsAutoString mTestBuiltInRootHash;
 #endif
   nsString mContentSigningRootHash;
 
-  void deleteBackgroundThreads();
-  void createBackgroundThreads();
-  nsCertVerificationThread* mCertVerificationThread;
-
   nsNSSHttpInterface mHttpForNSS;
   RefPtr<mozilla::psm::SharedCertVerifier> mDefaultCertVerifier;
 
   static PRStatus IdentityInfoInit(void);
 };
 
 class nsNSSErrors
 {
deleted file mode 100644
--- a/security/manager/ssl/nsUsageArrayHelper.cpp
+++ /dev/null
@@ -1,238 +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/. */
-
-#include "nsUsageArrayHelper.h"
-
-#include "ScopedNSSTypes.h"
-#include "mozilla/Assertions.h"
-#include "nsCOMPtr.h"
-#include "nsComponentManagerUtils.h"
-#include "nsDateTimeFormatCID.h"
-#include "nsIDateTimeFormat.h"
-#include "nsNSSCertificate.h"
-#include "nsReadableUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nspr.h"
-#include "pkix/pkixnss.h"
-#include "secerr.h"
-
-using namespace mozilla;
-using namespace mozilla::psm;
-
-extern LazyLogModule gPIPNSSLog;
-
-static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); // XXX? needed?::
-
-nsUsageArrayHelper::nsUsageArrayHelper(CERTCertificate *aCert)
-:mCert(aCert)
-{
-  nsNSSShutDownPreventionLock locker;
-  defaultcertdb = CERT_GetDefaultCertDB();
-  nssComponent = do_GetService(kNSSComponentCID, &m_rv);
-}
-
-namespace {
-
-// Some validation errors are non-fatal in that, we should keep checking the
-// cert for other usages after receiving them; i.e. they are errors that NSS
-// returns when a certificate isn't valid for a particular usage, but which
-// don't indicate that the certificate is invalid for ANY usage. Others errors
-// (e.g. revocation) are fatal, and we should immediately stop validation of
-// the cert when we encounter them.
-bool
-isFatalError(uint32_t checkResult)
-{
-  return checkResult != nsIX509Cert::VERIFIED_OK &&
-         checkResult != nsIX509Cert::USAGE_NOT_ALLOWED &&
-         checkResult != nsIX509Cert::ISSUER_NOT_TRUSTED &&
-         checkResult != nsIX509Cert::ISSUER_UNKNOWN;
-}
-
-} // unnamed namespace
-
-// Validates the certificate for the given usage. If the certificate is valid
-// for the given usage, aCounter is incremented, a string description of the
-// usage is appended to outUsages, and nsNSSCertificate::VERIFIED_OK is
-// returned. Otherwise, if validation failed, one of the other "Constants for
-// certificate verification results" in nsIX509Cert is returned.
-uint32_t
-nsUsageArrayHelper::check(uint32_t previousCheckResult,
-                          const char *suffix,
-                          CertVerifier * certVerifier,
-                          SECCertificateUsage aCertUsage,
-                          mozilla::pkix::Time time,
-                          CertVerifier::Flags flags,
-                          uint32_t &aCounter,
-                          char16_t **outUsages)
-{
-  if (!aCertUsage) {
-    MOZ_CRASH("caller should have supplied non-zero aCertUsage");
-  }
-
-  if (isFatalError(previousCheckResult)) {
-      return previousCheckResult;
-  }
-
-  nsAutoCString typestr;
-  switch (aCertUsage) {
-  case certificateUsageSSLClient:
-    typestr = "VerifySSLClient";
-    break;
-  case certificateUsageSSLServer:
-    typestr = "VerifySSLServer";
-    break;
-  case certificateUsageEmailSigner:
-    typestr = "VerifyEmailSigner";
-    break;
-  case certificateUsageEmailRecipient:
-    typestr = "VerifyEmailRecip";
-    break;
-  case certificateUsageObjectSigner:
-    typestr = "VerifyObjSign";
-    break;
-  case certificateUsageSSLCA:
-    typestr = "VerifySSLCA";
-    break;
-  case certificateUsageVerifyCA:
-    typestr = "VerifyCAVerifier";
-    break;
-  case certificateUsageStatusResponder:
-    typestr = "VerifyStatusResponder";
-    break;
-  default:
-    MOZ_CRASH("unknown cert usage passed to check()");
-  }
-
-  UniqueCERTCertList unusedBuiltChain;
-  SECStatus rv = certVerifier->VerifyCert(mCert, aCertUsage, time,
-                                          nullptr /*XXX:wincx*/,
-                                          nullptr /*hostname*/,
-                                          unusedBuiltChain, flags);
-
-  if (rv == SECSuccess) {
-    typestr.Append(suffix);
-    nsAutoString verifyDesc;
-    m_rv = nssComponent->GetPIPNSSBundleString(typestr.get(), verifyDesc);
-    if (NS_SUCCEEDED(m_rv)) {
-      outUsages[aCounter++] = ToNewUnicode(verifyDesc);
-    }
-    return nsIX509Cert::VERIFIED_OK;
-  }
-
-  PRErrorCode error = PR_GetError();
-
-  uint32_t result = nsIX509Cert::NOT_VERIFIED_UNKNOWN;
-  verifyFailed(&result, error);
-
-  // USAGE_NOT_ALLOWED is the weakest non-fatal error; let all other errors
-  // override it.
-  if (result == nsIX509Cert::USAGE_NOT_ALLOWED &&
-      previousCheckResult != nsIX509Cert::VERIFIED_OK) {
-      result = previousCheckResult;
-  }
-
-  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
-          ("error validating certificate for usage %s: %s (%d) -> %ud \n",
-          typestr.get(), PR_ErrorToName(error), (int) error, (int) result));
-
-  return result;
-}
-
-
-// Maps the error code to one of the Constants for certificate verification
-// results" in nsIX509Cert.
-void
-nsUsageArrayHelper::verifyFailed(uint32_t *_verified, int err)
-{
-  switch (err) {
-  /* For these cases, verify only failed for the particular usage */
-  case SEC_ERROR_INADEQUATE_KEY_USAGE:
-  case SEC_ERROR_INADEQUATE_CERT_TYPE:
-  case SEC_ERROR_CA_CERT_INVALID:
-  case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
-  case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE:
-  case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
-    *_verified = nsNSSCertificate::USAGE_NOT_ALLOWED; break;
-  /* These are the cases that have individual error messages */
-  case SEC_ERROR_REVOKED_CERTIFICATE:
-    *_verified = nsNSSCertificate::CERT_REVOKED; break;
-  case SEC_ERROR_EXPIRED_CERTIFICATE:
-    *_verified = nsNSSCertificate::CERT_EXPIRED; break;
-  case SEC_ERROR_UNTRUSTED_CERT:
-    *_verified = nsNSSCertificate::CERT_NOT_TRUSTED; break;
-  case SEC_ERROR_UNTRUSTED_ISSUER:
-    *_verified = nsNSSCertificate::ISSUER_NOT_TRUSTED; break;
-  case SEC_ERROR_UNKNOWN_ISSUER:
-    *_verified = nsNSSCertificate::ISSUER_UNKNOWN; break;
-  case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-    // XXX are there other error for this?
-    *_verified = nsNSSCertificate::INVALID_CA; break;
-  case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
-    *_verified = nsNSSCertificate::SIGNATURE_ALGORITHM_DISABLED; break;
-  default:
-    *_verified = nsNSSCertificate::NOT_VERIFIED_UNKNOWN; break;
-  }
-}
-
-nsresult
-nsUsageArrayHelper::GetUsagesArray(const char *suffix,
-                      bool localOnly,
-                      uint32_t outArraySize,
-                      uint32_t *_verified,
-                      uint32_t *_count,
-                      char16_t **outUsages)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (NS_FAILED(m_rv))
-    return m_rv;
-
-  NS_ENSURE_TRUE(nssComponent, NS_ERROR_NOT_AVAILABLE);
-
-  if (outArraySize < max_returned_out_array_size)
-    return NS_ERROR_FAILURE;
-
-  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
-  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
-
-  uint32_t &count = *_count;
-  count = 0;
-
-  mozilla::pkix::Time now(mozilla::pkix::Now());
-
-  CertVerifier::Flags flags = localOnly ? CertVerifier::FLAG_LOCAL_ONLY : 0;
-
-  // The following list of checks must be < max_returned_out_array_size
-
-  uint32_t result;
-  result = check(nsIX509Cert::VERIFIED_OK, suffix, certVerifier,
-                 certificateUsageSSLClient, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageSSLServer, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageEmailSigner, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageEmailRecipient, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageObjectSigner, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageSSLCA, now, flags, count, outUsages);
-  result = check(result, suffix, certVerifier,
-                 certificateUsageStatusResponder, now, flags, count, outUsages);
-
-  if (isFatalError(result) || count == 0) {
-    MOZ_ASSERT(result != nsIX509Cert::VERIFIED_OK);
-
-    // Clear the output usage strings in the case where we encountered a fatal
-    // error after we already successfully validated the cert for some usages.
-    for (uint32_t i = 0; i < count; ++i) {
-      delete outUsages[i];
-      outUsages[i] = nullptr;
-    }
-    count = 0;
-    *_verified = result;
-  } else {
-    *_verified = nsNSSCertificate::VERIFIED_OK;
-  }
-  return NS_OK;
-}
deleted file mode 100644
--- a/security/manager/ssl/nsUsageArrayHelper.h
+++ /dev/null
@@ -1,45 +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/. */
-
-#ifndef _NSUSAGEARRAYHELPER_H_
-#define _NSUSAGEARRAYHELPER_H_
-
-#include "CertVerifier.h"
-#include "nsNSSComponent.h"
-#include "certt.h"
-#include "pkix/Time.h"
-
-class nsUsageArrayHelper
-{
-public:
-  explicit nsUsageArrayHelper(CERTCertificate *aCert);
-
-  nsresult GetUsagesArray(const char *suffix,
-               bool localOnly,
-               uint32_t outArraySize,
-               uint32_t *_verified,
-               uint32_t *_count,
-               char16_t **tmpUsages);
-
-  enum { max_returned_out_array_size = 12 };
-
-private:
-  CERTCertificate *mCert;
-  nsresult m_rv;
-  CERTCertDBHandle *defaultcertdb;
-  nsCOMPtr<nsINSSComponent> nssComponent;
-
-  uint32_t check(uint32_t previousCheckResult,
-                 const char *suffix,
-                 mozilla::psm::CertVerifier * certVerifier,
-                 SECCertificateUsage aCertUsage,
-                 mozilla::pkix::Time time,
-                 mozilla::psm::CertVerifier::Flags flags,
-                 uint32_t &aCounter,
-                 char16_t **outUsages);
-
-  void verifyFailed(uint32_t *_verified, int err);
-};
-
-#endif
--- a/security/manager/ssl/tests/mochitest/browser/browser.ini
+++ b/security/manager/ssl/tests/mochitest/browser/browser.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 tags = psm
 support-files = head.js
 
 [browser_bug627234_perwindowpb.js]
 [browser_certificateManagerLeak.js]
 [browser_certViewer.js]
+support-files = *.pem
--- a/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
+++ b/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
@@ -1,40 +1,267 @@
 /* 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";
 
-var gBugWindow;
+// Repeatedly opens the certificate viewer dialog with various certificates and
+// determines that the viewer correctly identifies either what usages those
+// certificates are valid for or what errors prevented the certificates from
+// being verified.
+
+var { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
+
+var certificates = [];
+
+registerCleanupFunction(function() {
+  let certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                 .getService(Ci.nsIX509CertDB);
+  certificates.forEach(cert => {
+    certdb.deleteCertificate(cert);
+  });
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("ca.pem", "CTu,CTu,CTu");
+  let win = yield displayCertificate(cert);
+  checkUsages(win, ["SSL Certificate Authority"]);
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("ssl-ee.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkUsages(win, ["SSL Server Certificate", "SSL Client Certificate"]);
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("email-ee.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate"]);
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("code-ee.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkUsages(win, ["Object Signer"]);
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("expired-ca.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win, "Could not verify this certificate because it has expired.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("ee-from-expired-ca.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because the CA certificate " +
+             "is invalid.");
+  yield BrowserTestUtils.closeWindow(win);
+});
 
-function onLoad() {
-  gBugWindow.removeEventListener("load", onLoad);
-  gBugWindow.addEventListener("unload", onUnload);
-  gBugWindow.close();
-}
+add_task(function* () {
+  let cert = yield readCertificate("unknown-issuer.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because the issuer is " +
+             "unknown.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("md5-ee.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because it was signed using " +
+             "a signature algorithm that was disabled because that algorithm " +
+             "is not secure.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  let cert = yield readCertificate("untrusted-ca.pem", "p,p,p");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because it is not trusted.");
+  yield BrowserTestUtils.closeWindow(win);
+});
 
-function onUnload() {
-  gBugWindow.removeEventListener("unload", onUnload);
-  window.focus();
-  finish();
+add_task(function* () {
+  let cert = yield readCertificate("ee-from-untrusted-ca.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because the issuer is not " +
+             "trusted.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  // Note that there's currently no way to un-do this. This should only be a
+  // problem if another test re-uses a certificate with this same key (perhaps
+  // likely) and subject (less likely).
+  let certBlocklist = Cc["@mozilla.org/security/certblocklist;1"]
+                        .getService(Ci.nsICertBlocklist);
+  certBlocklist.revokeCertBySubjectAndPubKey(
+    "MBIxEDAOBgNVBAMMB3Jldm9rZWQ=", // CN=revoked
+    "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="); // hash of the shared key
+  let cert = yield readCertificate("revoked.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win,
+             "Could not verify this certificate because it has been revoked.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* () {
+  // This certificate has a keyUsage extension asserting cRLSign and
+  // keyCertSign, but it doesn't have a basicConstraints extension. This
+  // shouldn't be valid for any usage. Sadly, we give a pretty lame error
+  // message in this case.
+  let cert = yield readCertificate("invalid.pem", ",,");
+  let win = yield displayCertificate(cert);
+  checkError(win, "Could not verify this certificate for unknown reasons.");
+  yield BrowserTestUtils.closeWindow(win);
+});
+
+/**
+ * Helper for readCertificate.
+ */
+function pemToBase64(pem) {
+  return pem.replace(/-----BEGIN CERTIFICATE-----/, "")
+            .replace(/-----END CERTIFICATE-----/, "")
+            .replace(/[\r\n]/g, "");
 }
 
-// This test opens and then closes the certificate viewer to test that it
-// does not cause assertion failures.
-function test() {
-  waitForExplicitFinish();
-  let certdb = Cc["@mozilla.org/security/x509certdb;1"]
-                 .getService(Ci.nsIX509CertDB);
-  let certList = certdb.getCerts();
-  let enumerator = certList.getEnumerator();
-  ok(enumerator.hasMoreElements(), "we have at least one certificate");
-  let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
-  ok(cert, "found a certificate to look at");
-  info("looking at certificate with nickname " + cert.nickname);
+/**
+ * Given the filename of a certificate, returns a promise that will resolve with
+ * a handle to the certificate when that certificate has been read and imported
+ * with the given trust settings.
+ *
+ * @param {String} filename
+ *        The filename of the certificate (assumed to be in the same directory).
+ * @param {String} trustString
+ *        A string describing how the certificate should be trusted (see
+ *        `certutil -A --help`).
+ * @return {Promise}
+ *         A promise that will resolve with a handle to the certificate.
+ */
+function readCertificate(filename, trustString) {
+  return OS.File.read(getTestFilePath(filename)).then(data => {
+    let decoder = new TextDecoder();
+    let pem = decoder.decode(data);
+    let certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                   .getService(Ci.nsIX509CertDB);
+    let base64 = pemToBase64(pem);
+    certdb.addCertFromBase64(base64, trustString, "unused");
+    let cert = certdb.constructX509FromBase64(base64);
+    certificates.push(cert); // so we remember to delete this at the end
+    return cert;
+  }, error => { throw error; });
+}
+
+/**
+ * Given a certificate, returns a promise that will resolve when the certificate
+ * viewer has opened is displaying that certificate, and has finished
+ * determining its valid usages.
+ *
+ * @param {nsIX509Cert} certificate
+ *        The certificate to view and determine usages for.
+ * @return {Promise}
+ *         A promise that will resolve with a handle on the opened certificate
+ *         viewer window when the usages have been determined.
+ */
+function displayCertificate(certificate) {
   let array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-  array.appendElement(cert, false);
+  array.appendElement(certificate, false);
   let params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
                  .createInstance(Ci.nsIDialogParamBlock);
   params.objects = array;
-  gBugWindow = window.openDialog("chrome://pippki/content/certViewer.xul",
-                                 "", "", params);
-  gBugWindow.addEventListener("load", onLoad);
+  let win = window.openDialog("chrome://pippki/content/certViewer.xul", "",
+                              "", params);
+  return TestUtils.topicObserved("ViewCertDetails:CertUsagesDone",
+                                 (subject, data) => subject == win)
+  .then(([subject, data]) => subject, error => { throw error; });
+}
+
+/**
+ * Given a certificate viewer window, finds the usages the certificate is valid
+ * for.
+ *
+ * @param {window} win
+ *        The certificate viewer window.
+ * @return {String[]}
+ *         An array of strings describing the usages the certificate is valid
+ *         for.
+ */
+function getUsages(win) {
+  let determinedUsages = [];
+  let verifyInfoBox = win.document.getElementById("verify_info_box");
+  Array.from(verifyInfoBox.children).forEach(child => {
+    if (child.getAttribute("hidden") != "true" &&
+        child.getAttribute("id") != "verified") {
+      determinedUsages.push(child.getAttribute("value"));
+    }
+  });
+  return determinedUsages.sort();
 }
+
+/**
+ * Given a certificate viewer window, returns the error string describing a
+ * failure encountered when determining the certificate's usages. It will be
+ * "This certificate has been verified for the following uses:" when the
+ * certificate has successfully verified for at least one usage.
+ *
+ * @param {window} win
+ *        The certificate viewer window.
+ * @return {String}
+ *         A string describing the error encountered, or the success message if
+ *         the certificate is valid for at least one usage.
+ */
+function getError(win) {
+  return win.document.getElementById("verified").textContent;
+}
+
+/**
+ * Given a certificate viewer window and an array of expected usage
+ * descriptions, verifies that the window is actually showing that the
+ * certificate has validated for those usages.
+ *
+ * @param {window} win
+ *        The certificate viewer window.
+ * @param {String[]} usages
+ *        An array of expected usage descriptions.
+ */
+function checkUsages(win, usages) {
+  Assert.equal(getError(win),
+               "This certificate has been verified for the following uses:",
+               "should have successful verification message");
+  let determinedUsages = getUsages(win);
+  usages.sort();
+  Assert.equal(determinedUsages.length, usages.length,
+               "number of usages as determined by cert viewer should be equal");
+  while (usages.length > 0) {
+    Assert.equal(determinedUsages.pop(), usages.pop(),
+                 "usages as determined by cert viewer should be equal");
+  }
+}
+
+/**
+ * Given a certificate viewer window and an expected error, verifies that the
+ * window is actually showing that error.
+ *
+ * @param {window} win
+ *        The certificate viewer window.
+ * @param {String} error
+ *        The expected error message.
+ */
+function checkError(win, error) {
+  let determinedUsages = getUsages(win);
+  Assert.equal(determinedUsages.length, 0,
+               "should not have any successful usages in error case");
+  Assert.equal(getError(win), error,
+               "determined error should be the same as expected error");
+}
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ca.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxTCCAa+gAwIBAgIUQy+m6w0ZtMTfbmtELQQz8zwqCAowCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMA0xCzAJBgNVBAMMAmNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptu
+Gobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO
+7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgf
+qDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/yt
+HSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcx
+uLP+SSP6clHEMdUDrNoYCjXtjQIDAQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud
+DwQEAwIBBjALBgkqhkiG9w0BAQsDggEBAJQcekrdR+S6U0I3owUQxVOoUJMzHdTj
+u562Ra7cOiJQwe1OQZbvo6rQkQWPrpuDOGpwwr1+HBMGb8mjUqeFo5wIinU003TC
+UYYEpDCbPwXOKDkDUukKd1aO4wpJc/v8YIiCz7aCRj9HQ3L5YO5JsgMNSCXKKoUm
+ILcz2V+IQZ6lePzFfd2aO3zLMDPwEOyujYYtQnBVZIT4F/x/6nU8E6bkbDSGPjQW
+CSVhwa0YQ9lCRSM6e//wGry4i8X8718t1V+Nqh7y6u7UlOrXbNEA4pR6mvJsqPhF
+Mj82We4OGNBxXbyuGJObQgLBfmRuwKQT9SNtKWEifiaTw8apT/fBagc=
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ca.pem.certspec
@@ -0,0 +1,4 @@
+issuer:ca
+subject:ca
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/code-ee.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAa6gAwIBAgIUdey1Pi3nj8syGBLqTY30bbsak7swCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBIxEDAOBgNVBAMMB2NvZGUtZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
+sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
+TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
+xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
+tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
+8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjFzAVMBMGA1UdJQQMMAoGCCsG
+AQUFBwMDMAsGCSqGSIb3DQEBCwOCAQEAubYFMnDLOK8/99OLWeejdD6HQ8Qg2W4u
+7I9hZySo+g0w2U6jvtgSTvUfN/Zk33fSu90yOnWg1v+6tvd/jdwxfooVfz7zNWa9
+i6/oSY/0THBhX9bf9b0wHmZLnuhS7AwG6BCbqulQ3xJxCSWUieFTyoMl4UnW64md
+QBI+ZkLkS7O71pARnw0SdE4nxO1J8fLPi/7nYHiGfebqcoBC/AUwMM/Zni9KFkgy
+/uQRXUylNAgAByIdG6vS4ULgTKh34FS08Ff7/cWZppe9eUogLLQ+J2cyPupN8LYd
+hWC1mCbgCX3QqHiHg6ACX05Zc3YFW80ddlczDVNpM09g1GSGYpllng==
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/code-ee.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:code-ee
+extension:extKeyUsage:codeSigning
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ee-from-expired-ca.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICvjCCAaigAwIBAgIUMUZEIRRo2v0demTGW3vuRccAgCMwCwYJKoZIhvcNAQEL
+MBUxEzARBgNVBAMMCmV4cGlyZWQtY2EwIhgPMjAxNDExMjcwMDAwMDBaGA8yMDE3
+MDIwNDAwMDAwMFowHTEbMBkGA1UEAwwSZWUtZnJvbS1leHBpcmVkLWNhMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohRqESOFtZB/W62iAY2ED08E9nq
+5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+KvWnVramRxCHqlWqdFh/cc1SSc
+An7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+rWkasdMCOosqQe6ncOAPDY39
+ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYk
+zBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5Fw6naOGzey8ib2njtIqVYR3u
+JtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXtjQIDAQAB
+MAsGCSqGSIb3DQEBCwOCAQEABbpfCUwzbTCDWWwBqaY8+3q3PjeQK/QdyI4HSX5C
++dp7LJF+x/24xArqKf8HTuhndprUvlJOFkojK1CLaece7yC1fh/viFZ6NLoTPNXU
+cmdEHsrzO4LTOY/eeR9ml7Rx26B50Wva01SyXkW9TZbPGPQysCgD31XkxmzTAG9t
+M5kp+XplMd/UEjkNQaXD0lzm3lJ+3n2U6xMmDc+8us0l6X8yBmjjywBWTSX+U83a
+eZXMpU40Y4ZHyNqfALGZUG22trd+68YVvK7jmnbk9fu/FZkjh0qiPlAUJXg0OybW
+YHerQxXuf+5+ftPTDkzyPY9txQGFoqY8k3zVQNw33wFzGQ==
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ee-from-expired-ca.pem.certspec
@@ -0,0 +1,2 @@
+issuer:expired-ca
+subject:ee-from-expired-ca
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ee-from-untrusted-ca.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaygAwIBAgIUTUHM6wHTfIkC0P4Z9VRrPJV6O6IwCwYJKoZIhvcNAQEL
+MBcxFTATBgNVBAMMDHVudHJ1c3RlZC1jYTAiGA8yMDE0MTEyNzAwMDAwMFoYDzIw
+MTcwMjA0MDAwMDAwWjAfMR0wGwYDVQQDDBRlZS1mcm9tLXVudHJ1c3RlZC1jYTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9
+PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3
+HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3Dg
+Dw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7
+EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SK
+lWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0C
+AwEAATALBgkqhkiG9w0BAQsDggEBAJlRi+i7+kPXxfx6If69aQMsAIYwBXhbeHJr
+TfaljltazfCirKB1hDb/pTYmSFMWDO+C9GIRBBKWR4+rR6D8n1qiJOJqe+QHtQam
+BPi8xMTHEkNVTEax+Ux2im21BPUU8xFzCta/STMCt2E+6g832JX1XxLxRlp631Vn
+pF9MFZU9HQqW4z8YBPPKE4ny9eBOGH/PzYHETL5AgJn1K5iRFZjA94iwqsHvJ/6v
+AY1b5hw1slwem9ZWYcoUUl3YAV7sF3pIbakrRSjU3HEfGcDUDOePrBZekJhICwK4
+xs2cqEX0FLZqsNiS7rpfRZXt4Ufl6V3G8MEO010lICk9ZuHr9vc=
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ee-from-untrusted-ca.pem.certspec
@@ -0,0 +1,2 @@
+issuer:untrusted-ca
+subject:ee-from-untrusted-ca
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/email-ee.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxTCCAa+gAwIBAgIUI2oh2cgrnM8p3D/8Ijd06wwY/UQwCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBMxETAPBgNVBAMMCGVtYWlsLWVlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4Ngf
+vbGcBptuGobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTb
+uUzCa2wO7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3S
+O8XguEgfqDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR
+3bTK9/ytHSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv
+5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXtjQIDAQABoxcwFTATBgNVHSUEDDAKBggr
+BgEFBQcDBDALBgkqhkiG9w0BAQsDggEBAIpPVolSwoZTwhouPemDUJTP8cZ/IPTg
+0GvzU07GH7y0Q9svPEBELRdgdHTWk3s5FaLgVGYStzs9OOpNj4fiP+CUJIwKlm6L
+Kt4mPganE67SRvHHYMzH+jjaL+xNl0Wa0O9ms+k+DQ+zB57hX8qE1oMszq00jZxH
+VIRl767e66Jgh89ac5BGoj1KXJxtUIocTKC+fMgUHbQ4oZ2v1IU2CeE6k2cvWvcU
+gclagK4EgWzIL8O2HLTLkLN163yWBYiOWQTOI+hCqsLz1OeU+J8pZ/eEYemeUV7g
+opZ5aLRzvXAkNz/eaeygEAu+6wkqVj3Btcabvx7dxmLkwDV8PjJsscs=
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/email-ee.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:email-ee
+extension:extKeyUsage:emailProtection
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/expired-ca.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIICzTCCAbegAwIBAgIUAfElDw37NeFULPHd+G2eoaHpvEYwCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTAwMTAxMDAwMDAwWhgPMjAxMTAxMDEwMDAw
+MDBaMBUxEzARBgNVBAMMCmV4cGlyZWQtY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg
+2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ
+5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQ
+PdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGj
+DJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8W
+iy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjHTAbMAwGA1UdEwQFMAMB
+Af8wCwYDVR0PBAQDAgEGMAsGCSqGSIb3DQEBCwOCAQEAde8CQNB8dVo5ly7Lu8x9
+5yDz2hpzAqqPDxP3+UqxzEgXeA4vfv1Bzvmxx69XEd+884M9Lkt2WBTrc+OrAgqX
+pCCt4X8bjV2t+mG1shtYEGKk5BtRVnorHhZyf6+5xtOfpV9DeWkf/aA1SJK1Kpt3
+cNSDW10PwaGuaNiUMEtIFLD/MYZCM98RFOSVDWjqafbfUBn4ZSeoyRi1C2d3lg0C
+jRFmOc1I4DQOUezp3C0WyCumJ0SLTIoYJGdAshMbDWPr0OOaB4GmI8miKhS6LM59
+o6C3fU8MJrRYKctYj0k9gW0DI6KuEFZj2AY8brv6Ufx1TKy5Z2pqIPeUbuJInCXM
+qA==
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/expired-ca.pem.certspec
@@ -0,0 +1,5 @@
+issuer:ca
+subject:expired-ca
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
+validity:20100101-20110101
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/invalid.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICvDCCAaagAwIBAgIUI3mu28hwWjSE4ii2aLFNdXKo79MwCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBIxEDAOBgNVBAMMB2ludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
+sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
+TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
+xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
+tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
+8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAGjDzANMAsGA1UdDwQEAwIBBjAL
+BgkqhkiG9w0BAQsDggEBACKFOLNLmPB5hFhmP3cruJydC3/5/1sKPmig+c5MMBKN
+hgKaPhU6JalCdrHK+httffvjwXkPRdqWHWM9ILcDcAuYzJqIMofiFlW6gthTvvdP
+sqkqXdxC2S00Dc55z47mKbLPkZm7/HMSOAya6oghywLuL3US6cmKrYZZbFqrecWc
+GIja9MtthFcoS84u+GmV3pRiU+sDvwo67u7R3recmAPDU75r9Yhh68H/urKoRhre
++10QOfQ0GGM80RP2fXg6P9MXI7/MEd8QTlUOK8xWrU6Q30R5BzF6lgwUqF5VoVxb
+WMPdPIS5gFktfqNituRNdMKlIFQ6f7YjaILDcu3upe0=
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/invalid.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:invalid
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/md5-ee.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqjCCAZSgAwIBAgIUT89onfON5U+5LLJ7imzzschILDgwCwYJKoZIhvcNAQEE
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBExDzANBgNVBAMMBm1kNS1lZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72x
+nAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lM
+wmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF
+4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20
+yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xx
+j5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAATALBgkqhkiG9w0BAQQDggEBAB4q
+QfSzrkQOHwIeVw/W1bpAzJ5Al92wDUNQEcw7JmZZ6Oz3bH+spBhq6xTnXqhMjCYM
+srINOlc+u/W6TqE1uPWPZvX1M9VFCWR5okXoFbc+8l6er5tun6tP7oWs7TxXzy7O
+e0GimlZ3W+LqA2ICynSYaULipFAJUvmmyFxlC3yPIawncpBWwPofPpGziF0FImSW
+PMslU5PExu982go8a6hfNAYEYH8bKetlfFPJ0DHe7/crmjE3NulnHt7HVh11OkuR
+FkjVTnuOoHGG4Z4tekPP0g1P+9m3EdTuP9Nk8hTZBThmRdAWIeBaefJJmZ91gJqA
+txFeIhOo4f1whxqNDk4=
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/md5-ee.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:md5-ee
+signature:md5WithRSAEncryption
--- a/security/manager/ssl/tests/mochitest/browser/moz.build
+++ b/security/manager/ssl/tests/mochitest/browser/moz.build
@@ -1,8 +1,30 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 BROWSER_CHROME_MANIFESTS += ['browser.ini']
 
+# Temporarily disabled. See bug 1256495.
+# (Note that when this gets enabled, some extra work will have to happen so
+# that the mochitest harness knows where to get the generated certificates -
+# right now it assumes they're in the source directory, which isn't the case
+# when they're automatically generated.)
+#test_certificates = (
+#    'ca.pem',
+#    'code-ee.pem',
+#    'ee-from-expired-ca.pem',
+#    'ee-from-untrusted-ca.pem',
+#    'email-ee.pem',
+#    'expired-ca.pem',
+#    'invalid.pem',
+#    'md5-ee.pem',
+#    'revoked.pem',
+#    'ssl-ee.pem',
+#    'unknown-issuer.pem',
+#    'untrusted-ca.pem',
+#)
+#
+#for test_certificate in test_certificates:
+#    GeneratedTestCertificate(test_certificate)
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/revoked.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqzCCAZWgAwIBAgIUIYb+7rSz8q+7zTVh7KE/MZTclrAwCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBIxEDAOBgNVBAMMB3Jldm9rZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9
+sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5
+TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7
+xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHd
+tMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l
+8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZIhvcNAQELA4IBAQBF
+h+yu2y2s3gulEXR80Hmm45+B/egT1K2fjoz8X5BcbqT5BcbPB4utokvUQq3W6uyr
+AHVmo55vpgbWp1Thz0RoHGZ5kkYlcrYy1S7sfuoowoMXv8iWu9DSyXqhqSUhYp9F
+9sov5d5lyeHLAekss1Aaybq0vh1O1tHtKHoanlfn5HEBDjbNpQozPh/kGQTuSZVY
+e9Ikh1lFNsUCzCElC+wdkATQbo5PpGEsJqk5bmz7W9l90j7+JFdH5onIFD4gSOK8
+2hsPCFDhmnma8/CvAY08hwEYmb26gnGQbVusIPr+Ui7LjUqW9b6XAdon2teXXEoa
+vCp11ICfcHvIHhoLDjkC
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/revoked.pem.certspec
@@ -0,0 +1,2 @@
+issuer:ca
+subject:revoked
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ssl-ee.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIICzTCCAbegAwIBAgIUZ71J5xveWHK5SkrwbRXbsbUtrlgwCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBExDzANBgNVBAMMBnNzbC1lZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72x
+nAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lM
+wmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF
+4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20
+yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xx
+j5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaMhMB8wHQYDVR0lBBYwFAYIKwYB
+BQUHAwEGCCsGAQUFBwMCMAsGCSqGSIb3DQEBCwOCAQEAkDks1086hp7MS0anvQw8
+XnkD8ItCFkcVk3aPdLlwODBGqDvrjIR9kCX2aJzdChiCnKPtN5pDiyfb/e+lJ4zN
+qXoSP2ksYbFtFr7Vp/eDEI9iwvFTEubYgq9Y8etInetFxEqRQPDtAYtZF7P6i1su
+FZUHlHYHsVmCCXXlhTy6BhmJCj0ANaquHHuACty55uNw2IbNYUKN7xp1qOJO2TUc
+ip4fybk+Rdm5fJOj48W7uUBpvzfnLI/ifABuVRy2koZvIewjAwwPZ8ggWyi6PHT3
+iLrLmorNMDWTWN898zO09skrcobFKrWJCuSafAeZYCYHDC7x1uVlLDM+v6N+fN14
+RA==
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/ssl-ee.pem.certspec
@@ -0,0 +1,3 @@
+issuer:ca
+subject:ssl-ee
+extension:extKeyUsage:serverAuth,clientAuth
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/unknown-issuer.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICtzCCAaGgAwIBAgIUc97erK6I1KzZpBDPfRQkFj/yzHQwCwYJKoZIhvcNAQEL
+MBIxEDAOBgNVBAMMB3Vua25vd24wIhgPMjAxNDExMjcwMDAwMDBaGA8yMDE3MDIw
+NDAwMDAwMFowGTEXMBUGA1UEAwwOdW5rbm93bi1pc3N1ZXIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVo
+V2wke8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p
+0DggKZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKk
+fbmIYXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZh
+W7filhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EI
+TjbLHCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZI
+hvcNAQELA4IBAQAzi/BVt5ZYRAbAI1sue6Qduqlk6OwVuROZS92xoo1G+bqJuMvv
+K1jiJWeZn1xGGrZcCeyTnf+Qst4Hd34PLApNHfDPdNW9C7QiTUva4GELCZsCS0+b
+hkX1W62OCS2gY64KVriAzbdKgx8nWhxlEa8zKBJEhWsX0t6PmjCxTEp1uyyJDlgg
+vG4OEvUxywbk/MDnsjs7pJ3jUZ3DVQb9t6+z5w29AL7qpzo0CZ77YEuZsV6IuAtg
+mNG1jfg7EkWBuxhHoI9UCqMquS4S9IHhuaDQ/qK8hBvjXTRsXyCKuwvIcxEns2aq
+1fIW02nd0nX6+UxASTfY+grYNE8US2XFluE3
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/unknown-issuer.pem.certspec
@@ -0,0 +1,2 @@
+issuer:unknown
+subject:unknown-issuer
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/untrusted-ca.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIICzzCCAbmgAwIBAgIUC/H/PjmG29sIm7mYo9C4emq7th8wCwYJKoZIhvcNAQEL
+MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
+MDBaMBcxFTATBgNVBAMMDHVudHJ1c3RlZC1jYTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wccl
+qODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sg
+w0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCx
+V5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1
+MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQs
+vxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaMdMBswDAYDVR0TBAUw
+AwEB/zALBgNVHQ8EBAMCAQYwCwYJKoZIhvcNAQELA4IBAQB0kH+mBoFNCKtakbPa
+WoptSlYB3v0Hivr64+6RGgbE1Ns0ZcEUpid/0PYCPo+2LE7Db6LRMmygQZ67G5Wq
+SQN9Wb2WR/RqwikX+UbsbRuTElM+QMQ2AmOKBjmF7krzixq3zP9/c+CtSN4+E6Qo
+XvH6GO3HWJ/7QdS/oGgbP63O9BszCOmZRAjNcBstwiVSxKSvJHpelbHsN7Ml4k0c
+CXRkxIebfNUcHSSAgDme7f0bGgG8XJSGONebLAJgQcq59EHYD5sE2xR0rF2lmFEq
+LO5IlW7TfTEGSQyinYO09nXcwuIbyFdYKaEBtE+ol6GIQyZGcb2AqSVXiseEWVId
+B0CN
+-----END CERTIFICATE-----
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/untrusted-ca.pem.certspec
@@ -0,0 +1,4 @@
+issuer:ca
+subject:untrusted-ca
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
--- a/testing/mochitest/browser.eslintrc
+++ b/testing/mochitest/browser.eslintrc
@@ -30,16 +30,17 @@
     "info": false,
     "is": false,
     "isnot": false,
     "ok": false,
     "registerCleanupFunction": false,
     "requestLongerTimeout": false,
     "SimpleTest": false,
     "SpecialPowers": false,
+    "TestUtils": false,
     "thisTestLeaksUncaughtRejectionsAndShouldBeFixed": false,
     "todo": false,
     "todo_is": false,
     "todo_isnot": false,
     "waitForClipboard": false,
     "waitForExplicitFinish": false,
     "waitForFocus": false,
   }