diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 751e7695c1ed..abf349dff0b8 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -15970,5 +15970,16 @@ bool Document::HasRecentlyStartedForegroundLoads() { return false; } +already_AddRefed +Document::RecomputeContentBlockingAllowListPrincipal( + nsIURI* aURIBeingLoaded, const OriginAttributes& aAttrs) { + AntiTrackingCommon::RecomputeContentBlockingAllowListPrincipal( + aURIBeingLoaded, aAttrs, + getter_AddRefs(mContentBlockingAllowListPrincipal)); + + nsCOMPtr copy = mContentBlockingAllowListPrincipal; + return copy.forget(); +} + } // namespace dom } // namespace mozilla diff --git a/dom/base/Document.h b/dom/base/Document.h index 7b4482ed4624..708dfdcb501a 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -574,6 +574,9 @@ class Document : public nsINode, return mContentBlockingAllowListPrincipal; } + already_AddRefed RecomputeContentBlockingAllowListPrincipal( + nsIURI* aURIBeingLoaded, const OriginAttributes& aAttrs); + // EventTarget void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; EventListenerManager* GetOrCreateListenerManager() override; diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp index 10e185dfe28d..d1e6a641d659 100644 --- a/dom/base/ThirdPartyUtil.cpp +++ b/dom/base/ThirdPartyUtil.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ThirdPartyUtil.h" +#include "nsDocShell.h" #include "nsGlobalWindowOuter.h" #include "nsNetCID.h" #include "nsNetUtil.h" @@ -139,6 +140,43 @@ ThirdPartyUtil::GetURIFromWindow(mozIDOMWindowProxy* aWin, nsIURI** result) { return rv; } +NS_IMETHODIMP +ThirdPartyUtil::GetContentBlockingAllowListPrincipalFromWindow( + mozIDOMWindowProxy* aWin, nsIURI* aURIBeingLoaded, nsIPrincipal** result) { + nsPIDOMWindowOuter* outerWindow = nsPIDOMWindowOuter::From(aWin); + nsPIDOMWindowInner* innerWindow = outerWindow->GetCurrentInnerWindow(); + Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr; + if (!doc) { + return GetPrincipalFromWindow(aWin, result); + } + + nsCOMPtr principal = + doc->GetContentBlockingAllowListPrincipal(); + if (aURIBeingLoaded && principal && principal->GetIsNullPrincipal()) { + // If we have an initial principal during navigation, recompute it to get + // the real content blocking allow list principal. + nsIDocShell* docShell = doc->GetDocShell(); + OriginAttributes attrs = + docShell ? nsDocShell::Cast(docShell)->GetOriginAttributes() + : OriginAttributes(); + principal = + doc->RecomputeContentBlockingAllowListPrincipal(aURIBeingLoaded, attrs); + } + + if (!principal || !principal->GetIsContentPrincipal()) { + // This is for compatibility with GetURIFromWindow. Null principals are + // explicitly special cased there. GetURI returns nullptr for + // SystemPrincipal and ExpandedPrincipal. + LOG( + ("ThirdPartyUtil::GetContentBlockingAllowListPrincipalFromWindow can't " + "use null principal\n")); + return NS_ERROR_INVALID_ARG; + } + + principal.forget(result); + return NS_OK; +} + // Determine if aFirstURI is third party with respect to aSecondURI. See docs // for mozIThirdPartyUtil. NS_IMETHODIMP diff --git a/netwerk/base/mozIThirdPartyUtil.idl b/netwerk/base/mozIThirdPartyUtil.idl index 17930be1e1d1..fdd4da5a3926 100644 --- a/netwerk/base/mozIThirdPartyUtil.idl +++ b/netwerk/base/mozIThirdPartyUtil.idl @@ -177,6 +177,15 @@ interface mozIThirdPartyUtil : nsISupports */ nsIPrincipal getPrincipalFromWindow(in mozIDOMWindowProxy aWindow); + /** + * getContentBlockingAllowListPrincipalFromWindow + * + * Returns the content blocking allow list principal for the window. + */ + [noscript] + nsIPrincipal getContentBlockingAllowListPrincipalFromWindow(in mozIDOMWindowProxy aWindow, + [optional] in nsIURI aURIBeingLoaded); + /** * getTopWindowForChannel * diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 874ea335c74d..b2f7e73769d1 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -234,6 +234,7 @@ struct HttpChannelOpenArgs nsIReferrerInfo referrerInfo; URIParams? apiRedirectTo; URIParams? topWindowURI; + OptionalPrincipalInfo contentBlockingAllowListPrincipal; uint32_t loadFlags; RequestHeaderTuples requestHeaders; nsCString requestMethod; diff --git a/netwerk/ipc/NeckoChild.cpp b/netwerk/ipc/NeckoChild.cpp index 9afc7186c9af..3866679c4556 100644 --- a/netwerk/ipc/NeckoChild.cpp +++ b/netwerk/ipc/NeckoChild.cpp @@ -418,8 +418,9 @@ mozilla::ipc::IPCResult NeckoChild::RecvNetworkChangeNotification( } PClassifierDummyChannelChild* NeckoChild::AllocPClassifierDummyChannelChild( - nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult, - const Maybe& aLoadInfo) { + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo) { return new ClassifierDummyChannelChild(); } diff --git a/netwerk/ipc/NeckoChild.h b/netwerk/ipc/NeckoChild.h index 2f0c2c11b302..bb852f48414f 100644 --- a/netwerk/ipc/NeckoChild.h +++ b/netwerk/ipc/NeckoChild.h @@ -93,7 +93,9 @@ class NeckoChild : public PNeckoChild { mozilla::ipc::IPCResult RecvNetworkChangeNotification(nsCString const& type); PClassifierDummyChannelChild* AllocPClassifierDummyChannelChild( - nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult, + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo); bool DeallocPClassifierDummyChannelChild( diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index b301ba693242..d8e1e8e1ed84 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -905,14 +905,16 @@ mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionFD( } PClassifierDummyChannelParent* NeckoParent::AllocPClassifierDummyChannelParent( - nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult, - const Maybe& aLoadInfo) { + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo) { RefPtr c = new ClassifierDummyChannelParent(); return c.forget().take(); } mozilla::ipc::IPCResult NeckoParent::RecvPClassifierDummyChannelConstructor( PClassifierDummyChannelParent* aActor, nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo) { ClassifierDummyChannelParent* p = static_cast(aActor); @@ -927,7 +929,8 @@ mozilla::ipc::IPCResult NeckoParent::RecvPClassifierDummyChannelConstructor( return IPC_FAIL_NO_REASON(this); } - p->Init(aURI, aTopWindowURI, aTopWindowURIResult, loadInfo); + p->Init(aURI, aTopWindowURI, aContentBlockingAllowListPrincipal, + aTopWindowURIResult, loadInfo); return IPC_OK(); } diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h index fc1455b8a7ce..0e10728342e1 100644 --- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -224,7 +224,9 @@ class NeckoParent : public PNeckoParent { GetExtensionFDResolver&& aResolve); PClassifierDummyChannelParent* AllocPClassifierDummyChannelParent( - nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult, + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo); bool DeallocPClassifierDummyChannelParent( @@ -232,7 +234,8 @@ class NeckoParent : public PNeckoParent { virtual mozilla::ipc::IPCResult RecvPClassifierDummyChannelConstructor( PClassifierDummyChannelParent* aActor, nsIURI* aURI, - nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult, + nsIURI* aTopWindowURI, nsIPrincipal* aContentBlockingAllowListPrincipal, + const nsresult& aTopWindowURIResult, const Maybe& aLoadInfo) override; mozilla::ipc::IPCResult RecvInitSocketProcessBridge( diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl index d16f88ba22c9..23fb73f60291 100644 --- a/netwerk/ipc/PNecko.ipdl +++ b/netwerk/ipc/PNecko.ipdl @@ -116,6 +116,7 @@ parent: async PChannelDiverter(ChannelDiverterArgs channel); async PClassifierDummyChannel(nsIURI uri, nsIURI aTopWindowURI, + nsIPrincipal contentBlockingAllowListPrincipal, nsresult aTopWindowURIResult, LoadInfoArgs? loadInfo); diff --git a/netwerk/protocol/http/ClassifierDummyChannel.cpp b/netwerk/protocol/http/ClassifierDummyChannel.cpp index 25f550ead0ed..5cb5b8945515 100644 --- a/netwerk/protocol/http/ClassifierDummyChannel.cpp +++ b/netwerk/protocol/http/ClassifierDummyChannel.cpp @@ -77,11 +77,12 @@ NS_INTERFACE_MAP_BEGIN(ClassifierDummyChannel) NS_INTERFACE_MAP_ENTRY_CONCRETE(ClassifierDummyChannel) NS_INTERFACE_MAP_END -ClassifierDummyChannel::ClassifierDummyChannel(nsIURI* aURI, - nsIURI* aTopWindowURI, - nsresult aTopWindowURIResult, - nsILoadInfo* aLoadInfo) +ClassifierDummyChannel::ClassifierDummyChannel( + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + nsresult aTopWindowURIResult, nsILoadInfo* aLoadInfo) : mTopWindowURI(aTopWindowURI), + mContentBlockingAllowListPrincipal(aContentBlockingAllowListPrincipal), mTopWindowURIResult(aTopWindowURIResult), mClassificationFlags(0) { MOZ_ASSERT(XRE_IsParentProcess()); @@ -97,6 +98,9 @@ ClassifierDummyChannel::~ClassifierDummyChannel() { mURI.forget()); NS_ReleaseOnMainThreadSystemGroup("ClassifierDummyChannel::mTopWindowURI", mTopWindowURI.forget()); + NS_ReleaseOnMainThreadSystemGroup( + "ClassifierDummyChannel::mContentBlockingAllowListPrincipal", + mContentBlockingAllowListPrincipal.forget()); } uint32_t ClassifierDummyChannel::ClassificationFlags() const { @@ -555,6 +559,14 @@ ClassifierDummyChannel::GetTopWindowURI(nsIURI** aTopWindowURI) { return mTopWindowURIResult; } +NS_IMETHODIMP +ClassifierDummyChannel::GetContentBlockingAllowListPrincipal( + nsIPrincipal** aPrincipal) { + nsCOMPtr copy = mContentBlockingAllowListPrincipal; + copy.forget(aPrincipal); + return NS_OK; +} + NS_IMETHODIMP ClassifierDummyChannel::SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) { return NS_ERROR_NOT_IMPLEMENTED; diff --git a/netwerk/protocol/http/ClassifierDummyChannel.h b/netwerk/protocol/http/ClassifierDummyChannel.h index 0ac402ca74eb..9593f2ab4fc8 100644 --- a/netwerk/protocol/http/ClassifierDummyChannel.h +++ b/netwerk/protocol/http/ClassifierDummyChannel.h @@ -19,6 +19,7 @@ } class nsIChannel; +class nsIPrincipal; namespace mozilla { namespace net { @@ -64,6 +65,7 @@ class ClassifierDummyChannel final : public nsIChannel, nsIChannel* aChannel, const std::function& aCallback); ClassifierDummyChannel(nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, nsresult aTopWindowURIResult, nsILoadInfo* aLoadInfo); uint32_t ClassificationFlags() const; @@ -76,6 +78,7 @@ class ClassifierDummyChannel final : public nsIChannel, nsCOMPtr mLoadInfo; nsCOMPtr mURI; nsCOMPtr mTopWindowURI; + nsCOMPtr mContentBlockingAllowListPrincipal; nsresult mTopWindowURIResult; uint32_t mClassificationFlags; diff --git a/netwerk/protocol/http/ClassifierDummyChannelChild.cpp b/netwerk/protocol/http/ClassifierDummyChannelChild.cpp index 4dc1c41d4c5d..51f4c2397edb 100644 --- a/netwerk/protocol/http/ClassifierDummyChannelChild.cpp +++ b/netwerk/protocol/http/ClassifierDummyChannelChild.cpp @@ -33,13 +33,18 @@ bool ClassifierDummyChannelChild::Create( nsresult topWindowURIResult = httpChannelInternal->GetTopWindowURI(getter_AddRefs(topWindowURI)); + nsCOMPtr principal; + nsresult rv = httpChannelInternal->GetContentBlockingAllowListPrincipal( + getter_AddRefs(principal)); + MOZ_ALWAYS_SUCCEEDS(rv); + nsCOMPtr loadInfo = aChannel->LoadInfo(); Maybe loadInfoArgs; mozilla::ipc::LoadInfoToLoadInfoArgs(loadInfo, &loadInfoArgs); PClassifierDummyChannelChild* actor = gNeckoChild->SendPClassifierDummyChannelConstructor( - aURI, topWindowURI, topWindowURIResult, loadInfoArgs); + aURI, topWindowURI, principal, topWindowURIResult, loadInfoArgs); if (!actor) { return false; } diff --git a/netwerk/protocol/http/ClassifierDummyChannelParent.cpp b/netwerk/protocol/http/ClassifierDummyChannelParent.cpp index d6c8cf868f91..380961706afd 100644 --- a/netwerk/protocol/http/ClassifierDummyChannelParent.cpp +++ b/netwerk/protocol/http/ClassifierDummyChannelParent.cpp @@ -19,9 +19,10 @@ ClassifierDummyChannelParent::ClassifierDummyChannelParent() ClassifierDummyChannelParent::~ClassifierDummyChannelParent() = default; -void ClassifierDummyChannelParent::Init(nsIURI* aURI, nsIURI* aTopWindowURI, - nsresult aTopWindowURIResult, - nsILoadInfo* aLoadInfo) { +void ClassifierDummyChannelParent::Init( + nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + nsresult aTopWindowURIResult, nsILoadInfo* aLoadInfo) { MOZ_ASSERT(mIPCActive); RefPtr self = this; @@ -33,7 +34,8 @@ void ClassifierDummyChannelParent::Init(nsIURI* aURI, nsIURI* aTopWindowURI, } RefPtr channel = new ClassifierDummyChannel( - aURI, aTopWindowURI, aTopWindowURIResult, aLoadInfo); + aURI, aTopWindowURI, aContentBlockingAllowListPrincipal, + aTopWindowURIResult, aLoadInfo); bool willCallback = NS_SUCCEEDED(AsyncUrlChannelClassifier::CheckChannel( channel, [self = std::move(self), channel]() { diff --git a/netwerk/protocol/http/ClassifierDummyChannelParent.h b/netwerk/protocol/http/ClassifierDummyChannelParent.h index fe9397e4f77c..c9274ae298b6 100644 --- a/netwerk/protocol/http/ClassifierDummyChannelParent.h +++ b/netwerk/protocol/http/ClassifierDummyChannelParent.h @@ -23,8 +23,9 @@ class ClassifierDummyChannelParent final ClassifierDummyChannelParent(); - void Init(nsIURI* aURI, nsIURI* aTopWindowURI, nsresult aTopWindowURIResult, - nsILoadInfo* aLoadInfo); + void Init(nsIURI* aURI, nsIURI* aTopWindowURI, + nsIPrincipal* aContentBlockingAllowListPrincipal, + nsresult aTopWindowURIResult, nsILoadInfo* aLoadInfo); private: ~ClassifierDummyChannelParent(); diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 4c6f11d1a40c..3ffb67bf37bf 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -298,6 +298,7 @@ void HttpBaseChannel::ReleaseMainThreadOnlyReferences() { arrayToRelease.AppendElement(mProxyURI.forget()); arrayToRelease.AppendElement(mPrincipal.forget()); arrayToRelease.AppendElement(mTopWindowURI.forget()); + arrayToRelease.AppendElement(mContentBlockingAllowListPrincipal.forget()); arrayToRelease.AppendElement(mListener.forget()); arrayToRelease.AppendElement(mCompressListener.forget()); @@ -2052,6 +2053,12 @@ nsresult HttpBaseChannel::GetTopWindowURI(nsIURI* aURIBeingLoaded, } } #endif + + if (!mContentBlockingAllowListPrincipal) { + Unused << util->GetContentBlockingAllowListPrincipalFromWindow( + win, aURIBeingLoaded, + getter_AddRefs(mContentBlockingAllowListPrincipal)); + } } } NS_IF_ADDREF(*aTopWindowURI = mTopWindowURI); @@ -2066,6 +2073,27 @@ HttpBaseChannel::GetDocumentURI(nsIURI** aDocumentURI) { return NS_OK; } +NS_IMETHODIMP +HttpBaseChannel::GetContentBlockingAllowListPrincipal( + nsIPrincipal** aPrincipal) { + NS_ENSURE_ARG_POINTER(aPrincipal); + if (!mContentBlockingAllowListPrincipal) { + if (!mTopWindowURI) { + // If mTopWindowURI is null, it's possible that these two fields haven't + // been initialized yet. GetTopWindowURI will lazily initilize both + // fields for us. + nsCOMPtr throwAway; + Unused << GetTopWindowURI(getter_AddRefs(throwAway)); + } else { + // Otherwise, the content blocking allow list principal is null (which is + // possible), so just return what we have... + } + } + nsCOMPtr copy = mContentBlockingAllowListPrincipal; + copy.forget(aPrincipal); + return NS_OK; +} + NS_IMETHODIMP HttpBaseChannel::SetDocumentURI(nsIURI* aDocumentURI) { ENSURE_CALLED_BEFORE_CONNECT(); diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 391e6eeeb06e..d11e8b4b7055 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -299,6 +299,8 @@ class HttpBaseChannel : public nsHashPropertyBag, NS_IMETHOD GetFetchCacheMode(uint32_t* aFetchCacheMode) override; NS_IMETHOD SetFetchCacheMode(uint32_t aFetchCacheMode) override; NS_IMETHOD GetTopWindowURI(nsIURI** aTopWindowURI) override; + NS_IMETHOD GetContentBlockingAllowListPrincipal( + nsIPrincipal** aPrincipal) override; NS_IMETHOD SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) override; NS_IMETHOD GetProxyURI(nsIURI** proxyURI) override; virtual void SetCorsPreflightParameters( @@ -464,6 +466,10 @@ class HttpBaseChannel : public nsHashPropertyBag, return NS_OK; } + void SetContentBlockingAllowListPrincipal(nsIPrincipal* aPrincipal) { + mContentBlockingAllowListPrincipal = aPrincipal; + } + // Set referrerInfo and compute the referrer header if neccessary. nsresult SetReferrerInfo(nsIReferrerInfo* aReferrerInfo, bool aClone, bool aCompute); @@ -572,6 +578,7 @@ class HttpBaseChannel : public nsHashPropertyBag, nsCOMPtr mProxyURI; nsCOMPtr mPrincipal; nsCOMPtr mTopWindowURI; + nsCOMPtr mContentBlockingAllowListPrincipal; nsCOMPtr mListener; // An instance of nsHTTPCompressConv nsCOMPtr mCompressListener; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 07b7191114a5..c4e98e6c5553 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -2840,12 +2840,25 @@ nsresult HttpChannelChild::ContinueAsyncOpen() { Maybe optionalCorsPreflightArgs; GetClientSetCorsPreflightParameters(optionalCorsPreflightArgs); - // NB: This call forces us to cache mTopWindowURI if we haven't already. + // NB: This call forces us to cache mTopWindowURI and + // mContentBlockingAllowListPrincipal if we haven't already. nsCOMPtr uri; GetTopWindowURI(mURI, getter_AddRefs(uri)); SerializeURI(mTopWindowURI, openArgs.topWindowURI()); + if (mContentBlockingAllowListPrincipal) { + PrincipalInfo principalInfo; + rv = PrincipalToPrincipalInfo(mContentBlockingAllowListPrincipal, + &principalInfo); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + openArgs.contentBlockingAllowListPrincipal() = principalInfo; + } else { + openArgs.contentBlockingAllowListPrincipal() = void_t(); + } + openArgs.preflightArgs() = optionalCorsPreflightArgs; openArgs.uploadStreamHasHeaders() = mUploadStreamHasHeaders; diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 629600176bfa..1ed2235c5886 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -133,14 +133,21 @@ bool HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs) { switch (aArgs.type()) { case HttpChannelCreationArgs::THttpChannelOpenArgs: { const HttpChannelOpenArgs& a = aArgs.get_HttpChannelOpenArgs(); + PrincipalInfo contentBlockingAllowListPrincipal; + if (a.contentBlockingAllowListPrincipal().type() == + OptionalPrincipalInfo::TPrincipalInfo) { + contentBlockingAllowListPrincipal = + a.contentBlockingAllowListPrincipal(); + } return DoAsyncOpen( a.uri(), a.original(), a.doc(), a.referrerInfo(), a.apiRedirectTo(), - a.topWindowURI(), a.loadFlags(), a.requestHeaders(), - a.requestMethod(), a.uploadStream(), a.uploadStreamHasHeaders(), - a.priority(), a.classOfService(), a.redirectionLimit(), a.allowSTS(), - a.thirdPartyFlags(), a.resumeAt(), a.startPos(), a.entityID(), - a.chooseApplicationCache(), a.appCacheClientID(), a.allowSpdy(), - a.allowAltSvc(), a.beConservative(), a.tlsFlags(), a.loadInfo(), + a.topWindowURI(), contentBlockingAllowListPrincipal, a.loadFlags(), + a.requestHeaders(), a.requestMethod(), a.uploadStream(), + a.uploadStreamHasHeaders(), a.priority(), a.classOfService(), + a.redirectionLimit(), a.allowSTS(), a.thirdPartyFlags(), a.resumeAt(), + a.startPos(), a.entityID(), a.chooseApplicationCache(), + a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), + a.beConservative(), a.tlsFlags(), a.loadInfo(), a.synthesizedResponseHead(), a.synthesizedSecurityInfoSerialization(), a.cacheKey(), a.requestContextID(), a.preflightArgs(), a.initialRwin(), a.blockAuthPrompt(), @@ -382,13 +389,14 @@ bool HttpChannelParent::DoAsyncOpen( const URIParams& aURI, const Maybe& aOriginalURI, const Maybe& aDocURI, nsIReferrerInfo* aReferrerInfo, const Maybe& aAPIRedirectToURI, - const Maybe& aTopWindowURI, const uint32_t& aLoadFlags, - const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, - const Maybe& uploadStream, const bool& uploadStreamHasHeaders, - const int16_t& priority, const uint32_t& classOfService, - const uint8_t& redirectionLimit, const bool& allowSTS, - const uint32_t& thirdPartyFlags, const bool& doResumeAt, - const uint64_t& startPos, const nsCString& entityID, + const Maybe& aTopWindowURI, + const PrincipalInfo& aContentBlockingAllowListPrincipal, + const uint32_t& aLoadFlags, const RequestHeaderTuples& requestHeaders, + const nsCString& requestMethod, const Maybe& uploadStream, + const bool& uploadStreamHasHeaders, const int16_t& priority, + const uint32_t& classOfService, const uint8_t& redirectionLimit, + const bool& allowSTS, const uint32_t& thirdPartyFlags, + const bool& doResumeAt, const uint64_t& startPos, const nsCString& entityID, const bool& chooseApplicationCache, const nsCString& appCacheClientID, const bool& allowSpdy, const bool& allowAltSvc, const bool& beConservative, const uint32_t& tlsFlags, const Maybe& aLoadInfoArgs, @@ -424,6 +432,10 @@ bool HttpChannelParent::DoAsyncOpen( nsCOMPtr docUri = DeserializeURI(aDocURI); nsCOMPtr apiRedirectToUri = DeserializeURI(aAPIRedirectToURI); nsCOMPtr topWindowUri = DeserializeURI(aTopWindowURI); + nsCOMPtr contentBlockingAllowListPrincipal = + (aContentBlockingAllowListPrincipal.type() != PrincipalInfo::T__None) + ? PrincipalInfoToPrincipal(aContentBlockingAllowListPrincipal) + : nullptr; LOG(("HttpChannelParent RecvAsyncOpen [this=%p uri=%s, gid=%" PRIu64 " topwinid=%" PRIx64 "]\n", @@ -490,6 +502,11 @@ bool HttpChannelParent::DoAsyncOpen( MOZ_ASSERT(NS_SUCCEEDED(rv)); } + if (contentBlockingAllowListPrincipal) { + httpChannel->SetContentBlockingAllowListPrincipal( + contentBlockingAllowListPrincipal); + } + if (aLoadFlags != nsIRequest::LOAD_NORMAL) httpChannel->SetLoadFlags(aLoadFlags); diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index e2569729cc74..068310903627 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -151,17 +151,18 @@ class HttpChannelParent final : public nsIInterfaceRequestor, const URIParams& uri, const Maybe& originalUri, const Maybe& docUri, nsIReferrerInfo* aReferrerInfo, const Maybe& internalRedirectUri, - const Maybe& topWindowUri, const uint32_t& loadFlags, - const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, - const Maybe& uploadStream, const bool& uploadStreamHasHeaders, - const int16_t& priority, const uint32_t& classOfService, - const uint8_t& redirectionLimit, const bool& allowSTS, - const uint32_t& thirdPartyFlags, const bool& doResumeAt, - const uint64_t& startPos, const nsCString& entityID, - const bool& chooseApplicationCache, const nsCString& appCacheClientID, - const bool& allowSpdy, const bool& allowAltSvc, - const bool& beConservative, const uint32_t& tlsFlags, - const Maybe& aLoadInfoArgs, + const Maybe& topWindowUri, + const PrincipalInfo& aContentBlockingAllowListPrincipal, + const uint32_t& loadFlags, const RequestHeaderTuples& requestHeaders, + const nsCString& requestMethod, const Maybe& uploadStream, + const bool& uploadStreamHasHeaders, const int16_t& priority, + const uint32_t& classOfService, const uint8_t& redirectionLimit, + const bool& allowSTS, const uint32_t& thirdPartyFlags, + const bool& doResumeAt, const uint64_t& startPos, + const nsCString& entityID, const bool& chooseApplicationCache, + const nsCString& appCacheClientID, const bool& allowSpdy, + const bool& allowAltSvc, const bool& beConservative, + const uint32_t& tlsFlags, const Maybe& aLoadInfoArgs, const Maybe& aSynthesizedResponseHead, const nsCString& aSecurityInfoSerialization, const uint32_t& aCacheKey, const uint64_t& aRequestContextID, diff --git a/netwerk/protocol/http/nsIHttpChannelInternal.idl b/netwerk/protocol/http/nsIHttpChannelInternal.idl index 97bca909f6db..9285918ad05a 100644 --- a/netwerk/protocol/http/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl @@ -305,6 +305,12 @@ interface nsIHttpChannelInternal : nsISupports */ [must_use] readonly attribute nsIURI topWindowURI; + /** + * The content blocking allow list principal belonging to the document + * loaded in the top-level window that's associated with this channel. + */ + [must_use, noscript] readonly attribute nsIPrincipal contentBlockingAllowListPrincipal; + /** * Set top-level window URI to this channel only when the topWindowURI * is null and there is no window associated to this channel. diff --git a/toolkit/components/antitracking/AntiTrackingCommon.cpp b/toolkit/components/antitracking/AntiTrackingCommon.cpp index 8fc3ec879ecf..966b230f0c42 100644 --- a/toolkit/components/antitracking/AntiTrackingCommon.cpp +++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp @@ -1955,6 +1955,49 @@ nsresult AntiTrackingCommon::IsOnContentBlockingAllowList( principal.forget(aPrincipal); } +/* static */ void +AntiTrackingCommon::RecomputeContentBlockingAllowListPrincipal( + nsIURI* aURIBeingLoaded, const OriginAttributes& aAttrs, + nsIPrincipal** aPrincipal) { + MOZ_ASSERT(aPrincipal); + + auto returnInputArgument = MakeScopeExit([&] { *aPrincipal = nullptr; }); + + // Take the host/port portion so we can allowlist by site. Also ignore the + // scheme, since users who put sites on the allowlist probably don't expect + // allowlisting to depend on scheme. + nsAutoCString escaped(NS_LITERAL_CSTRING("https://")); + nsAutoCString temp; + nsresult rv = aURIBeingLoaded->GetHostPort(temp); + // view-source URIs will be handled by the next block. + if (NS_FAILED(rv) && !aURIBeingLoaded->SchemeIs("view-source")) { + // Normal for some loads, no need to print a warning + return; + } + + // GetHostPort returns an empty string (with a success error code) for file:// + // URIs. + if (temp.IsEmpty()) { + return; + } + escaped.Append(temp); + + nsCOMPtr uri; + rv = NS_NewURI(getter_AddRefs(uri), escaped); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + nsCOMPtr principal = + BasePrincipal::CreateContentPrincipal(uri, aAttrs); + if (NS_WARN_IF(!principal)) { + return; + } + + returnInputArgument.release(); + principal.forget(aPrincipal); +} + /* static */ void AntiTrackingCommon::NotifyBlockingDecision(nsIChannel* aChannel, BlockingDecision aDecision, diff --git a/toolkit/components/antitracking/AntiTrackingCommon.h b/toolkit/components/antitracking/AntiTrackingCommon.h index 4c99bf89723f..92d41af744f7 100644 --- a/toolkit/components/antitracking/AntiTrackingCommon.h +++ b/toolkit/components/antitracking/AntiTrackingCommon.h @@ -22,6 +22,8 @@ class nsPIDOMWindowInner; namespace mozilla { +class OriginAttributes; + class AntiTrackingCommon final { public: // Normally we would include PContentParent.h here and use the @@ -141,6 +143,10 @@ class AntiTrackingCommon final { static void ComputeContentBlockingAllowListPrincipal( nsIPrincipal* aDocumentPrincipal, nsIPrincipal** aPrincipal); + static void RecomputeContentBlockingAllowListPrincipal( + nsIURI* aURIBeingLoaded, const OriginAttributes& aAttrs, + nsIPrincipal** aPrincipal); + enum class BlockingDecision { eBlock, eAllow,