Bug 1522210 - Fingerprinting and cryptomining classifiers must have separate nsIWebProgressListener blocking state codes - part 1 - UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode, r=Ehsan
☠☠ backed out by 7def006b5421 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 30 Jan 2019 19:08:08 +0000
changeset 513998 00494efd99e7935d1de77aaa2aa62467d706fa05
parent 513997 cd7547ae0876c4101414cae7d8703cef10c73916
child 513999 1e7503dad26a5ea26c10601a002552b6696de333
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEhsan
bugs1522210
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1522210 - Fingerprinting and cryptomining classifiers must have separate nsIWebProgressListener blocking state codes - part 1 - UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode, r=Ehsan Differential Revision: https://phabricator.services.mozilla.com/D17637
docshell/base/nsDocShell.cpp
dom/base/ChromeUtils.cpp
dom/base/ChromeUtils.h
dom/base/Document.cpp
dom/base/Document.h
dom/base/nsImageLoadingContent.cpp
dom/base/nsObjectLoadingContent.cpp
dom/chrome-webidl/ChromeUtils.webidl
dom/html/HTMLMediaElement.cpp
dom/script/ScriptLoader.cpp
dom/webidl/HTMLDocument.webidl
layout/style/Loader.cpp
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/url-classifier/UrlClassifierCommon.cpp
netwerk/url-classifier/UrlClassifierFeatureFactory.cpp
netwerk/url-classifier/UrlClassifierFeatureFactory.h
netwerk/url-classifier/nsChannelClassifier.cpp
toolkit/components/aboutperformance/content/aboutPerformance.js
toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
toolkit/components/url-classifier/tests/mochitest/allowlistAnnotatedFrame.html
toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedFrame.html
toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -57,16 +57,17 @@
 #include "mozilla/dom/SessionStorageManager.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/ChildSHistory.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
 
 #include "mozilla/net/ReferrerPolicy.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsIAppShell.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 #include "nsICachingChannel.h"
@@ -6694,17 +6695,18 @@ nsresult nsDocShell::EndPageLoad(nsIWebP
       DisplayLoadError(aStatus, url, nullptr, aChannel);
       return NS_OK;
     }
 
     // Handle iframe document not loading error because source was
     // a tracking URL. We make a note of this iframe node by including
     // it in a dedicated array of blocked tracking nodes under its parent
     // document. (document of parent window of blocked document)
-    if (isTopFrame == false && aStatus == NS_ERROR_TRACKING_URI) {
+    if (!isTopFrame &&
+        UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aStatus)) {
       // frameElement is our nsIContent to be annotated
       RefPtr<Element> frameElement;
       nsPIDOMWindowOuter* thisWindow = GetWindow();
       if (!thisWindow) {
         return NS_OK;
       }
 
       frameElement = thisWindow->GetFrameElement();
@@ -6720,17 +6722,17 @@ nsresult nsDocShell::EndPageLoad(nsIWebP
       }
 
       RefPtr<Document> parentDoc;
       parentDoc = parentItem->GetDocument();
       if (!parentDoc) {
         return NS_OK;
       }
 
-      parentDoc->AddBlockedTrackingNode(frameElement);
+      parentDoc->AddBlockedNodeByClassifier(frameElement);
 
       return NS_OK;
     }
 
     if (sURIFixup) {
       //
       // Try and make an alternative URI from the old one
       //
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -20,16 +20,17 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/IdleDeadline.h"
 #include "mozilla/dom/JSWindowActorService.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ReportingHeader.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WindowBinding.h"  // For IdleRequestCallback/Options
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "IOActivityMonitor.h"
 #include "nsThreadUtils.h"
 #include "mozJSComponentLoader.h"
 #include "GeckoProfiler.h"
 #include "nsIException.h"
 
 namespace mozilla {
 namespace dom {
@@ -828,10 +829,16 @@ constexpr auto kSkipSelfHosted = JS::Sav
     const GlobalObject& aGlobal, const nsAString& aName,
     const WindowActorOptions& aOptions, ErrorResult& aRv) {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   RefPtr<JSWindowActorService> service = JSWindowActorService::GetSingleton();
   service->RegisterWindowActor(aName, aOptions, aRv);
 }
 
+/* static */ bool ChromeUtils::IsClassifierBlockingErrorCode(
+    GlobalObject& aGlobal, uint32_t aError) {
+  return net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+      static_cast<nsresult>(aError));
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -174,14 +174,17 @@ class ChromeUtils {
   static double LastExternalProtocolIframeAllowed(GlobalObject& aGlobal);
 
   static void ResetLastExternalProtocolIframeAllowed(GlobalObject& aGlobal);
 
   static void RegisterWindowActor(const GlobalObject& aGlobal,
                                   const nsAString& aName,
                                   const WindowActorOptions& aOptions,
                                   ErrorResult& aRv);
+
+  static bool IsClassifierBlockingErrorCode(GlobalObject& aGlobal,
+                                            uint32_t aError);
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_ChromeUtils__
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -5391,24 +5391,25 @@ already_AddRefed<Attr> Document::CreateA
 void Document::ResolveScheduledSVGPresAttrs() {
   for (auto iter = mLazySVGPresElements.Iter(); !iter.Done(); iter.Next()) {
     SVGElement* svg = iter.Get()->GetKey();
     svg->UpdateContentDeclarationBlock();
   }
   mLazySVGPresElements.Clear();
 }
 
-already_AddRefed<nsSimpleContentList> Document::BlockedTrackingNodes() const {
+already_AddRefed<nsSimpleContentList> Document::BlockedNodesByClassifier()
+    const {
   RefPtr<nsSimpleContentList> list = new nsSimpleContentList(nullptr);
 
-  nsTArray<nsWeakPtr> blockedTrackingNodes;
-  blockedTrackingNodes = mBlockedTrackingNodes;
-
-  for (unsigned long i = 0; i < blockedTrackingNodes.Length(); i++) {
-    nsWeakPtr weakNode = blockedTrackingNodes[i];
+  nsTArray<nsWeakPtr> blockedNodes;
+  blockedNodes = mBlockedNodesByClassifier;
+
+  for (unsigned long i = 0; i < blockedNodes.Length(); i++) {
+    nsWeakPtr weakNode = blockedNodes[i];
     nsCOMPtr<nsIContent> node = do_QueryReferent(weakNode);
     // Consider only nodes to which we have managed to get strong references.
     // Coping with nullptrs since it's expected for nodes to disappear when
     // nobody else is referring to them.
     if (node) {
       list->AppendElement(node);
     }
   }
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -1365,43 +1365,43 @@ class Document : public nsINode,
 
   // Resolve all SVG pres attrs scheduled in ScheduleSVGForPresAttrEvaluation
   void ResolveScheduledSVGPresAttrs();
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
-  // Returns the size of the mBlockedTrackingNodes array.
+  // Returns the size of the mBlockedNodesByClassifier array.
+  //
+  // This array contains nodes that have been blocked to prevent user tracking,
+  // fingerprinting, cryptomining, etc. They most likely have had their
+  // nsIChannel canceled by the URL classifier (Safebrowsing).
+  //
+  // A script can subsequently use GetBlockedNodesByClassifier()
+  // to get a list of references to these nodes.
+  //
+  // Note:
+  // This expresses how many tracking nodes have been blocked for this document
+  // since its beginning, not how many of them are still around in the DOM tree.
+  // Weak references to blocked nodes are added in the mBlockedNodesByClassifier
+  // array but they are not removed when those nodes are removed from the tree
+  // or even garbage collected.
+  long BlockedNodeByClassifierCount() const {
+    return mBlockedNodesByClassifier.Length();
+  }
+
+  //
+  // Returns strong references to mBlockedNodesByClassifier. (Document.h)
   //
   // This array contains nodes that have been blocked to prevent
   // user tracking. They most likely have had their nsIChannel
   // canceled by the URL classifier (Safebrowsing).
   //
-  // A script can subsequently use GetBlockedTrackingNodes()
-  // to get a list of references to these nodes.
-  //
-  // Note:
-  // This expresses how many tracking nodes have been blocked for this
-  // document since its beginning, not how many of them are still around
-  // in the DOM tree. Weak references to blocked nodes are added in the
-  // mBlockedTrackingNodesArray but they are not removed when those nodes
-  // are removed from the tree or even garbage collected.
-  long BlockedTrackingNodeCount() const {
-    return mBlockedTrackingNodes.Length();
-  }
-
-  //
-  // Returns strong references to mBlockedTrackingNodes. (Document.h)
-  //
-  // This array contains nodes that have been blocked to prevent
-  // user tracking. They most likely have had their nsIChannel
-  // canceled by the URL classifier (Safebrowsing).
-  //
-  already_AddRefed<nsSimpleContentList> BlockedTrackingNodes() const;
+  already_AddRefed<nsSimpleContentList> BlockedNodesByClassifier() const;
 
   // Helper method that returns true if the document has storage-access sandbox
   // flag.
   bool StorageAccessSandboxed() const;
 
  protected:
   friend class nsUnblockOnloadEvent;
 
@@ -3243,28 +3243,28 @@ class Document : public nsINode,
   /**
    * Asserts IsXULDocument, and can't return null.
    * Defined inline in XULDocument.h
    */
   inline mozilla::dom::XULDocument* AsXULDocument();
 
   /*
    * Given a node, get a weak reference to it and append that reference to
-   * mBlockedTrackingNodes. Can be used later on to look up a node in it.
+   * mBlockedNodesByClassifier. Can be used later on to look up a node in it.
    * (e.g., by the UI)
    */
-  void AddBlockedTrackingNode(nsINode* node) {
+  void AddBlockedNodeByClassifier(nsINode* node) {
     if (!node) {
       return;
     }
 
     nsWeakPtr weakNode = do_GetWeakReference(node);
 
     if (weakNode) {
-      mBlockedTrackingNodes.AppendElement(weakNode);
+      mBlockedNodesByClassifier.AppendElement(weakNode);
     }
   }
 
   gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
   void FlushUserFontSet();
   void MarkUserFontSetDirty();
   mozilla::dom::FontFaceSet* GetFonts() { return mFontFaceSet; }
 
@@ -4243,17 +4243,17 @@ class Document : public nsINode,
   // Count of live static clones of this document.
   uint32_t mStaticCloneCount;
 
   // Array of nodes that have been blocked to prevent user tracking.
   // They most likely have had their nsIChannel canceled by the URL
   // classifier. (Safebrowsing)
   //
   // Weak nsINode pointers are used to allow nodes to disappear.
-  nsTArray<nsWeakPtr> mBlockedTrackingNodes;
+  nsTArray<nsWeakPtr> mBlockedNodesByClassifier;
 
   // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
   // updated on every set of mScriptGlobalObject.
   nsPIDOMWindowInner* mWindow;
 
   nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
 
   struct FrameRequest;
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -46,16 +46,17 @@
 #include "mozAutoDocUpdate.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ImageTracker.h"
 #include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/Preferences.h"
 
 #ifdef LoadImage
 // Undefine LoadImage to prevent naming conflict with Windows.
 #  undef LoadImage
 #endif
 
 using namespace mozilla;
@@ -179,26 +180,28 @@ nsImageLoadingContent::Notify(imgIReques
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     uint32_t reqStatus;
     aRequest->GetImageStatus(&reqStatus);
     /* triage STATUS_ERROR */
     if (reqStatus & imgIRequest::STATUS_ERROR) {
       nsresult errorCode = NS_OK;
       aRequest->GetImageErrorCode(&errorCode);
 
-      /* Handle image not loading error because source was a tracking URL.
+      /* Handle image not loading error because source was a tracking URL (or
+       * fingerprinting, cryptomining, etc).
        * We make a note of this image node by including it in a dedicated
        * array of blocked tracking nodes under its parent document.
        */
-      if (errorCode == NS_ERROR_TRACKING_URI) {
+      if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+              errorCode)) {
         nsCOMPtr<nsIContent> thisNode =
             do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
         Document* doc = GetOurOwnerDoc();
-        doc->AddBlockedTrackingNode(thisNode);
+        doc->AddBlockedNodeByClassifier(thisNode);
       }
     }
     nsresult status =
         reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK;
     return OnLoadComplete(aRequest, status);
   }
 
   if (aType == imgINotificationObserver::DECODE_COMPLETE) {
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -85,16 +85,17 @@
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/widget/IMEData.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/LoadInfo.h"
 #include "nsChannelClassifier.h"
 #include "nsFocusManager.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #  ifdef CreateEvent
 #    undef CreateEvent
@@ -988,17 +989,17 @@ nsObjectLoadingContent::OnStartRequest(n
           NS_LITERAL_STRING(
               " since it was found on an internal Firefox blocklist.");
       console->LogStringMessage(message.get());
     }
     mContentBlockingEnabled = true;
     return NS_ERROR_FAILURE;
   }
 
-  if (status == NS_ERROR_TRACKING_URI) {
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status)) {
     mContentBlockingEnabled = true;
     return NS_ERROR_FAILURE;
   }
 
   if (!success) {
     LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this));
     // If the request fails, we still call LoadObject() to handle fallback
     // content and notifying of failure. (mChannelLoaded && !mChannel) indicates
@@ -1012,24 +1013,25 @@ nsObjectLoadingContent::OnStartRequest(n
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStopRequest(nsIRequest* aRequest,
                                       nsISupports* aContext,
                                       nsresult aStatusCode) {
   AUTO_PROFILER_LABEL("nsObjectLoadingContent::OnStopRequest", NETWORK);
 
-  // Handle object not loading error because source was a tracking URL.
+  // Handle object not loading error because source was a tracking URL (or
+  // fingerprinting, cryptomining, etc.).
   // We make a note of this object node by including it in a dedicated
   // array of blocked tracking nodes under its parent document.
-  if (aStatusCode == NS_ERROR_TRACKING_URI) {
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aStatusCode)) {
     nsCOMPtr<nsIContent> thisNode =
         do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
     if (thisNode && thisNode->IsInComposedDoc()) {
-      thisNode->GetComposedDoc()->AddBlockedTrackingNode(thisNode);
+      thisNode->GetComposedDoc()->AddBlockedNodeByClassifier(thisNode);
     }
   }
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
   mChannel = nullptr;
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -386,16 +386,20 @@ partial namespace ChromeUtils {
   /**
    * For testing purpose we need to reset this value.
    */
   [ChromeOnly]
   void resetLastExternalProtocolIframeAllowed();
 
   [ChromeOnly, Throws]
   void registerWindowActor(DOMString aName, WindowActorOptions aOptions);
+
+  [ChromeOnly]
+  // aError should a nsresult.
+  boolean isClassifierBlockingErrorCode(unsigned long aError);
 };
 
 /**
  * Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
  * Used by requestPerformanceMetrics
  */
 
 dictionary MediaMemoryInfoDictionary {
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -74,16 +74,17 @@
 #include "mozilla/dom/PlayPromise.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrack.h"
 #include "mozilla/dom/VideoPlaybackQuality.h"
 #include "mozilla/dom/VideoTrack.h"
 #include "mozilla/dom/VideoTrackList.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDisplayList.h"
 #include "nsDocShell.h"
 #include "nsError.h"
 #include "nsGenericHTMLElement.h"
@@ -634,23 +635,25 @@ HTMLMediaElement::MediaLoadListener::OnS
   }
 
   // Don't continue to load if the request failed or has been canceled.
   nsresult status;
   nsresult rv = aRequest->GetStatus(&status);
   NS_ENSURE_SUCCESS(rv, rv);
   if (NS_FAILED(status)) {
     if (element) {
-      // Handle media not loading error because source was a tracking URL.
+      // Handle media not loading error because source was a tracking URL (or
+      // fingerprinting, cryptomining, etc).
       // We make a note of this media node by including it in a dedicated
       // array of blocked tracking nodes under its parent document.
-      if (status == NS_ERROR_TRACKING_URI) {
+      if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+              status)) {
         Document* ownerDoc = element->OwnerDoc();
         if (ownerDoc) {
-          ownerDoc->AddBlockedTrackingNode(element);
+          ownerDoc->AddBlockedNodeByClassifier(element);
         }
       }
       element->NotifyLoadError(
           nsPrintfCString("%u: %s", uint32_t(status), "Request failed"));
     }
     return status;
   }
 
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -23,16 +23,17 @@
 #include "xpcpublic.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContent.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/SRILogHelper.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "nsGkAtoms.h"
 #include "nsNetUtil.h"
 #include "nsGlobalWindowInner.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
@@ -3244,18 +3245,19 @@ void ScriptLoader::ReportErrorToConsole(
   }
 
   bool isScript = !aRequest->IsModuleRequest();
   const char* message;
   if (aResult == NS_ERROR_MALFORMED_URI) {
     message = isScript ? "ScriptSourceMalformed" : "ModuleSourceMalformed";
   } else if (aResult == NS_ERROR_DOM_BAD_URI) {
     message = isScript ? "ScriptSourceNotAllowed" : "ModuleSourceNotAllowed";
-  } else if (aResult == NS_ERROR_TRACKING_URI) {
-    // Tracking protection errors already show their own console messages.
+  } else if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+                 aResult)) {
+    // Blocking classifier error codes already show their own console messages.
     return;
   } else {
     message = isScript ? "ScriptSourceLoadFailed" : "ModuleSourceLoadFailed";
   }
 
   NS_ConvertUTF8toUTF16 url(aRequest->mURI->GetSpecOrDefault());
   const char16_t* params[] = {url.get()};
 
@@ -3280,23 +3282,25 @@ void ScriptLoader::ReportPreloadErrorsTo
       ReportPreloadErrorsToConsole(childRequest);
     }
   }
 }
 
 void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
                                    nsresult aResult) {
   /*
-   * Handle script not loading error because source was a tracking URL.
+   * Handle script not loading error because source was an tracking URL (or
+   * fingerprinting, cryptoming, etc).
    * We make a note of this script node by including it in a dedicated
    * array of blocked tracking nodes under its parent document.
    */
-  if (aResult == NS_ERROR_TRACKING_URI) {
+  if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+          aResult)) {
     nsCOMPtr<nsIContent> cont = do_QueryInterface(aRequest->Element());
-    mDocument->AddBlockedTrackingNode(cont);
+    mDocument->AddBlockedNodeByClassifier(cont);
   }
 
   if (aRequest->IsModuleRequest() && !aRequest->mIsInline) {
     auto request = aRequest->AsModuleRequest();
     SetModuleFetchFinishedAndResumeWaitingRequests(request, aResult);
   }
 
   if (aRequest->mInDeferList) {
--- a/dom/webidl/HTMLDocument.webidl
+++ b/dom/webidl/HTMLDocument.webidl
@@ -56,24 +56,25 @@ interface HTMLDocument : Document {
   //             the implementation is no-op.
   // XXXbz do we actually need these anymore?
   void                      captureEvents();
   void                      releaseEvents();
 };
 
 partial interface HTMLDocument {
   /*
-   * Number of nodes that have been blocked by
-   * the Safebrowsing API to prevent tracking.
+   * Number of nodes that have been blocked by the Safebrowsing API to prevent
+   * tracking, cryptomining and so on. This method is for testing only.
    */
   [ChromeOnly, Pure]
-  readonly attribute long blockedTrackingNodeCount;
+  readonly attribute long blockedNodeByClassifierCount;
 
   /*
-   * List of nodes that have been blocked by
-   * the Safebrowsing API to prevent tracking.
+   * List of nodes that have been blocked by the Safebrowsing API to prevent
+   * tracking, fingerprinting, cryptomining and so on. This method is for
+   * testing only.
    */
   [ChromeOnly, Pure]
-  readonly attribute NodeList blockedTrackingNodes;
+  readonly attribute NodeList blockedNodesByClassifier;
 
   [ChromeOnly]
   void userInteractionForTesting();
 };
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -41,16 +41,17 @@
 #include "nsThreadUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIThreadInternal.h"
 #include "nsINetworkPredictor.h"
 #include "nsStringStream.h"
 #include "mozilla/dom/MediaList.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/URL.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/ConsoleReportCollector.h"
 #include "mozilla/ServoUtils.h"
 #include "mozilla/css/StreamLoader.h"
 
@@ -590,30 +591,32 @@ nsresult SheetLoadData::VerifySheetReady
     LOG_WARN(("  No document and not non-document sheet; dropping load"));
     mLoader->SheetComplete(this, NS_BINDING_ABORTED);
     return NS_OK;
   }
 
   if (NS_FAILED(aStatus)) {
     LOG_WARN(
         ("  Load failed: status 0x%" PRIx32, static_cast<uint32_t>(aStatus)));
-    // Handle sheet not loading error because source was a tracking URL.
+    // Handle sheet not loading error because source was a tracking URL (or
+    // fingerprinting, cryptomining, etc).
     // We make a note of this sheet node by including it in a dedicated
     // array of blocked tracking nodes under its parent document.
     //
     // Multiple sheet load instances might be tied to this request,
     // we annotate each one linked to a valid owning element (node).
-    if (aStatus == NS_ERROR_TRACKING_URI) {
+    if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+            aStatus)) {
       Document* doc = mLoader->GetDocument();
       if (doc) {
         for (SheetLoadData* data = this; data; data = data->mNext) {
           // mOwningElement may be null but AddBlockTrackingNode can cope
           nsCOMPtr<nsIContent> content =
               do_QueryInterface(data->mOwningElement);
-          doc->AddBlockedTrackingNode(content);
+          doc->AddBlockedNodeByClassifier(content);
         }
       }
     }
     mLoader->SheetComplete(this, aStatus);
     return NS_OK;
   }
 
   if (!aChannel) {
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/extensions/StreamFilterParent.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/HttpChannelChild.h"
 #include "mozilla/net/UrlClassifierCommon.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 
 #include "AltDataOutputStreamChild.h"
 #include "CookieServiceChild.h"
 #include "HttpBackgroundChannelChild.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsPrimitives.h"
 #include "nsContentPolicyUtils.h"
 #include "nsDOMNavigationTiming.h"
@@ -1185,17 +1186,18 @@ void HttpChannelChild::DoOnStopRequest(n
   AUTO_PROFILER_LABEL("HttpChannelChild::DoOnStopRequest", NETWORK);
   LOG(("HttpChannelChild::DoOnStopRequest [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIsPending);
 
   // NB: We use aChannelStatus here instead of mStatus because if there was an
   // nsCORSListenerProxy on this request, it will override the tracking
   // protection's return value.
-  if (aChannelStatus == NS_ERROR_TRACKING_URI ||
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+          aChannelStatus) ||
       aChannelStatus == NS_ERROR_MALWARE_URI ||
       aChannelStatus == NS_ERROR_UNWANTED_URI ||
       aChannelStatus == NS_ERROR_BLOCKED_URI ||
       aChannelStatus == NS_ERROR_HARMFUL_URI ||
       aChannelStatus == NS_ERROR_PHISHING_URI) {
     nsCString list, provider, fullhash;
 
     nsresult rv = GetMatchedList(list);
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -117,16 +117,17 @@
 #include "nsIMIMEInputStream.h"
 #include "nsIMultiplexInputStream.h"
 #include "../../cache2/CacheFileUtils.h"
 #include "nsINetworkLinkService.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/net/AsyncUrlChannelClassifier.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 
 #ifdef MOZ_TASK_TRACER
 #  include "GeckoTaskTracer.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ProfilerMarkerPayload.h"
 #endif
@@ -5985,19 +5986,24 @@ NS_INTERFACE_MAP_END_INHERITING(HttpBase
 // nsHttpChannel::nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::Cancel(nsresult status) {
   MOZ_ASSERT(NS_IsMainThread());
   // We should never have a pump open while a CORS preflight is in progress.
   MOZ_ASSERT_IF(mPreflightChannel, !mCachePump);
-  MOZ_ASSERT(status != NS_ERROR_TRACKING_URI,
-             "NS_ERROR_TRACKING_URI needs to be handled by "
-             "CancelForTrackingProtection()");
+#ifdef DEBUG
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status)) {
+    MOZ_CRASH_UNSAFE_PRINTF(
+        "Blocking classifier error %d need to be handled by "
+        "CancelForTrackingProtection()",
+        status);
+  }
+#endif
 
   LOG(("nsHttpChannel::Cancel [this=%p status=%" PRIx32 "]\n", this,
        static_cast<uint32_t>(status)));
   if (mCanceled) {
     LOG(("  ignoring; already canceled\n"));
     return NS_OK;
   }
 
@@ -6083,17 +6089,17 @@ void nsHttpChannel::ContinueCancelledByT
   }
 
   Unused << CancelInternal(NS_ERROR_TRACKING_URI);
 }
 
 nsresult nsHttpChannel::CancelInternal(nsresult status) {
   bool trackingProtectionCancellationPending =
       !!mTrackingProtectionCancellationPending;
-  if (status == NS_ERROR_TRACKING_URI) {
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status)) {
     mTrackingProtectionCancellationPending = 0;
   }
 
   mCanceled = true;
   mStatus = status;
   if (mProxyRequest) mProxyRequest->Cancel(status);
   CancelNetworkRequest(status);
   mCacheInputStream.CloseAndRelease();
--- a/netwerk/url-classifier/UrlClassifierCommon.cpp
+++ b/netwerk/url-classifier/UrlClassifierCommon.cpp
@@ -3,16 +3,17 @@
 /* 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 "mozilla/net/UrlClassifierCommon.h"
 
 #include "mozilla/AntiTrackingCommon.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsContentUtils.h"
 #include "nsIChannel.h"
 #include "nsIClassifiedChannel.h"
 #include "mozilla/dom/Document.h"
 #include "nsIDocShell.h"
 #include "nsIHttpChannel.h"
@@ -219,35 +220,39 @@ LazyLogModule UrlClassifierCommon::sLog(
   nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
   if (!docShell) {
     return NS_OK;
   }
   RefPtr<dom::Document> doc = docShell->GetDocument();
   NS_ENSURE_TRUE(doc, NS_OK);
 
   unsigned state;
-  if (aErrorCode == NS_ERROR_TRACKING_URI) {
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)) {
     state = nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
   } else {
     state = nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
   }
 
   UrlClassifierCommon::NotifyChannelBlocked(channel, uriBeingLoaded, state);
 
   // Log a warning to the web console.
   nsCOMPtr<nsIURI> uri;
   channel->GetURI(getter_AddRefs(uri));
   NS_ConvertUTF8toUTF16 spec(uri->GetSpecOrDefault());
   const char16_t* params[] = {spec.get()};
-  const char* message = (aErrorCode == NS_ERROR_TRACKING_URI)
-                            ? "TrackerUriBlocked"
-                            : "UnsafeUriBlocked";
-  nsCString category = (aErrorCode == NS_ERROR_TRACKING_URI)
-                           ? NS_LITERAL_CSTRING("Tracking Protection")
-                           : NS_LITERAL_CSTRING("Safe Browsing");
+  const char* message;
+  nsCString category;
+
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)) {
+    message = UrlClassifierFeatureFactory::
+        ClassifierBlockingErrorCodeToConsoleMessage(aErrorCode, category);
+  } else {
+    message = "UnsafeUriBlocked";
+    category = NS_LITERAL_CSTRING("Safe Browsing");
+  }
 
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, category, doc,
                                   nsContentUtils::eNECKO_PROPERTIES, message,
                                   params, ArrayLength(params));
 
   return NS_OK;
 }
 
--- a/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp
+++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp
@@ -200,10 +200,51 @@ UrlClassifierFeatureFactory::CreateFeatu
     const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
     const nsTArray<nsCString>& aWhitelistTables) {
   nsCOMPtr<nsIUrlClassifierFeature> feature =
       new UrlClassifierFeatureCustomTables(aName, aBlacklistTables,
                                            aWhitelistTables);
   return feature.forget();
 }
 
+namespace {
+
+struct BlockingErrorCode {
+  nsresult mErrorCode;
+  const char* mConsoleMessage;
+  nsCString mConsoleCategory;
+};
+
+static const BlockingErrorCode sBlockingErrorCodes[] = {
+    {NS_ERROR_TRACKING_URI, "TrackerUriBlocked",
+     NS_LITERAL_CSTRING("Tracking Protection")},
+};
+
+}  // namespace
+
+/* static */ bool UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
+    nsresult aError) {
+  // In theory we can iterate through the features, but at the moment, we can
+  // just have a simple check here.
+  for (const auto& blockingErrorCode : sBlockingErrorCodes) {
+    if (aError == blockingErrorCode.mErrorCode) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/* static */ const char*
+UrlClassifierFeatureFactory::ClassifierBlockingErrorCodeToConsoleMessage(
+    nsresult aError, nsACString& aCategory) {
+  for (const auto& blockingErrorCode : sBlockingErrorCodes) {
+    if (aError == blockingErrorCode.mErrorCode) {
+      aCategory = blockingErrorCode.mConsoleCategory;
+      return blockingErrorCode.mConsoleMessage;
+    }
+  }
+
+  return nullptr;
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/url-classifier/UrlClassifierFeatureFactory.h
+++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.h
@@ -32,14 +32,22 @@ class UrlClassifierFeatureFactory final 
   static already_AddRefed<nsIUrlClassifierFeature> GetFeatureByName(
       const nsACString& aFeatureName);
 
   static void GetFeatureNames(nsTArray<nsCString>& aArray);
 
   static already_AddRefed<nsIUrlClassifierFeature> CreateFeatureWithTables(
       const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
       const nsTArray<nsCString>& aWhitelistTables);
+
+  // Returns true if this error is known as one of the blocking error codes.
+  static bool IsClassifierBlockingErrorCode(nsresult aError);
+
+  // This can be called only if IsClassifierBlockingErrorCode(aError) returns
+  // true.
+  static const char* ClassifierBlockingErrorCodeToConsoleMessage(
+      nsresult aError, nsACString& aCategory);
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_UrlClassifierFeatureFactory_h
--- a/netwerk/url-classifier/nsChannelClassifier.cpp
+++ b/netwerk/url-classifier/nsChannelClassifier.cpp
@@ -24,16 +24,17 @@
 #include "nsIUrlClassifierFeature.h"
 #include "nsPrintfCString.h"
 
 #include "mozilla/Components.h"
 #include "mozilla/ErrorNames.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/net/UrlClassifierCommon.h"
+#include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Services.h"
 
 namespace mozilla {
 namespace net {
 
 //
 // MOZ_LOG=nsChannelClassifier:5
@@ -279,17 +280,18 @@ bool nsChannelClassifier::IsHostnameWhit
 
 // Note in the cache entry that this URL was classified, so that future
 // cached loads don't need to be checked.
 void nsChannelClassifier::MarkEntryClassified(nsresult status) {
   // Should only be called in the parent process.
   MOZ_ASSERT(XRE_IsParentProcess());
 
   // Don't cache tracking classifications because we support allowlisting.
-  if (status == NS_ERROR_TRACKING_URI || mIsAllowListed) {
+  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status) ||
+      mIsAllowListed) {
     return;
   }
 
   if (LOG_ENABLED()) {
     nsAutoCString errorName;
     GetErrorName(status, errorName);
     nsCOMPtr<nsIURI> uri;
     mChannel->GetURI(getter_AddRefs(uri));
@@ -384,17 +386,18 @@ nsresult nsChannelClassifier::SendThreat
 
 NS_IMETHODIMP
 nsChannelClassifier::OnClassifyComplete(nsresult aErrorCode,
                                         const nsACString& aList,
                                         const nsACString& aProvider,
                                         const nsACString& aFullHash) {
   // Should only be called in the parent process.
   MOZ_ASSERT(XRE_IsParentProcess());
-  MOZ_ASSERT(aErrorCode != NS_ERROR_TRACKING_URI);
+  MOZ_ASSERT(
+      !UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode));
 
   if (mSuspendedChannel) {
     nsAutoCString errorName;
     if (LOG_ENABLED() && NS_FAILED(aErrorCode)) {
       GetErrorName(aErrorCode, errorName);
       LOG(("nsChannelClassifier[%p]:OnClassifyComplete %s (suspended channel)",
            this, errorName.get()));
     }
--- a/toolkit/components/aboutperformance/content/aboutPerformance.js
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.js
@@ -252,17 +252,17 @@ var State = {
         return false;
 
       let principal =
         Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("http://" + host);
       let classifier =
         Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIURIClassifier);
       classifier.classify(principal, null, true,
                           (aErrorCode, aList, aProvider, aFullHash) => {
-        this._trackingState.set(host, aErrorCode == Cr.NS_ERROR_TRACKING_URI);
+        this._trackingState.set(host, ChromeUtils.IsClassifierBlockingErrorCode(aErrorCode));
       });
     }
     return this._trackingState.get(host);
   },
 
   getCounters() {
     tabFinder.update();
     // We rebuild the maps during each iteration to make sure that
--- a/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
@@ -75,17 +75,17 @@ add_task(async function() {
 
   await promise;
 
   info("Verify the number of tracking nodes found");
   await ContentTask.spawn(browser,
                           { expected: 3,
                           },
                           async function(obj) {
-    is(content.document.blockedTrackingNodeCount, obj.expected, "Expected tracking nodes found");
+    is(content.document.blockedNodeByClassifierCount, obj.expected, "Expected tracking nodes found");
   });
 
   info("Removing the tab");
   BrowserTestUtils.removeTab(tab);
 
   UrlClassifierTestUtils.cleanupTestTrackers();
   await extension.unload();
 });
--- a/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
@@ -70,16 +70,16 @@ add_task(async function() {
 
   await promise;
 
   info("Verify the number of tracking nodes found");
   await ContentTask.spawn(browser,
                           { expected: gExpectedResourcesSeen,
                           },
                           async function(obj) {
-    is(content.document.blockedTrackingNodeCount, obj.expected, "Expected tracking nodes found");
+    is(content.document.blockedNodeByClassifierCount, obj.expected, "Expected tracking nodes found");
   });
 
   info("Removing the tab");
   BrowserTestUtils.removeTab(tab);
 
   UrlClassifierTestUtils.cleanupTestTrackers();
 });
--- a/toolkit/components/url-classifier/tests/mochitest/allowlistAnnotatedFrame.html
+++ b/toolkit/components/url-classifier/tests/mochitest/allowlistAnnotatedFrame.html
@@ -22,17 +22,17 @@ function checkLoads() {
   window.parent.is(scriptItem2, "spoiled", "Should not block tracking js 2");
   window.parent.is(imageItem1, "spoiled", "Should not block tracking img 1");
   window.parent.is(imageItem2, "spoiled", "Should not block tracking img 2");
   window.parent.is(frameItem1, "spoiled", "Should not block tracking iframe 1");
   window.parent.is(frameItem2, "spoiled", "Should not block tracking iframe 2");
   window.parent.is(mediaItem1, "loaded", "Should not block tracking video");
   window.parent.is(xhrItem, "loaded", "Should not block tracking XHR");
   window.parent.is(fetchItem, "loaded", "Should not block fetches from tracking domains");
-  window.parent.is(window.document.blockedTrackingNodeCount, 0,
+  window.parent.is(window.document.blockedNodeByClassifierCount, 0,
     "No elements should be blocked");
 
   // End (parent) test.
   window.parent.clearPermissions();
   window.parent.SimpleTest.finish();
 }
 
 var onloadCalled = false;
--- a/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedFrame.html
+++ b/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedFrame.html
@@ -49,50 +49,50 @@ function checkLoads() {
   window.parent.is(
     fetchItem, "error", "Should not fetch from tracking URLs");
 
   var elt = document.getElementById("styleCheck");
   var style = document.defaultView.getComputedStyle(elt);
   window.parent.isnot(
     style.visibility, "hidden", "Should not load tracking css");
 
-  window.parent.is(window.document.blockedTrackingNodeCount, badids.length,
+  window.parent.is(window.document.blockedNodeByClassifierCount, badids.length,
     "Should identify all tracking elements");
 
-  var blockedTrackingNodes = window.document.blockedTrackingNodes;
+  var blockedNodes = window.document.blockedNodesByClassifier;
 
-  // Make sure that every node in blockedTrackingNodes exists in the tree
+  // Make sure that every node in blockedNodes exists in the tree
   // (that may not always be the case but do not expect any nodes to disappear
   // from the tree here)
   var allNodeMatch = true;
-  for (let i = 0; i < blockedTrackingNodes.length; i++) {
+  for (let i = 0; i < blockedNodes.length; i++) {
     let nodeMatch = false;
     for (let j = 0; j < badids.length && !nodeMatch; j++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == document.getElementById(badids[j]));
+        (blockedNodes[i] == document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   window.parent.ok(allNodeMatch,
     "All annotated nodes are expected in the tree");
 
   // Make sure that every node with a badid (see badids) is found in the
-  // blockedTrackingNodes. This tells us if we are neglecting to annotate
+  // blockedNodes. This tells us if we are neglecting to annotate
   // some nodes
   allNodeMatch = true;
   for (let j = 0; j < badids.length; j++) {
     let nodeMatch = false;
-    for (let i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
+    for (let i = 0; i < blockedNodes.length && !nodeMatch; i++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == document.getElementById(badids[j]));
+        (blockedNodes[i] == document.getElementById(badids[j]));
     }
 
     if (!nodeMatch) {
-      console.log(badids[j] + " was not found in blockedTrackingNodes");
+      console.log(badids[j] + " was not found in blockedNodes");
     }
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   window.parent.ok(allNodeMatch,
     "All tracking nodes are expected to be annotated as such");
 
   // Unset prefs, etc.
   window.parent.cleanup();
--- a/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
@@ -67,44 +67,44 @@ function checkLoads(aWindow, aBlocked) {
   is(win.document.getElementById("badimage").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking images");
   is(win.document.getElementById("goodscript").dataset.touched, "yes", "Should load whitelisted tracking javascript");
   is(win.document.getElementById("goodimage").dataset.touched, "yes", "Should load non-blacklisted image");
 
   var elt = win.document.getElementById("styleCheck");
   var style = win.document.defaultView.getComputedStyle(elt);
   isnot(style.visibility, aBlocked ? "hidden" : "", "Should not load tracking css");
 
-  is(win.document.blockedTrackingNodeCount, aBlocked ? badids.length : 0, "Should identify all tracking elements");
+  is(win.document.blockedNodeByClassifierCount, aBlocked ? badids.length : 0, "Should identify all tracking elements");
 
-  var blockedTrackingNodes = win.document.blockedTrackingNodes;
+  var blockedNodes = win.document.blockedNodesByClassifier;
 
-  // Make sure that every node in blockedTrackingNodes exists in the tree
+  // Make sure that every node in blockedNodes exists in the tree
   // (that may not always be the case but do not expect any nodes to disappear
   // from the tree here)
   var allNodeMatch = true;
-  for (let i = 0; i < blockedTrackingNodes.length; i++) {
+  for (let i = 0; i < blockedNodes.length; i++) {
     let nodeMatch = false;
     for (let j = 0; j < badids.length && !nodeMatch; j++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
+        (blockedNodes[i] == win.document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   is(allNodeMatch, true, "All annotated nodes are expected in the tree");
 
   // Make sure that every node with a badid (see badids) is found in the
-  // blockedTrackingNodes. This tells us if we are neglecting to annotate
+  // blockedNodes. This tells us if we are neglecting to annotate
   // some nodes
   allNodeMatch = true;
   for (let j = 0; j < badids.length; j++) {
     let nodeMatch = false;
-    for (let i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
+    for (let i = 0; i < blockedNodes.length && !nodeMatch; i++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
+        (blockedNodes[i] == win.document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   is(allNodeMatch, aBlocked, "All tracking nodes are expected to be annotated as such");
 }
 
 SpecialPowers.pushPrefEnv(
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
@@ -56,55 +56,55 @@ function testOnWindow(contentPage) {
 var alwaysbadids = [
   "badscript",
 ];
 
 function checkLoads(aWindow, aWhitelisted, tpEnabled) {
   var win = aWindow.content;
   if (!tpEnabled) {
     is(win.document.getElementById("badscript").dataset.touched, "yes", "Should load tracking javascript");
-    is(win.document.blockedTrackingNodeCount, 0, "Should not identify any tracking elements");
+    is(win.document.blockedNodeByClassifierCount, 0, "Should not identify any tracking elements");
     return;
   }
 
   is(win.document.getElementById("badscript").dataset.touched, "no", "Should not load tracking javascript");
   is(win.document.getElementById("goodscript").dataset.touched, aWhitelisted ? "yes" : "no", "Should load whitelisted tracking javascript");
 
   var badids = alwaysbadids.slice();
   if (!aWhitelisted) {
     badids.push("goodscript");
   }
-  is(win.document.blockedTrackingNodeCount, badids.length, "Should identify all tracking elements");
+  is(win.document.blockedNodeByClassifierCount, badids.length, "Should identify all tracking elements");
 
-  var blockedTrackingNodes = win.document.blockedTrackingNodes;
+  var blockedNodes = win.document.blockedNodesByClassifier;
 
-  // Make sure that every node in blockedTrackingNodes exists in the tree
+  // Make sure that every node in blockedNodes exists in the tree
   // (that may not always be the case but do not expect any nodes to disappear
   // from the tree here)
   var allNodeMatch = true;
-  for (let i = 0; i < blockedTrackingNodes.length; i++) {
+  for (let i = 0; i < blockedNodes.length; i++) {
     let nodeMatch = false;
     for (let j = 0; j < badids.length && !nodeMatch; j++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
+        (blockedNodes[i] == win.document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   is(allNodeMatch, true, "All annotated nodes are expected in the tree");
 
   // Make sure that every node with a badid (see badids) is found in the
-  // blockedTrackingNodes. This tells us if we are neglecting to annotate
+  // blockedNodes. This tells us if we are neglecting to annotate
   // some nodes
   allNodeMatch = true;
   for (let j = 0; j < badids.length; j++) {
     let nodeMatch = false;
-    for (let i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
+    for (let i = 0; i < blockedNodes.length && !nodeMatch; i++) {
       nodeMatch = nodeMatch ||
-        (blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
+        (blockedNodes[i] == win.document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
   is(allNodeMatch, true, "All tracking nodes are expected to be annotated as such");
 }
 
 SpecialPowers.pushPrefEnv(