Backed out changeset 44635c073692 (bug 1345058) on suspicion of causing intermittent xpcshell failures in toolkit/components/url-classifier/tests/unit/test_bug1274685_unowned_list.js on OS X. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 19 May 2017 13:13:18 +0200
changeset 409661 939f52993a6bae4a040a77156c3fda0ce44d53a6
parent 409660 a1a117e6fc22090174fcc92f2131e3e131c68471
child 409662 74890c4c6bc34ef7fa965c391f5aae4f6b6cddcf
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1345058
milestone55.0a1
backs out44635c0736928ed71f080bec6d1e46778edc9cfe
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
Backed out changeset 44635c073692 (bug 1345058) on suspicion of causing intermittent xpcshell failures in toolkit/components/url-classifier/tests/unit/test_bug1274685_unowned_list.js on OS X. r=backout
dom/base/nsDocument.cpp
dom/base/nsDocument.h
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -264,17 +264,16 @@
 #include "nsISpeculativeConnect.h"
 
 #include "mozilla/MediaManager.h"
 #ifdef MOZ_WEBRTC
 #include "IPeerConnection.h"
 #endif // MOZ_WEBRTC
 
 #include "nsIURIClassifier.h"
-#include "mozilla/ClearOnShutdown.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 static LazyLogModule gDocumentLeakPRLog("DocumentLeak");
 static LazyLogModule gCspPRLog("CSP");
@@ -305,75 +304,16 @@ GetHttpChannelHelper(nsIChannel* aChanne
   }
 
   httpChannel = do_QueryInterface(baseChannel);
   httpChannel.forget(aHttpChannel);
 
   return NS_OK;
 }
 
-////////////////////////////////////////////////////////////////////
-// PrincipalFlashClassifier
-
-// Classify the flash based on the document principal.
-// The usage of this class is as follows:
-//
-// 1) Call AsyncClassify() as early as possible to asynchronously do
-//    classification against all the flash blocking related tables
-//    via nsIURIClassifier.asyncClassifyLocalWithTables.
-//
-// 2) At any time you need the classification result, call Result()
-//    and it is guaranteed to give you the result. Note that you have
-//    to specify "aIsThirdParty" to the function so please make sure
-//    you can already corretly decide if the document is third-party.
-//
-//    Behind the scenes, the sync classification API
-//    (nsIURIClassifier.classifyLocalWithTable) may be called as a fallback to
-//    synchronously get the result if the asyncClassifyLocalWithTables hasn't
-//    been done yet.
-//
-// 3) You can call Result() as many times as you want and only the first time
-//    may it unfortunately call the blocking sync API. The subsequent call
-//    will just return the result we came out in the first time.
-//
-class PrincipalFlashClassifier final : public nsIURIClassifierCallback
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIURICLASSIFIERCALLBACK
-
-  explicit PrincipalFlashClassifier();
-
-  // Fire async classification based on the given principal.
-  void AsyncClassify(nsIPrincipal* aPrincipal);
-
-  // Would block if the result hasn't come out.
-  mozilla::dom::FlashClassification Result(nsIPrincipal* aPrincipal,
-                                           bool aIsThirdParty);
-
-private:
-  ~PrincipalFlashClassifier() = default;
-
-  void Reset();
-  bool EnsureUriClassifier();
-  mozilla::dom::FlashClassification CheckIfClassifyNeeded(nsIPrincipal* aPrincipal);
-  mozilla::dom::FlashClassification Resolve(bool aIsThirdParty);
-  mozilla::dom::FlashClassification AsyncClassifyInternal(nsIPrincipal* aPrincipal);
-  nsCString GetClassificationTables(bool aIsThirdParty);
-
-  // For the fallback sync classification.
-  nsCOMPtr<nsIURI> mClassificationURI;
-
-  nsCOMPtr<nsIURIClassifier> mUriClassifier;
-  bool mAsyncClassified;
-  nsTArray<nsCString> mMatchedTables;
-  mozilla::dom::FlashClassification mResult;
-};
-
-
 #define NAME_NOT_VALID ((nsSimpleContentList*)1)
 
 nsIdentifierMapEntry::~nsIdentifierMapEntry()
 {
 }
 
 void
 nsIdentifierMapEntry::Traverse(nsCycleCollectionTraversalCallback* aCallback)
@@ -1491,20 +1431,16 @@ nsDocument::nsDocument(const char* aCont
 
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
 
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
 
   // void state used to differentiate an empty source from an unselected source
   mPreloadPictureFoundSource.SetIsVoid(true);
-
-  // For determining if this is a flash document which should be
-  // blocked based on its principal.
-  mPrincipalFlashClassifier = new PrincipalFlashClassifier();
 }
 
 void
 nsDocument::ClearAllBoxObjects()
 {
   if (mBoxObjectTable) {
     for (auto iter = mBoxObjectTable->Iter(); !iter.Done(); iter.Next()) {
       nsPIBoxObject* boxObject = iter.UserData();
@@ -2643,21 +2579,16 @@ nsDocument::StartDocumentLoad(const char
   }
 
   // If this is not a data document, set CSP.
   if (!mLoadedAsData) {
     nsresult rv = InitCSP(aChannel);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // Perform a async flash classification based on the doc principal
-  // in an early stage to reduce the blocking time.
-  mFlashClassification = FlashClassification::Unclassified;
-  mPrincipalFlashClassifier->AsyncClassify(GetPrincipal());
-
   return NS_OK;
 }
 
 void
 nsDocument::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages)
 {
   for (uint32_t i = 0; i < aMessages.Length(); ++i) {
     nsAutoString messageTag;
@@ -13248,31 +13179,16 @@ nsIDocument::UpdateStyleBackendType()
     NS_WARNING("stylo: No docshell yet, assuming Gecko style system");
   } else if (nsLayoutUtils::SupportsServoStyleBackend(this)) {
     mStyleBackendType = StyleBackendType::Servo;
   }
 #endif
 }
 
 /**
- * Retrieves the classification of the Flash plugins in the document based on
- * the classification lists. We perform AsyncInitFlashClassification on
- * StartDocumentLoad() and the result may not be initialized when this function
- * gets called. In that case, We can only unfortunately have a blocking wait.
- *
- * For more information, see
- * toolkit/components/url-classifier/flash-block-lists.rst
- */
-FlashClassification
-nsDocument::PrincipalFlashClassification()
-{
-  return mPrincipalFlashClassifier->Result(GetPrincipal(), IsThirdParty());
-}
-
-/**
  * Helper function for |nsDocument::PrincipalFlashClassification|
  *
  * Adds a table name string to a table list (a comma separated string). The
  * table will not be added if the name is an empty string.
  */
 static void
 MaybeAddTableToTableList(const nsACString& aTableNames,
                          nsACString& aTableList)
@@ -13302,356 +13218,134 @@ ArrayContainsTable(const nsTArray<nsCStr
     // cannot contain another existing table name.
     if (FindInReadable(table, aTableNames)) {
       return true;
     }
   }
   return false;
 }
 
-namespace {
-
-// An object to store all preferences we need for flash blocking feature.
-struct PrefStore
-{
-  PrefStore()
-  {
-    Preferences::AddBoolVarCache(&mFlashBlockEnabled,
-                                 "plugins.flashBlock.enabled");
-    Preferences::AddBoolVarCache(&mPluginsHttpOnly,
-                                 "plugins.http_https_only");
-
-    // We only need to register string-typed preferences.
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowTable", this);
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowExceptTable", this);
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashTable", this);
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashExceptTable", this);
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocTable", this);
-    Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocExceptTable", this);
-
-    UpdateStringPrefs();
-  }
-
-  ~PrefStore()
-  {
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowTable", this);
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowExceptTable", this);
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashTable", this);
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashExceptTable", this);
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocTable", this);
-    Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocExceptTable", this);
-  }
-
-  void UpdateStringPrefs()
-  {
-    Preferences::GetCString("urlclassifier.flashAllowTable", &mAllowTables);
-    Preferences::GetCString("urlclassifier.flashAllowExceptTable", &mAllowExceptionsTables);
-    Preferences::GetCString("urlclassifier.flashTable", &mDenyTables);
-    Preferences::GetCString("urlclassifier.flashExceptTable", &mDenyExceptionsTables);
-    Preferences::GetCString("urlclassifier.flashSubDocTable", &mSubDocDenyTables);
-    Preferences::GetCString("urlclassifier.flashSubDocExceptTable", &mSubDocDenyExceptionsTables);
-  }
-
-  static void UpdateStringPrefs(const char*, void* aClosure)
-  {
-    static_cast<PrefStore*>(aClosure)->UpdateStringPrefs();
-  }
-
-  bool mFlashBlockEnabled;
-  bool mPluginsHttpOnly;
-
-  nsCString mAllowTables;
-  nsCString mAllowExceptionsTables;
-  nsCString mDenyTables;
-  nsCString mDenyExceptionsTables;
-  nsCString mSubDocDenyTables;
-  nsCString mSubDocDenyExceptionsTables;
-};
-
-static const
-PrefStore& GetPrefStore()
-{
-  static UniquePtr<PrefStore> sPrefStore;
-  if (!sPrefStore) {
-    sPrefStore.reset(new PrefStore());
-    ClearOnShutdown(&sPrefStore);
-  }
-  return *sPrefStore;
-}
-
-} // end of unnamed namespace.
-
-////////////////////////////////////////////////////////////////////
-// PrincipalFlashClassifier implementation.
-
-NS_IMPL_ISUPPORTS(PrincipalFlashClassifier, nsIURIClassifierCallback)
-
-PrincipalFlashClassifier::PrincipalFlashClassifier()
-{
-  Reset();
-}
-
-void
-PrincipalFlashClassifier::Reset()
-{
-  mAsyncClassified = false;
-  mMatchedTables.Clear();
-  mResult = FlashClassification::Unclassified;
-}
-
-nsCString
-PrincipalFlashClassifier::GetClassificationTables(bool aIsThirdParty)
-{
-  nsAutoCString tables;
-  auto& prefs = GetPrefStore();
-
-  MaybeAddTableToTableList(prefs.mAllowTables, tables);
-  MaybeAddTableToTableList(prefs.mAllowExceptionsTables, tables);
-  MaybeAddTableToTableList(prefs.mDenyTables, tables);
-  MaybeAddTableToTableList(prefs.mDenyExceptionsTables, tables);
-
-  if (aIsThirdParty) {
-    MaybeAddTableToTableList(prefs.mSubDocDenyTables, tables);
-    MaybeAddTableToTableList(prefs.mSubDocDenyExceptionsTables, tables);
-  }
-
-  return tables;
-}
-
-bool
-PrincipalFlashClassifier::EnsureUriClassifier()
-{
-  if (mUriClassifier) {
-    return true;
-  }
-  mUriClassifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
-  return !!mUriClassifier;
-}
-
+/**
+ * Retrieves the classification of the Flash plugins in the document based on
+ * the classification lists.
+ *
+ * For more information, see
+ * toolkit/components/url-classifier/flash-block-lists.rst
+ */
 FlashClassification
-PrincipalFlashClassifier::Result(nsIPrincipal* aPrincipal, bool aIsThirdParty)
-{
-  if (FlashClassification::Unclassified != mResult) {
-    // We already have the result. Just return it.
-    return mResult;
-  }
-
-  // TODO: Bug 1342333 - Entirely remove the use of the sync API
-  // (ClassifyLocalWithTables).
-  if (!mAsyncClassified) {
-
-    //
-    // We may
-    //   1) have called AsyncClassifyLocalWithTables but OnClassifyComplete
-    //      hasn't been called.
-    //   2) haven't even called AsyncClassifyLocalWithTables.
-    //
-    // In both cases we need to do the synchronous classification as the fallback.
-    //
-
-    if (!EnsureUriClassifier()) {
-      return FlashClassification::Denied;
-    }
-    mResult = CheckIfClassifyNeeded(aPrincipal);
-    if (FlashClassification::Unclassified != mResult) {
-      return mResult;
-    }
-
-    nsCString classificationTables = GetClassificationTables(aIsThirdParty);
-    nsresult rv = mUriClassifier->ClassifyLocalWithTables(mClassificationURI,
-                                                          classificationTables,
-                                                          mMatchedTables);
-    if (NS_FAILED(rv)) {
-      if (rv == NS_ERROR_MALFORMED_URI) {
-        // This means that the URI had no hostname (ex: file://doc.html). In this
-        // case, we allow the default (Unknown plugin) behavior.
-        mResult = FlashClassification::Unknown;
-      } else {
-        mResult = FlashClassification::Denied;
-      }
-      return mResult;
-    }
-  }
-
-  // Resolve the result based on mMatchedTables and aIsThirdParty.
-  mResult = Resolve(aIsThirdParty);
-  MOZ_ASSERT(FlashClassification::Unclassified != mResult);
-
-  // The subsequent call of Result() will return the resolved result
-  // and never reach here until Reset() is called.
-  return mResult;
-}
-
-/*virtual*/ nsresult
-PrincipalFlashClassifier::OnClassifyComplete(nsresult /*aErrorCode*/,
-                                             const nsACString& aLists, // Only this matters.
-                                             const nsACString& /*aProvider*/,
-                                             const nsACString& /*aPrefix*/)
-{
-  mAsyncClassified = true;
-
-  if (FlashClassification::Unclassified != mResult) {
-    // Result() has been called prior to this callback.
-    return NS_OK;
-  }
-
-  // TODO: Bug 1364804 - We should use a callback type which notifies
-  // the result as a string array rather than a formatted string.
-
-  // We only populate the matched list without resolving the classification
-  // result because we are not sure if the parent doc has been properly set.
-  // We also parse the comma-separated tables to array. (the code is copied
-  // from Classifier::SplitTables.)
-  nsACString::const_iterator begin, iter, end;
-  aLists.BeginReading(begin);
-  aLists.EndReading(end);
-  while (begin != end) {
-    iter = begin;
-    FindCharInReadable(',', iter, end);
-    nsDependentCSubstring table = Substring(begin,iter);
-    if (!table.IsEmpty()) {
-      mMatchedTables.AppendElement(Substring(begin, iter));
-    }
-    begin = iter;
-    if (begin != end) {
-      begin++;
-    }
-  }
-
-  return NS_OK;
-}
-
-// We resolve the classification result based on aIsThirdParty
-// and the matched tables we got ealier on (via either sync or async API).
-FlashClassification
-PrincipalFlashClassifier::Resolve(bool aIsThirdParty)
-{
-  MOZ_ASSERT(FlashClassification::Unclassified == mResult,
-             "We already have resolved classification result.");
-
-  if (mMatchedTables.IsEmpty()) {
-    return FlashClassification::Unknown;
-  }
-
-  auto& prefs = GetPrefStore();
-  if (ArrayContainsTable(mMatchedTables, prefs.mDenyTables) &&
-      !ArrayContainsTable(mMatchedTables, prefs.mDenyExceptionsTables)) {
-    return FlashClassification::Denied;
-  } else if (ArrayContainsTable(mMatchedTables, prefs.mAllowTables) &&
-             !ArrayContainsTable(mMatchedTables, prefs.mAllowExceptionsTables)) {
-    return FlashClassification::Allowed;
-  }
-
-  if (aIsThirdParty && ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyTables) &&
-      !ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyExceptionsTables)) {
-    return FlashClassification::Denied;
-  }
-
-  return FlashClassification::Unknown;
-}
-
-void
-PrincipalFlashClassifier::AsyncClassify(nsIPrincipal* aPrincipal)
-{
-  MOZ_ASSERT(FlashClassification::Unclassified == mResult,
-             "The old classification result should be reset first.");
-  Reset();
-  mResult = AsyncClassifyInternal(aPrincipal);
-}
-
-FlashClassification
-PrincipalFlashClassifier::CheckIfClassifyNeeded(nsIPrincipal* aPrincipal)
+nsDocument::PrincipalFlashClassification()
 {
   nsresult rv;
-  auto& prefs = GetPrefStore();
+
+  bool httpOnly = Preferences::GetBool("plugins.http_https_only", true);
+  bool flashBlock = Preferences::GetBool("plugins.flashBlock.enabled", false);
 
   // If neither pref is on, skip the null-principal and principal URI checks.
-  if (prefs.mPluginsHttpOnly && !prefs.mFlashBlockEnabled) {
+  if (!httpOnly && !flashBlock) {
     return FlashClassification::Unknown;
   }
 
-  nsCOMPtr<nsIPrincipal> principal = aPrincipal;
+  nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
   if (principal->GetIsNullPrincipal()) {
     return FlashClassification::Denied;
   }
 
   nsCOMPtr<nsIURI> classificationURI;
   rv = principal->GetURI(getter_AddRefs(classificationURI));
   if (NS_FAILED(rv) || !classificationURI) {
     return FlashClassification::Denied;
   }
 
-  if (prefs.mPluginsHttpOnly) {
+  if (httpOnly) {
     // Only allow plugins for documents from an HTTP/HTTPS origin. This should
     // allow dependent data: URIs to load plugins, but not:
     // * chrome documents
     // * "bare" data: loads
     // * FTP/gopher/file
     nsAutoCString scheme;
     rv = classificationURI->GetScheme(scheme);
     if (NS_WARN_IF(NS_FAILED(rv)) ||
         !(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
       return FlashClassification::Denied;
     }
   }
 
   // If flash blocking is disabled, it is equivalent to all sites being
   // on neither list.
-  if (!prefs.mFlashBlockEnabled) {
+  if (!flashBlock) {
     return FlashClassification::Unknown;
   }
 
-  return FlashClassification::Unclassified;
-}
-
-// Using nsIURIClassifier.asyncClassifyLocalWithTables to do classification
-// against the flash related tables based on the given principal.
-FlashClassification
-PrincipalFlashClassifier::AsyncClassifyInternal(nsIPrincipal* aPrincipal)
-{
-  auto result = CheckIfClassifyNeeded(aPrincipal);
-  if (FlashClassification::Unclassified != result) {
-    return result;
-  }
-
-  // We haven't been able to decide if it's a third party document
-  // since determining if a document is third-party may depend on its
-  // parent document. At the time we call AsyncClassifyInternal
-  // (i.e. StartDocumentLoad) the parent document may not have been
-  // set. As a result, we wait until Resolve() to be called to
-  // take "is third party" into account. At this point, we just assume
-  // it's third-party to include every list.
-  nsCString tables = GetClassificationTables(true);
+  nsAutoCString allowTables, allowExceptionsTables,
+                denyTables, denyExceptionsTables,
+                subDocDenyTables, subDocDenyExceptionsTables,
+                tables;
+  Preferences::GetCString("urlclassifier.flashAllowTable", &allowTables);
+  MaybeAddTableToTableList(allowTables, tables);
+  Preferences::GetCString("urlclassifier.flashAllowExceptTable",
+                          &allowExceptionsTables);
+  MaybeAddTableToTableList(allowExceptionsTables, tables);
+  Preferences::GetCString("urlclassifier.flashTable", &denyTables);
+  MaybeAddTableToTableList(denyTables, tables);
+  Preferences::GetCString("urlclassifier.flashExceptTable",
+                          &denyExceptionsTables);
+  MaybeAddTableToTableList(denyExceptionsTables, tables);
+
+  bool isThirdPartyDoc = IsThirdParty();
+  if (isThirdPartyDoc) {
+    Preferences::GetCString("urlclassifier.flashSubDocTable",
+                            &subDocDenyTables);
+    MaybeAddTableToTableList(subDocDenyTables, tables);
+    Preferences::GetCString("urlclassifier.flashSubDocExceptTable",
+                            &subDocDenyExceptionsTables);
+    MaybeAddTableToTableList(subDocDenyExceptionsTables, tables);
+  }
+
   if (tables.IsEmpty()) {
     return FlashClassification::Unknown;
   }
 
-  if (!EnsureUriClassifier()) {
+  nsCOMPtr<nsIURIClassifier> uriClassifier =
+    do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
     return FlashClassification::Denied;
   }
 
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(mClassificationURI));
-  if (NS_FAILED(rv) || !mClassificationURI) {
-    return FlashClassification::Denied;
-  }
-
-  rv = mUriClassifier->AsyncClassifyLocalWithTables(mClassificationURI,
-                                                    tables,
-                                                    this);
+  nsTArray<nsCString> results;
+  rv = uriClassifier->ClassifyLocalWithTables(classificationURI,
+                                              tables,
+                                              results);
   if (NS_FAILED(rv)) {
     if (rv == NS_ERROR_MALFORMED_URI) {
       // This means that the URI had no hostname (ex: file://doc.html). In this
       // case, we allow the default (Unknown plugin) behavior.
       return FlashClassification::Unknown;
     } else {
       return FlashClassification::Denied;
     }
   }
 
-  return FlashClassification::Unclassified;
+  if (results.IsEmpty()) {
+    return FlashClassification::Unknown;
+  }
+
+  if (ArrayContainsTable(results, denyTables) &&
+      !ArrayContainsTable(results, denyExceptionsTables)) {
+    return FlashClassification::Denied;
+  } else if (ArrayContainsTable(results, allowTables) &&
+             !ArrayContainsTable(results, allowExceptionsTables)) {
+    return FlashClassification::Allowed;
+  }
+
+  if (isThirdPartyDoc && ArrayContainsTable(results, subDocDenyTables) &&
+      !ArrayContainsTable(results, subDocDenyExceptionsTables)) {
+    return FlashClassification::Denied;
+  }
+
+  return FlashClassification::Unknown;
 }
 
 FlashClassification
 nsDocument::ComputeFlashClassification()
 {
   nsCOMPtr<nsIDocShellTreeItem> current = this->GetDocShell();
   if (!current) {
     return FlashClassification::Denied;
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -66,17 +66,16 @@
 #include "mozilla/Attributes.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "jsfriendapi.h"
 #include "ImportManager.h"
 #include "mozilla/LinkedList.h"
 #include "CustomElementRegistry.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/Maybe.h"
-#include "nsIURIClassifier.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
 
 class nsDOMStyleSheetSetList;
@@ -551,19 +550,16 @@ protected:
                                nsILoadGroup* aLoadGroup,
                                nsIDocument* aDisplayDocument);
 
   nsClassHashtable<nsURIHashKey, ExternalResource> mMap;
   nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads;
   bool mHaveShutDown;
 };
 
-// For classifying a flash document based on its principal.
-class PrincipalFlashClassifier;
-
 // Base class for our document implementations.
 class nsDocument : public nsIDocument,
                    public nsIDOMDocument,
                    public nsIDOMDocumentXBL,
                    public nsSupportsWeakReference,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer,
                    public nsIApplicationCacheContainer,
@@ -1454,17 +1450,16 @@ protected:
   // full-screen element onto this stack, and when we cancel full-screen we
   // pop one off this stack, restoring the previous full-screen state
   nsTArray<nsWeakPtr> mFullScreenStack;
 
   // The root of the doc tree in which this document is in. This is only
   // non-null when this document is in fullscreen mode.
   nsWeakPtr mFullscreenRoot;
 
-  RefPtr<PrincipalFlashClassifier> mPrincipalFlashClassifier;
   mozilla::dom::FlashClassification mFlashClassification;
   // Do not use this value directly. Call the |IsThirdParty()| method, which
   // caches its result here.
   mozilla::Maybe<bool> mIsThirdParty;
 private:
   void UpdatePossiblyStaleDocumentState();
   static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
 
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -1645,16 +1645,22 @@ nsUrlClassifierDBService::Init()
   }
 
   sGethashNoise = Preferences::GetUint(GETHASH_NOISE_PREF,
     GETHASH_NOISE_DEFAULT);
   ReadTablesFromPrefs();
   nsresult rv;
 
   {
+    // Force PSM loading on main thread
+    nsCOMPtr<nsICryptoHash> dummy = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  {
     // Force nsIUrlClassifierUtils loading on main thread.
     nsCOMPtr<nsIUrlClassifierUtils> dummy =
       do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Directory providers must also be accessed on the main thread.
   nsCOMPtr<nsIFile> cacheDir;
@@ -1810,28 +1816,16 @@ nsUrlClassifierDBService::ClassifyLocal(
 NS_IMETHODIMP
 nsUrlClassifierDBService::AsyncClassifyLocalWithTables(nsIURI *aURI,
                                                        const nsACString& aTables,
                                                        nsIURIClassifierCallback* aCallback)
 {
   MOZ_ASSERT(NS_IsMainThread(), "AsyncClassifyLocalWithTables must be called "
                                 "on main thread");
 
-  // We do this check no matter what process we are in to return
-  // error as early as possible.
-  nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
-  NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
-
-  nsAutoCString key;
-  // Canonicalize the url
-  nsCOMPtr<nsIUrlClassifierUtils> utilsService =
-    do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
-  nsresult rv = utilsService->GetKeyForURI(uri, key);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   if (XRE_IsContentProcess()) {
     using namespace mozilla::dom;
     using namespace mozilla::ipc;
 
     ContentChild* content = ContentChild::GetSingleton();
     MOZ_ASSERT(content);
 
     auto actor = new URLClassifierLocalChild();
@@ -1854,16 +1848,26 @@ nsUrlClassifierDBService::AsyncClassifyL
 
   if (gShuttingDownThread) {
     return NS_ERROR_ABORT;
   }
 
   using namespace mozilla::Telemetry;
   auto startTime = TimeStamp::Now(); // For telemetry.
 
+  nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
+  NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
+
+  nsAutoCString key;
+  // Canonicalize the url
+  nsCOMPtr<nsIUrlClassifierUtils> utilsService =
+    do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
+  nsresult rv = utilsService->GetKeyForURI(uri, key);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   auto worker = mWorker;
   nsCString tables(aTables);
 
   // Since aCallback will be passed around threads...
   nsMainThreadPtrHandle<nsIURIClassifierCallback> callback(
     new nsMainThreadPtrHolder<nsIURIClassifierCallback>(aCallback));
 
   nsCOMPtr<nsIRunnable> r =