Bug 1482950 - Use the correct 3rdparty check in tracking annotations. r=dimi,Ehsan,mayhemer!,ehsan!
authorFrancois Marier <francois@mozilla.com>
Mon, 20 Aug 2018 23:53:45 +0000
changeset 487570 251360ecbedff5fbaa014cd859a4fbd9914d4233
parent 487569 c2422757c912799714b0dd9238748585aa3d575a
child 487571 3f0325c0b307be193b5549f6bd98881a2d70a371
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdimi, Ehsan, mayhemer
bugs1482950, 1476324, 1476715, 1108017
milestone63.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 1482950 - Use the correct 3rdparty check in tracking annotations. r=dimi,Ehsan,mayhemer!,ehsan! The mIsTrackingResource flag on nsIHttpChannel was split into two separate flags depending on whether or not the resource is third-party. The correct flag will be set by the channel classifier. Similarly, a new function was introduced, GetIsThirdPartyTrackingResource(), for those consumers (like TP) who only care about third-party trackers. The existing function, GetIsTracking(), will continue to look at both first-party and third-party trackers (the behavior since first party tracking was added to annotations in bug 1476324). The OverrideTrackingResource() function now allows nsHTMLDocument to override both mIsFirstPartyTrackingResource and mIsThirdPartyTrackingResource, but since this function is a little dangerous and only has a single user, I added an assert to make future callers think twice about using it to opt out of tracking annotations. Currently, only the default storage restrictions need to look at first-party trackers so every other consumer has been moved to mIsThirdPartyTrackingResource or GetIsThirdPartyTrackingResource(). This effectively reverts the third-party checks added in bug 1476715 and replaces them with the more complicated check that was added in bug 1108017. It follows the approach that Ehsan initially suggested in bug 1476715. It also reverts the changes in the expected values of the tracking annotation test since these were, in hindsight, a warning about this regression. Depends on D3722 Differential Revision: https://phabricator.services.mozilla.com/D3723
dom/html/nsHTMLDocument.cpp
dom/script/ScriptLoader.cpp
netwerk/base/SimpleChannelParent.cpp
netwerk/base/nsChannelClassifier.cpp
netwerk/base/nsIParentChannel.idl
netwerk/protocol/data/DataChannelParent.cpp
netwerk/protocol/file/FileChannelParent.cpp
netwerk/protocol/ftp/FTPChannelParent.cpp
netwerk/protocol/http/HttpBackgroundChannelChild.cpp
netwerk/protocol/http/HttpBackgroundChannelChild.h
netwerk/protocol/http/HttpBackgroundChannelParent.cpp
netwerk/protocol/http/HttpBackgroundChannelParent.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/NullHttpChannel.cpp
netwerk/protocol/http/PHttpBackgroundChannel.ipdl
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsIHttpChannel.idl
netwerk/protocol/viewsource/nsViewSourceChannel.cpp
netwerk/test/unit/test_trackingProtection_annotateChannels.js
uriloader/exthandler/nsExternalProtocolHandler.cpp
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1076,17 +1076,17 @@ nsHTMLDocument::CreateDummyChannelForCoo
     if (isTracking) {
       // If our document channel is from a tracking resource, we must
       // override our channel's tracking status.
       nsCOMPtr<nsIHttpChannel> httpChannel =
         do_QueryInterface(channel);
       MOZ_ASSERT(httpChannel, "How come we're coming from an HTTP doc but "
                               "we don't have an HTTP channel here?");
       if (httpChannel) {
-        httpChannel->OverrideTrackingResource(isTracking);
+        httpChannel->OverrideTrackingFlagsForDocumentCookieAccessor(docHTTPChannel);
       }
     }
   }
 
   return channel.forget();
 }
 
 void
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -3157,17 +3157,17 @@ ScriptLoader::PrepareLoadedRequest(Scrip
     }
 
     nsAutoCString sourceMapURL;
     if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
       aRequest->mHasSourceMapURL = true;
       aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL);
     }
 
-    if (httpChannel->GetIsTrackingResource()) {
+    if (httpChannel->GetIsThirdPartyTrackingResource()) {
       aRequest->SetIsTracking();
     }
   }
 
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
   // If this load was subject to a CORS check, don't flag it with a separate
   // origin principal, so that it will treat our document's principal as the
   // origin principal.  Module loads always use CORS.
--- a/netwerk/base/SimpleChannelParent.cpp
+++ b/netwerk/base/SimpleChannelParent.cpp
@@ -34,17 +34,17 @@ SimpleChannelParent::SetParentListener(H
 NS_IMETHODIMP
 SimpleChannelParent::NotifyTrackingProtectionDisabled()
 {
   // Nothing to do.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SimpleChannelParent::NotifyTrackingResource()
+SimpleChannelParent::NotifyTrackingResource(bool aIsThirdParty)
 {
   // Nothing to do.
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SimpleChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
                                               const nsACString& aProvider,
--- a/netwerk/base/nsChannelClassifier.cpp
+++ b/netwerk/base/nsChannelClassifier.cpp
@@ -208,32 +208,79 @@ CachedPrefs::~CachedPrefs()
   Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_SKIP_HOSTNAMES, this);
   Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_ANNOTATION_TABLE, this);
   Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_ANNOTATION_WHITELIST, this);
   Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_TRACKING_WHITELIST, this);
   Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_TRACKING_TABLE, this);
 }
 } // anonymous namespace
 
+static nsresult
+IsThirdParty(nsIChannel* aChannel, bool* aResult)
+{
+  NS_ENSURE_ARG(aResult);
+  *aResult = false;
+
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
+  if (NS_WARN_IF(!thirdPartyUtil)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
+  if (NS_FAILED(rv) || !chan) {
+    LOG(("nsChannelClassifier: Not an HTTP channel"));
+    return NS_OK;
+  }
+  nsCOMPtr<nsIURI> chanURI;
+  rv = aChannel->GetURI(getter_AddRefs(chanURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> topWinURI;
+  rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (!topWinURI) {
+    LOG(("nsChannelClassifier: No window URI\n"));
+  }
+
+  // Third party checks don't work for chrome:// URIs in mochitests, so just
+  // default to isThirdParty = true. We check isThirdPartyWindow to expand
+  // the list of domains that are considered first party (e.g., if
+  // facebook.com includes an iframe from fatratgames.com, all subsources
+  // included in that iframe are considered third-party with
+  // isThirdPartyChannel, even if they are not third-party w.r.t.
+  // facebook.com), and isThirdPartyChannel to prevent top-level navigations
+  // from being detected as third-party.
+  bool isThirdPartyChannel = true;
+  bool isThirdPartyWindow = true;
+  thirdPartyUtil->IsThirdPartyURI(chanURI, topWinURI, &isThirdPartyWindow);
+  thirdPartyUtil->IsThirdPartyChannel(aChannel, nullptr, &isThirdPartyChannel);
+
+  *aResult = isThirdPartyWindow && isThirdPartyChannel;
+  return NS_OK;
+}
+
 static void
-SetIsTrackingResourceHelper(nsIChannel* aChannel)
+SetIsTrackingResourceHelper(nsIChannel* aChannel, bool aIsThirdParty)
 {
   MOZ_ASSERT(aChannel);
 
   nsCOMPtr<nsIParentChannel> parentChannel;
   NS_QueryNotificationCallbacks(aChannel, parentChannel);
   if (parentChannel) {
     // This channel is a parent-process proxy for a child process
     // request. We should notify the child process as well.
-    parentChannel->NotifyTrackingResource();
+    parentChannel->NotifyTrackingResource(aIsThirdParty);
   }
 
   RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(aChannel);
   if (httpChannel) {
-    httpChannel->SetIsTrackingResource();
+    httpChannel->SetIsTrackingResource(aIsThirdParty);
   }
 }
 
 static void
 LowerPriorityHelper(nsIChannel* aChannel)
 {
   MOZ_ASSERT(aChannel);
 
@@ -361,58 +408,36 @@ nsChannelClassifier::ShouldEnableTrackin
                                                          bool *result)
 {
     // Should only be called in the parent process.
     MOZ_ASSERT(XRE_IsParentProcess());
 
     NS_ENSURE_ARG(result);
     *result = false;
 
-    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-      services::GetThirdPartyUtil();
-    if (NS_WARN_IF(!thirdPartyUtil)) {
-      return NS_ERROR_FAILURE;
-    }
-
     nsresult rv;
     nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
     if (NS_FAILED(rv) || !chan) {
       LOG(("nsChannelClassifier[%p]: Not an HTTP channel", this));
       return NS_OK;
     }
 
-    nsCOMPtr<nsIURI> topWinURI;
-    rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-
-    if (!topWinURI) {
-      LOG(("nsChannelClassifier[%p]: No window URI\n", this));
-    }
-
     nsCOMPtr<nsIURI> chanURI;
     rv = aChannel->GetURI(getter_AddRefs(chanURI));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Only perform third-party checks for tracking protection
     if (!aAnnotationsOnly) {
-      // Third party checks don't work for chrome:// URIs in mochitests, so just
-      // default to isThirdParty = true. We check isThirdPartyWindow to expand
-      // the list of domains that are considered first party (e.g., if
-      // facebook.com includes an iframe from fatratgames.com, all subsources
-      // included in that iframe are considered third-party with
-      // isThirdPartyChannel, even if they are not third-party w.r.t.
-      // facebook.com), and isThirdPartyChannel to prevent top-level navigations
-      // from being detected as third-party.
-      bool isThirdPartyChannel = true;
-      bool isThirdPartyWindow = true;
-      thirdPartyUtil->IsThirdPartyURI(chanURI, topWinURI, &isThirdPartyWindow);
-      thirdPartyUtil->IsThirdPartyChannel(aChannel, nullptr, &isThirdPartyChannel);
-      if (!isThirdPartyWindow || !isThirdPartyChannel) {
+      bool isThirdParty = false;
+      rv = IsThirdParty(aChannel, &isThirdParty);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        LOG(("nsChannelClassifier[%p]: IsThirdParty() failed", this));
+        return NS_OK;
+      }
+      if (!isThirdParty) {
         *result = false;
         if (LOG_ENABLED()) {
           nsCString spec = chanURI->GetSpecOrDefault();
           spec.Truncate(std::min(spec.Length(), sMaxSpecLength));
           LOG(("nsChannelClassifier[%p]: Skipping tracking protection checks "
                "for first party or top-level load channel[%p] with uri %s",
                this, aChannel, spec.get()));
         }
@@ -422,16 +447,22 @@ nsChannelClassifier::ShouldEnableTrackin
 
     if (AddonMayLoad(aChannel, chanURI)) {
         return NS_OK;
     }
 
     nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    nsCOMPtr<nsIURI> topWinURI;
+    rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
     if (!topWinURI && CachedPrefs::GetInstance()->IsAllowListExample()) {
       LOG(("nsChannelClassifier[%p]: Allowlisting test domain\n", this));
       rv = ios->NewURI(NS_LITERAL_CSTRING("http://allowlisted.example.com"),
                        nullptr, nullptr, getter_AddRefs(topWinURI));
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // Take the host/port portion so we can allowlist by site. Also ignore the
@@ -1189,45 +1220,49 @@ TrackingURICallback::OnWhitelistResult(n
   mChannelCallback();
   return NS_OK;
 }
 
 void
 TrackingURICallback::OnTrackerFound(nsresult aErrorCode)
 {
   nsCOMPtr<nsIChannel> channel = mChannelClassifier->GetChannel();
+  MOZ_ASSERT(channel);
   if (aErrorCode == NS_ERROR_TRACKING_URI &&
       mChannelClassifier->ShouldEnableTrackingProtection()) {
     mChannelClassifier->SetBlockedContent(channel, aErrorCode,
                                           mList, mProvider, mFullHash);
     LOG(("TrackingURICallback[%p]::OnTrackerFound, cancelling channel[%p]",
          mChannelClassifier.get(), channel.get()));
     channel->Cancel(aErrorCode);
   } else {
     MOZ_ASSERT(aErrorCode == NS_ERROR_TRACKING_ANNOTATION_URI);
     MOZ_ASSERT(mChannelClassifier->ShouldEnableTrackingAnnotation());
 
+    bool isThirdPartyWithTopLevelWinURI = false;
+    nsresult rv = IsThirdParty(channel, &isThirdPartyWithTopLevelWinURI);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      LOG(("TrackingURICallback[%p]::OnTrackerFound IsThirdParty() failed",
+           mChannelClassifier.get()));
+      return; // we'll assume the channel is NOT third-party
+    }
+
     LOG(("TrackingURICallback[%p]::OnTrackerFound, annotating channel[%p]",
          mChannelClassifier.get(), channel.get()));
 
-    // Even with TP disabled, we still want to show the user that there
-    // are unblocked trackers on the site, so notify the UI that we loaded
-    // tracking content. UI code can treat this notification differently
-    // depending on whether TP is enabled or disabled.
-    mChannelClassifier->NotifyTrackingProtectionDisabled(channel);
+    SetIsTrackingResourceHelper(channel, isThirdPartyWithTopLevelWinURI);
 
-    SetIsTrackingResourceHelper(channel);
-    if (CachedPrefs::GetInstance()->IsLowerNetworkPriority()) {
-      nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-        services::GetThirdPartyUtil();
-      bool result = false;
-      if (thirdPartyUtil &&
-          NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyChannel(channel, nullptr,
-                                                           &result)) &&
-          result) {
+    if (isThirdPartyWithTopLevelWinURI) {
+      // Even with TP disabled, we still want to show the user that there
+      // are unblocked trackers on the site, so notify the UI that we loaded
+      // tracking content. UI code can treat this notification differently
+      // depending on whether TP is enabled or disabled.
+      mChannelClassifier->NotifyTrackingProtectionDisabled(channel);
+
+      if (CachedPrefs::GetInstance()->IsLowerNetworkPriority()) {
         LowerPriorityHelper(channel);
       }
     }
   }
 }
 
 } // end of unnamed namespace/
 
--- a/netwerk/base/nsIParentChannel.idl
+++ b/netwerk/base/nsIParentChannel.idl
@@ -45,16 +45,19 @@ interface nsIParentChannel : nsIStreamLi
    */
   [noscript] void setClassifierMatchedInfo(in ACString aList,
                                            in ACString aProvider,
                                            in ACString aFullHash);
 
   /**
    * Called to notify the HttpChannelChild that the resource being loaded
    * is on the tracking protection list.
+   * @param aIsThirdParty
+   *        Whether or not the resourced is considered first-party
+   *        with the URI of the window.
    */
-  [noscript] void notifyTrackingResource();
+  [noscript] void notifyTrackingResource(in bool aIsThirdParty);
 
   /**
    * Called to invoke deletion of the IPC protocol.
    */
   void delete();
 };
--- a/netwerk/protocol/data/DataChannelParent.cpp
+++ b/netwerk/protocol/data/DataChannelParent.cpp
@@ -34,17 +34,17 @@ DataChannelParent::SetParentListener(Htt
 NS_IMETHODIMP
 DataChannelParent::NotifyTrackingProtectionDisabled()
 {
     // Nothing to do.
     return NS_OK;
 }
 
 NS_IMETHODIMP
-DataChannelParent::NotifyTrackingResource()
+DataChannelParent::NotifyTrackingResource(bool aIsThirdParty)
 {
     // Nothing to do.
     return NS_OK;
 }
 
 NS_IMETHODIMP
 DataChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
                                             const nsACString& aProvider,
--- a/netwerk/protocol/file/FileChannelParent.cpp
+++ b/netwerk/protocol/file/FileChannelParent.cpp
@@ -34,17 +34,17 @@ FileChannelParent::SetParentListener(Htt
 NS_IMETHODIMP
 FileChannelParent::NotifyTrackingProtectionDisabled()
 {
   // Nothing to do.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-FileChannelParent::NotifyTrackingResource()
+FileChannelParent::NotifyTrackingResource(bool aIsThirdParty)
 {
   // Nothing to do.
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FileChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
                                             const nsACString& aProvider,
--- a/netwerk/protocol/ftp/FTPChannelParent.cpp
+++ b/netwerk/protocol/ftp/FTPChannelParent.cpp
@@ -572,17 +572,17 @@ FTPChannelParent::SetParentListener(Http
 NS_IMETHODIMP
 FTPChannelParent::NotifyTrackingProtectionDisabled()
 {
   // One day, this should probably be filled in.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-FTPChannelParent::NotifyTrackingResource()
+FTPChannelParent::NotifyTrackingResource(bool aIsThirdParty)
 {
   // One day, this should probably be filled in.
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FTPChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
                                            const nsACString& aProvider,
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
@@ -343,28 +343,29 @@ HttpBackgroundChannelChild::RecvNotifyTr
   // NotifyTrackingProtectionDisabled has no order dependency to OnStartRequest.
   // It this be handled as soon as possible
   mChannelChild->ProcessNotifyTrackingProtectionDisabled();
 
   return IPC_OK();
 }
 
 IPCResult
-HttpBackgroundChannelChild::RecvNotifyTrackingResource()
+HttpBackgroundChannelChild::RecvNotifyTrackingResource(const bool& aIsThirdParty)
 {
-  LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingResource [this=%p]\n", this));
+  LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingResource thirdparty=%d "
+       "[this=%p]\n", static_cast<int>(aIsThirdParty), this));
   MOZ_ASSERT(OnSocketThread());
 
   if (NS_WARN_IF(!mChannelChild)) {
     return IPC_OK();
   }
 
   // NotifyTrackingResource has no order dependency to OnStartRequest.
   // It this be handled as soon as possible
-  mChannelChild->ProcessNotifyTrackingResource();
+  mChannelChild->ProcessNotifyTrackingResource(aIsThirdParty);
 
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& info)
 {
   LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", this));
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.h
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.h
@@ -60,17 +60,17 @@ protected:
   IPCResult RecvFlushedForDiversion() override;
 
   IPCResult RecvDivertMessages() override;
 
   IPCResult RecvOnStartRequestSent() override;
 
   IPCResult RecvNotifyTrackingProtectionDisabled() override;
 
-  IPCResult RecvNotifyTrackingResource() override;
+  IPCResult RecvNotifyTrackingResource(const bool& aIsThirdParty) override;
 
   IPCResult RecvSetClassifierMatchedInfo(const ClassifierInfo& info) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   virtual ~HttpBackgroundChannelChild();
 
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelParent.cpp
@@ -375,40 +375,42 @@ HttpBackgroundChannelParent::OnNotifyTra
 
     return NS_SUCCEEDED(rv);
   }
 
   return SendNotifyTrackingProtectionDisabled();
 }
 
 bool
-HttpBackgroundChannelParent::OnNotifyTrackingResource()
+HttpBackgroundChannelParent::OnNotifyTrackingResource(bool aIsThirdParty)
 {
-  LOG(("HttpBackgroundChannelParent::OnNotifyTrackingResource [this=%p]\n", this));
+  LOG(("HttpBackgroundChannelParent::OnNotifyTrackingResource thirdparty=%d "
+       "[this=%p]\n", static_cast<int>(aIsThirdParty), this));
   AssertIsInMainProcess();
 
   if (NS_WARN_IF(!mIPCOpened)) {
     return false;
   }
 
   if (!IsOnBackgroundThread()) {
     MutexAutoLock lock(mBgThreadMutex);
     nsresult rv = mBackgroundThread->Dispatch(
-      NewRunnableMethod(
+      NewRunnableMethod<bool>(
         "net::HttpBackgroundChannelParent::OnNotifyTrackingResource",
         this,
-        &HttpBackgroundChannelParent::OnNotifyTrackingResource),
+        &HttpBackgroundChannelParent::OnNotifyTrackingResource,
+        aIsThirdParty),
       NS_DISPATCH_NORMAL);
 
     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
 
     return NS_SUCCEEDED(rv);
   }
 
-  return SendNotifyTrackingResource();
+  return SendNotifyTrackingResource(aIsThirdParty);
 }
 
 bool
 HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(const nsACString& aList,
                                                         const nsACString& aProvider,
                                                         const nsACString& aFullHash)
 {
   LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n", this));
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.h
+++ b/netwerk/protocol/http/HttpBackgroundChannelParent.h
@@ -65,17 +65,17 @@ public:
   // To send FlushedForDiversion and DivertMessages messages
   // over background channel.
   bool OnDiversion();
 
   // To send NotifyTrackingProtectionDisabled message over background channel.
   bool OnNotifyTrackingProtectionDisabled();
 
   // To send NotifyTrackingResource message over background channel.
-  bool OnNotifyTrackingResource();
+  bool OnNotifyTrackingResource(bool aIsThirdParty);
 
   // To send SetClassifierMatchedInfo message over background channel.
   bool OnSetClassifierMatchedInfo(const nsACString& aList,
                                   const nsACString& aProvider,
                                   const nsACString& aFullHash);
 
 protected:
   void ActorDestroy(ActorDestroyReason aWhy) override;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -166,17 +166,18 @@ HttpBaseChannel::HttpBaseChannel()
   , mRequestContextID(0)
   , mContentWindowId(0)
   , mTopLevelOuterContentWindowId(0)
   , mAltDataLength(0)
   , mChannelId(0)
   , mReqContentLength(0U)
   , mStatus(NS_OK)
   , mCanceled(false)
-  , mIsTrackingResource(false)
+  , mIsFirstPartyTrackingResource(false)
+  , mIsThirdPartyTrackingResource(false)
   , mLoadFlags(LOAD_NORMAL)
   , mCaps(0)
   , mClassOfService(0)
   , mUpgradeToSecure(false)
   , mApplyConversion(true)
   , mIsPending(false)
   , mWasOpened(false)
   , mRequestObserversCalled(false)
@@ -313,20 +314,28 @@ HttpBaseChannel::ReleaseMainThreadOnlyRe
     nsCOMPtr<nsISupports> nonTailRemover(new NonTailRemover(mRequestContext));
     arrayToRelease.AppendElement(nonTailRemover.forget());
   }
 
   NS_DispatchToMainThread(new ProxyReleaseRunnable(std::move(arrayToRelease)));
 }
 
 void
-HttpBaseChannel::SetIsTrackingResource()
-{
-  LOG(("HttpBaseChannel::SetIsTrackingResource %p", this));
-  mIsTrackingResource = true;
+HttpBaseChannel::SetIsTrackingResource(bool aIsThirdParty)
+{
+  LOG(("HttpBaseChannel::SetIsTrackingResource thirdparty=%d %p",
+       static_cast<int>(aIsThirdParty), this));
+
+  if (aIsThirdParty) {
+    MOZ_ASSERT(!mIsFirstPartyTrackingResource);
+    mIsThirdPartyTrackingResource = true;
+  } else {
+    MOZ_ASSERT(!mIsThirdPartyTrackingResource);
+    mIsFirstPartyTrackingResource = true;
+  }
 }
 
 nsresult
 HttpBaseChannel::Init(nsIURI *aURI,
                       uint32_t aCaps,
                       nsProxyInfo *aProxyInfo,
                       uint32_t aProxyResolveFlags,
                       nsIURI *aProxyURI,
@@ -1547,28 +1556,49 @@ NS_IMETHODIMP HttpBaseChannel::SetTopLev
 {
   mContentWindowId = aWindowId;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetIsTrackingResource(bool* aIsTrackingResource)
 {
-  *aIsTrackingResource = mIsTrackingResource;
+  MOZ_ASSERT(!(mIsFirstPartyTrackingResource && mIsThirdPartyTrackingResource));
+  *aIsTrackingResource =
+    mIsThirdPartyTrackingResource || mIsFirstPartyTrackingResource;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetIsThirdPartyTrackingResource(bool* aIsTrackingResource)
+{
+  MOZ_ASSERT(!(mIsFirstPartyTrackingResource && mIsThirdPartyTrackingResource));
+  *aIsTrackingResource = mIsThirdPartyTrackingResource;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HttpBaseChannel::OverrideTrackingResource(bool aIsTracking)
-{
-  LOG(("HttpBaseChannel::OverrideTrackingResource(%d) %p "
-       "mIsTrackingResource=%d",
-      (int) aIsTracking, this, (int) mIsTrackingResource));
-
-  mIsTrackingResource = aIsTracking;
+HttpBaseChannel::OverrideTrackingFlagsForDocumentCookieAccessor(nsIHttpChannel* aDocumentChannel)
+{
+  LOG(("HttpBaseChannel::OverrideTrackingFlagsForDocumentCookieAccessor() %p "
+       "mIsFirstPartyTrackingResource=%d  mIsThirdPartyTrackingResource=%d",
+       this, static_cast<int>(mIsFirstPartyTrackingResource),
+       static_cast<int>(mIsThirdPartyTrackingResource)));
+
+  // The semantics we'd like to achieve here are that document.cookie
+  // should follow the same rules that the document is subject to with
+  // regards to content blocking. Therefore we need to propagate the
+  // same flags from the document channel to the fake channel here.
+  if (aDocumentChannel->GetIsThirdPartyTrackingResource()) {
+    mIsThirdPartyTrackingResource = true;
+  } else {
+    mIsFirstPartyTrackingResource = true;
+  }
+
+  MOZ_ASSERT(!(mIsFirstPartyTrackingResource && mIsThirdPartyTrackingResource));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
 {
   *aTransferSize = mTransferSize;
   return NS_OK;
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -206,17 +206,18 @@ public:
   NS_IMETHOD GetProtocolVersion(nsACString & aProtocolVersion) override;
   NS_IMETHOD GetChannelId(uint64_t *aChannelId) override;
   NS_IMETHOD SetChannelId(uint64_t aChannelId) override;
   NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override;
   NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override;
   NS_IMETHOD GetTopLevelOuterContentWindowId(uint64_t *aWindowId) override;
   NS_IMETHOD SetTopLevelOuterContentWindowId(uint64_t aWindowId) override;
   NS_IMETHOD GetIsTrackingResource(bool* aIsTrackingResource) override;
-  NS_IMETHOD OverrideTrackingResource(bool aIsTracking) override;
+  NS_IMETHOD GetIsThirdPartyTrackingResource(bool* aIsTrackingResource) override;
+  NS_IMETHOD OverrideTrackingFlagsForDocumentCookieAccessor(nsIHttpChannel* aDocumentChannel) override;
 
   // nsIHttpChannelInternal
   NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
   NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI) override;
   NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor) override;
   NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor) override;
   NS_IMETHOD SetCookie(const char *aCookieHeader) override;
   NS_IMETHOD GetThirdPartyFlags(uint32_t *aForce) override;
@@ -373,17 +374,17 @@ public: /* Necko internal use only... */
     DoApplyContentConversions(nsIStreamListener *aNextListener,
                               nsIStreamListener **aNewNextListener);
 
     // Callback on STS thread called by CopyComplete when NS_AsyncCopy()
     // is finished. This function works as a proxy function to dispatch
     // |EnsureUploadStreamIsCloneableComplete| to main thread.
     virtual void OnCopyComplete(nsresult aStatus);
 
-    void SetIsTrackingResource();
+    void SetIsTrackingResource(bool aIsThirdParty);
 
     const uint64_t& ChannelId() const
     {
       return mChannelId;
     }
 
     void InternalSetUploadStream(nsIInputStream *uploadStream)
     {
@@ -620,17 +621,18 @@ protected:
   uint64_t mChannelId;
   uint64_t mReqContentLength;
 
   Atomic<nsresult, ReleaseAcquire>  mStatus;
 
   // Use Release-Acquire ordering to ensure the OMT ODA is ignored while channel
   // is canceled on main thread.
   Atomic<bool, ReleaseAcquire> mCanceled;
-  Atomic<bool, ReleaseAcquire> mIsTrackingResource;
+  Atomic<bool, ReleaseAcquire> mIsFirstPartyTrackingResource;
+  Atomic<bool, ReleaseAcquire> mIsThirdPartyTrackingResource;
 
   uint32_t                          mLoadFlags;
   uint32_t                          mCaps;
   uint32_t                          mClassOfService;
 
   uint32_t                          mUpgradeToSecure            : 1;
   uint32_t                          mApplyConversion            : 1;
   uint32_t                          mIsPending                  : 1;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -2035,22 +2035,23 @@ HttpChannelChild::ProcessNotifyTrackingP
       "nsChannelClassifier::NotifyTrackingProtectionDisabled",
       [self]() {
         nsChannelClassifier::NotifyTrackingProtectionDisabled(self);
       }),
     NS_DISPATCH_NORMAL);
 }
 
 void
-HttpChannelChild::ProcessNotifyTrackingResource()
+HttpChannelChild::ProcessNotifyTrackingResource(bool aIsThirdParty)
 {
-  LOG(("HttpChannelChild::ProcessNotifyTrackingResource [this=%p]\n", this));
+  LOG(("HttpChannelChild::ProcessNotifyTrackingResource thirdparty=%d "
+       "[this=%p]\n", static_cast<int>(aIsThirdParty), this));
   MOZ_ASSERT(OnSocketThread());
 
-  SetIsTrackingResource();
+  SetIsTrackingResource(aIsThirdParty);
 }
 
 void
 HttpChannelChild::FlushedForDiversion()
 {
   LOG(("HttpChannelChild::FlushedForDiversion [this=%p]\n", this));
   MOZ_RELEASE_ASSERT(mDivertingToParent);
 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -248,17 +248,17 @@ private:
   void ProcessOnStopRequest(const nsresult& aStatusCode,
                             const ResourceTimingStruct& aTiming,
                             const nsHttpHeaderArray& aResponseTrailers);
   void ProcessOnProgress(const int64_t& aProgress, const int64_t& aProgressMax);
   void ProcessOnStatus(const nsresult& aStatus);
   void ProcessFlushedForDiversion();
   void ProcessDivertMessages();
   void ProcessNotifyTrackingProtectionDisabled();
-  void ProcessNotifyTrackingResource();
+  void ProcessNotifyTrackingResource(bool aIsThirdParty);
   void ProcessSetClassifierMatchedInfo(const nsCString& aList,
                                        const nsCString& aProvider,
                                        const nsCString& aFullHash);
 
   // Return true if we need to tell the parent the size of unreported received
   // data
   bool NeedToReportBytesRead();
   int32_t mUnreportBytesRead = 0;
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -1819,22 +1819,23 @@ HttpChannelParent::SetClassifierMatchedI
   if (!mIPCClosed) {
     MOZ_ASSERT(mBgParent);
     Unused << mBgParent->OnSetClassifierMatchedInfo(aList, aProvider, aFullHash);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HttpChannelParent::NotifyTrackingResource()
+HttpChannelParent::NotifyTrackingResource(bool aIsThirdParty)
 {
-  LOG(("HttpChannelParent::NotifyTrackingResource [this=%p]\n", this));
+  LOG(("HttpChannelParent::NotifyTrackingResource thirdparty=%d [this=%p]\n",
+       static_cast<int>(aIsThirdParty), this));
   if (!mIPCClosed) {
     MOZ_ASSERT(mBgParent);
-    Unused << mBgParent->OnNotifyTrackingResource();
+    Unused << mBgParent->OnNotifyTrackingResource(aIsThirdParty);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelParent::Delete()
 {
   if (!mIPCClosed)
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -99,17 +99,23 @@ NullHttpChannel::SetTopLevelOuterContent
 
 NS_IMETHODIMP
 NullHttpChannel::GetIsTrackingResource(bool* aIsTrackingResource)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-NullHttpChannel::OverrideTrackingResource(bool aIsTracking)
+NullHttpChannel::GetIsThirdPartyTrackingResource(bool* aIsTrackingResource)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+NullHttpChannel::OverrideTrackingFlagsForDocumentCookieAccessor(nsIHttpChannel* aDocumentChannel)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 NullHttpChannel::GetTransferSize(uint64_t *aTransferSize)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
--- a/netwerk/protocol/http/PHttpBackgroundChannel.ipdl
+++ b/netwerk/protocol/http/PHttpBackgroundChannel.ipdl
@@ -53,17 +53,17 @@ child:
   // OnDataAvailable and OnStopRequest messages in the queue back to the parent.
   async DivertMessages();
 
   // Tell the child that tracking protection was disabled for this load.
   async NotifyTrackingProtectionDisabled();
 
   // Tell the child that the resource being loaded is on the tracking
   // protection list.
-  async NotifyTrackingResource();
+  async NotifyTrackingResource(bool aIsThirdParty);
 
   // Tell the child information of matched URL againts SafeBrowsing list
   async SetClassifierMatchedInfo(ClassifierInfo info);
 
   async __delete__();
 
 };
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -621,31 +621,22 @@ nsHttpChannel::Connect()
         LOG(("Resuming from cache is not supported yet"));
         return NS_ERROR_DOCUMENT_NOT_CACHED;
     }
 
     if (ShouldIntercept()) {
         return RedirectToInterceptedChannel();
     }
 
-    bool isTrackingResource = mIsTrackingResource; // is atomic
+    bool isTrackingResource = mIsThirdPartyTrackingResource; // is atomic
     LOG(("nsHttpChannel %p tracking resource=%d, cos=%u",
           this, isTrackingResource, mClassOfService));
 
     if (isTrackingResource) {
-        nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-          services::GetThirdPartyUtil();
-        bool result = false;
-        if (thirdPartyUtil &&
-            NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyChannel(this, nullptr,
-                                                             &result)) &&
-            result) {
-
-            AddClassFlags(nsIClassOfService::Tail);
-        }
+        AddClassFlags(nsIClassOfService::Tail);
     }
 
     if (WaitingForTailUnblock()) {
         MOZ_DIAGNOSTIC_ASSERT(!mOnTailUnblock);
         mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
         return NS_OK;
     }
 
@@ -689,24 +680,16 @@ nsHttpChannel::CheckFastBlocked()
 
     if (!sFastBlockInited) {
         sFastBlockInited = true;
         Preferences::AddBoolVarCache(&sIsContentBlockingEnabled, "browser.contentblocking.enabled");
         Preferences::AddBoolVarCache(&sIsFastBlockEnabled, "browser.fastblock.enabled");
         Preferences::AddUintVarCache(&sFastBlockTimeout, "browser.fastblock.timeout");
     }
 
-    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
-    bool result = false;
-    if (!thirdPartyUtil ||
-        NS_FAILED(thirdPartyUtil->IsThirdPartyChannel(this, nullptr, &result)) ||
-        !result) {
-        return false;
-    }
-
     TimeStamp timestamp;
     if (NS_FAILED(GetNavigationStartTimeStamp(&timestamp))) {
         return false;
     }
 
     if (!sIsContentBlockingEnabled || !sIsFastBlockEnabled ||
         IsContentPolicyTypeWhitelistedForFastBlock(mLoadInfo) ||
         !timestamp) {
@@ -730,17 +713,17 @@ nsHttpChannel::CheckFastBlocked()
 
 nsresult
 nsHttpChannel::ConnectOnTailUnblock()
 {
     nsresult rv;
 
     LOG(("nsHttpChannel::ConnectOnTailUnblock [this=%p]\n", this));
 
-    bool isTrackingResource = mIsTrackingResource; // is atomic
+    bool isTrackingResource = mIsThirdPartyTrackingResource; // is atomic
     if (isTrackingResource && CheckFastBlocked()) {
         Unused << AsyncAbort(NS_ERROR_ABORT);
         CloseCacheEntry(false);
         return NS_OK;
     }
 
     // Consider opening a TCP connection right away.
     SpeculativeConnect();
@@ -2323,34 +2306,22 @@ nsHttpChannel::ProcessResponse()
     // If that's null, though, we'll fall back to mReferrer just in case (this
     // is especially useful in xpcshell tests, where we don't have an actual
     // pageload to get a referrer from).
     nsCOMPtr<nsIURI> referrer = GetReferringPage();
     if (!referrer) {
         referrer = mReferrer;
     }
 
-    // We consider top-level tracking resource as non-tracking if not in 3rd
-    // party context.
-    bool isThirdPartyAndTrackingResource = false;
-    if(mIsTrackingResource) {
-        nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-          services::GetThirdPartyUtil();
-        if (thirdPartyUtil) {
-            thirdPartyUtil->IsThirdPartyChannel(this, nullptr,
-                                                &isThirdPartyAndTrackingResource);
-        }
-    }
-
     if (referrer) {
         nsCOMPtr<nsILoadContextInfo> lci = GetLoadContextInfo(this);
         mozilla::net::Predictor::UpdateCacheability(referrer, mURI, httpStatus,
                                                     mRequestHead, mResponseHead,
                                                     lci,
-                                                    isThirdPartyAndTrackingResource);
+                                                    mIsThirdPartyTrackingResource);
     }
 
     // Only allow 407 (authentication required) to continue
     if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
         return ProcessFailedProxyConnect(httpStatus);
     }
 
     MOZ_ASSERT(!mCachedContentIsValid || mRaceCacheWithNetwork,
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -474,30 +474,46 @@ interface nsIHttpChannel : nsIChannel
      */
     [must_use] attribute uint64_t topLevelContentWindowId;
 
     /**
      * Returns true if the channel has loaded a resource that is on the tracking
      * protection list.  This is only available if the
      * privacy.trackingprotection.annotate_channels pref is set and its value
      * should only be relied on after the channel has established a connection.
-     * Note that, if the privacy.trackingprotection.annotate_channels pref is set, also
-     * top-level channels could be marked as tracking resource.
+     *
+     * Note that top-level channels could be marked as tracking
+     * resource. In order to identify third-party tracking resources
+     * specifically, use isThirdPartyTrackingResource.
      */
     [infallible] readonly attribute boolean isTrackingResource;
 
     /**
-     * This method is used in order to override the tracking status of an HTTP
-     * channel.  This should only be called by Gecko under certain circumstances
-     * when Gecko can guarantee that the channel classifier service will not be
+     * Returns true if the channel has loaded a resource that is on the tracking
+     * protection list and is considered third-party with the top window URI.
+     * This is only available if the privacy.trackingprotection.annotate_channels
+     * pref is set and its value should only be relied on after the channel has
+     * established a connection.
+     */
+    [infallible] readonly attribute boolean isThirdPartyTrackingResource;
+
+    /**
+     * This method is used by the document.cookie call site in order
+     * to override the tracking status of an HTTP channel. This should
+     * only be called by Gecko under certain circumstances when Gecko
+     * can guarantee that the channel classifier service will not be
      * determining the tracking status of the channel.
      *
-     * Please avoid calling this API if you're unsure whether you should be using it.
+     * @param aDocumentChannel
+     *        The document channel from which to copy the tracking flags
+     *
+     * Please avoid calling this API if you're unsure whether you
+     * should be using it.
      */
-    [noscript] void overrideTrackingResource(in boolean aIsTracking);
+    [noscript] void overrideTrackingFlagsForDocumentCookieAccessor(in nsIHttpChannel aDocumentChannel);
 
     /**
      * ID of the top-level outer content window. Identifies this channel's
      * top-level window it comes from.
      *
      * NOTE: The setter of this attribute is currently for xpcshell test only.
      *       Don't alter it otherwise.
      */
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -829,20 +829,27 @@ nsViewSourceChannel::SetTopLevelOuterCon
 NS_IMETHODIMP
 nsViewSourceChannel::GetIsTrackingResource(bool* aIsTrackingResource)
 {
   return !mHttpChannel ? NS_ERROR_NULL_POINTER :
       mHttpChannel->GetIsTrackingResource(aIsTrackingResource);
 }
 
 NS_IMETHODIMP
-nsViewSourceChannel::OverrideTrackingResource(bool aIsTracking)
+nsViewSourceChannel::GetIsThirdPartyTrackingResource(bool* aIsTrackingResource)
 {
   return !mHttpChannel ? NS_ERROR_NULL_POINTER :
-      mHttpChannel->OverrideTrackingResource(aIsTracking);
+      mHttpChannel->GetIsThirdPartyTrackingResource(aIsTrackingResource);
+}
+
+NS_IMETHODIMP
+nsViewSourceChannel::OverrideTrackingFlagsForDocumentCookieAccessor(nsIHttpChannel* aDocumentChannel)
+{
+  return !mHttpChannel ? NS_ERROR_NULL_POINTER :
+      mHttpChannel->OverrideTrackingFlagsForDocumentCookieAccessor(aDocumentChannel);
 }
 
 NS_IMETHODIMP
 nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
 {
     return !mHttpChannel ? NS_ERROR_NULL_POINTER :
         mHttpChannel->GetRequestMethod(aRequestMethod);
 }
--- a/netwerk/test/unit/test_trackingProtection_annotateChannels.js
+++ b/netwerk/test/unit/test_trackingProtection_annotateChannels.js
@@ -274,26 +274,26 @@ var tests = [
         expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
         expectedThrottleable: false, // ignored since tracking==false
       },
       {
         path: trackingOrigin + "/evil.css",
         loadingPrincipal: null, // system principal
         topWindowURI: defaultTopWindowURI,
         expectedTracking: true,
-        expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
-        expectedThrottleable: false,
+        expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
+        expectedThrottleable: true,
       },
       {
         path: trackingOrigin + "/evil.js",
         loadingPrincipal: null, // system principal
         topWindowURI: defaultTopWindowURI,
         expectedTracking: true,
-        expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
-        expectedThrottleable: false,
+        expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
+        expectedThrottleable: true,
       },
     ];
     // We add the doPriorityTest test here so that it only gets injected in the
     // test list if we're not skipping over this test.
     tests.unshift(doPriorityTest);
     runTests();
   },
 
--- a/uriloader/exthandler/nsExternalProtocolHandler.cpp
+++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp
@@ -425,17 +425,17 @@ NS_IMETHODIMP nsExtProtocolChannel::Noti
 NS_IMETHODIMP nsExtProtocolChannel::SetClassifierMatchedInfo(const nsACString& aList,
                                                              const nsACString& aProvider,
                                                              const nsACString& aFullHash)
 {
   // nothing to do
   return NS_OK;
 }
 
-NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingResource()
+NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingResource(bool aIsThirdParty)
 {
   // nothing to do
   return NS_OK;
 }
 
 NS_IMETHODIMP nsExtProtocolChannel::Delete()
 {
   // nothing to do