diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 3e604f9cde39..38d82d2fe32c 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -301,6 +301,7 @@ bool nsContentUtils::sAnimationsAPIElementAnimateEnabled = false; bool nsContentUtils::sGetBoxQuadsEnabled = false; bool nsContentUtils::sSkipCursorMoveForSameValueSet = false; bool nsContentUtils::sRequestIdleCallbackEnabled = false; +bool nsContentUtils::sLowerNetworkPriority = false; int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000; int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000; @@ -715,6 +716,9 @@ nsContentUtils::Init() Preferences::AddBoolVarCache(&sRequestIdleCallbackEnabled, "dom.requestIdleCallback.enabled", false); + Preferences::AddBoolVarCache(&sLowerNetworkPriority, + "privacy.trackingprotection.lower_network_priority", false); + Element::InitCCCallbacks(); Unused << nsRFPService::GetOrCreate(); diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 6852ef009aa1..41fedbf90aee 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2953,6 +2953,10 @@ public: static bool GetUserIsInteracting(); + // Check pref "privacy.trackingprotection.lower_network_priority" to see + // if we want to lower the priority of the channel. + static bool IsLowerNetworkPriority() { return sLowerNetworkPriority; } + private: static bool InitializeEventTable(); @@ -3079,6 +3083,7 @@ private: static bool sGetBoxQuadsEnabled; static bool sSkipCursorMoveForSameValueSet; static bool sRequestIdleCallbackEnabled; + static bool sLowerNetworkPriority; static uint32_t sCookiesLifetimePolicy; static uint32_t sCookiesBehavior; diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index f8e589fec1b6..2774a056ee9c 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -46,6 +46,7 @@ #include "nsIAuthPrompt2.h" #include "nsIOutputStream.h" #include "nsISupportsPrimitives.h" +#include "nsISupportsPriority.h" #include "nsIInterfaceRequestorUtils.h" #include "nsStreamUtils.h" #include "nsThreadUtils.h" @@ -2550,6 +2551,37 @@ XMLHttpRequestMainThread::CreateChannel() return NS_OK; } +void +XMLHttpRequestMainThread::MaybeLowerChannelPriority() +{ + nsCOMPtr doc = GetDocumentIfCurrent(); + if (!doc) { + return; + } + + AutoJSAPI jsapi; + if (!jsapi.Init(GetOwnerGlobal())) { + return; + } + + JSContext* cx = jsapi.cx(); + nsAutoCString fileNameString; + if (!nsJSUtils::GetCallingLocation(cx, fileNameString)) { + return; + } + + if (!doc->IsScriptTracking(fileNameString)) { + return; + } + + nsCOMPtr p = do_QueryInterface(mChannel); + if (!p) { + return; + } + + p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST); +} + nsresult XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream, int64_t aUploadLength, @@ -2738,6 +2770,12 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream, // Make sure to hold a strong reference so that we don't leak the wrapper. nsCOMPtr listener = new net::nsStreamListenerWrapper(this); + // Check if this XHR is created from a tracking script. + // If yes, lower the channel's priority. + if (nsContentUtils::IsLowerNetworkPriority()) { + MaybeLowerChannelPriority(); + } + // Start reading from the channel rv = mChannel->AsyncOpen2(listener); listener = nullptr; diff --git a/dom/xhr/XMLHttpRequestMainThread.h b/dom/xhr/XMLHttpRequestMainThread.h index 637aa164c1b1..e15a8d847d92 100644 --- a/dom/xhr/XMLHttpRequestMainThread.h +++ b/dom/xhr/XMLHttpRequestMainThread.h @@ -314,6 +314,8 @@ private: // response header is supported. static bool IsLowercaseResponseHeader(); + void MaybeLowerChannelPriority(); + public: virtual void Send(JSContext* /*aCx*/, ErrorResult& aRv) override