From ce16e42511399716524edfefa160964a1ae10c3a Mon Sep 17 00:00:00 2001 From: Andreas Farre Date: Thu, 20 Jun 2024 13:22:41 +0000 Subject: [PATCH] Bug 1890748 - Move responsibility of FeaturePolicy initialization to nsILoadInfo. r=freddyb,necko-reviewers,jesup,dom-core,sefeng, a=dmeehan Differential Revision: https://phabricator.services.mozilla.com/D207140 --- docshell/base/CanonicalBrowsingContext.cpp | 16 ++- docshell/base/CanonicalBrowsingContext.h | 10 +- docshell/base/nsDocShell.cpp | 8 +- dom/base/Document.cpp | 102 +++++++++--------- dom/base/Document.h | 3 +- dom/base/nsObjectLoadingContent.cpp | 5 +- dom/html/HTMLIFrameElement.cpp | 4 +- dom/ipc/ContentParent.cpp | 4 +- dom/ipc/ContentParent.h | 2 +- dom/ipc/DOMTypes.ipdlh | 10 -- dom/ipc/PContent.ipdl | 4 +- dom/ipc/PWindowGlobal.ipdl | 4 - dom/ipc/WindowGlobalChild.cpp | 6 -- dom/ipc/WindowGlobalChild.h | 8 -- dom/ipc/WindowGlobalParent.cpp | 3 - dom/security/featurepolicy/FeaturePolicy.cpp | 35 ++++++ dom/security/featurepolicy/FeaturePolicy.h | 17 +++ .../featurepolicy/FeaturePolicyUtils.cpp | 75 +++++-------- .../featurepolicy/FeaturePolicyUtils.h | 8 +- dom/xslt/xslt/txMozillaXMLOutput.cpp | 1 + ipc/glue/BackgroundUtils.cpp | 14 ++- netwerk/base/LoadInfo.cpp | 11 ++ netwerk/base/LoadInfo.h | 7 ++ netwerk/base/TRRLoadInfo.cpp | 9 ++ netwerk/base/nsILoadInfo.idl | 12 +++ netwerk/ipc/DocumentLoadListener.cpp | 3 + netwerk/ipc/NeckoChannelParams.ipdlh | 4 + 27 files changed, 220 insertions(+), 165 deletions(-) diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp index beae24fbd122..b59a70321b6c 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp @@ -2779,12 +2779,8 @@ void CanonicalBrowsingContext::CancelSessionStoreUpdate() { } void CanonicalBrowsingContext::SetContainerFeaturePolicy( - FeaturePolicy* aContainerFeaturePolicy) { - mContainerFeaturePolicy = aContainerFeaturePolicy; - - if (WindowGlobalParent* current = GetCurrentWindowGlobal()) { - Unused << current->SendSetContainerFeaturePolicy(mContainerFeaturePolicy); - } + Maybe&& aContainerFeaturePolicyInfo) { + mContainerFeaturePolicyInfo = std::move(aContainerFeaturePolicyInfo); } void CanonicalBrowsingContext::SetCrossGroupOpenerId(uint64_t aOpenerId) { @@ -3202,15 +3198,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CanonicalBrowsingContext, if (tmp->mSessionHistory) { tmp->mSessionHistory->SetBrowsingContext(nullptr); } - NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionHistory, mContainerFeaturePolicy, - mCurrentBrowserParent, mWebProgress, + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionHistory, mCurrentBrowserParent, + mWebProgress, mSessionStoreSessionStorageUpdateTimer) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CanonicalBrowsingContext, BrowsingContext) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionHistory, mContainerFeaturePolicy, - mCurrentBrowserParent, mWebProgress, + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionHistory, mCurrentBrowserParent, + mWebProgress, mSessionStoreSessionStorageUpdateTimer) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/docshell/base/CanonicalBrowsingContext.h b/docshell/base/CanonicalBrowsingContext.h index ccbdf9ed9655..3355c0e006b8 100644 --- a/docshell/base/CanonicalBrowsingContext.h +++ b/docshell/base/CanonicalBrowsingContext.h @@ -10,6 +10,7 @@ #include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/MediaControlKeySource.h" #include "mozilla/dom/BrowsingContextWebProgress.h" +#include "mozilla/dom/FeaturePolicy.h" #include "mozilla/dom/ProcessIsolation.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/SessionHistoryEntry.h" @@ -314,9 +315,10 @@ class CanonicalBrowsingContext final : public BrowsingContext { void ResetScalingZoom(); - void SetContainerFeaturePolicy(FeaturePolicy* aContainerFeaturePolicy); - FeaturePolicy* GetContainerFeaturePolicy() const { - return mContainerFeaturePolicy; + void SetContainerFeaturePolicy( + Maybe&& aContainerFeaturePolicyInfo); + const Maybe& GetContainerFeaturePolicy() const { + return mContainerFeaturePolicyInfo; } void SetRestoreData(SessionStoreRestoreData* aData, ErrorResult& aError); @@ -581,7 +583,7 @@ class CanonicalBrowsingContext final : public BrowsingContext { nsCOMPtr mDocShellProgressBridge; RefPtr mStatusFilter; - RefPtr mContainerFeaturePolicy; + Maybe mContainerFeaturePolicyInfo; friend class BrowserSessionStore; WeakPtr& GetSessionStoreFormDataRef() { diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 0dbf1c30f810..5133fd683789 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -6586,8 +6586,6 @@ nsresult nsDocShell::CreateAboutBlankDocumentViewer( // after being set here. blankDoc->SetSandboxFlags(sandboxFlags); - blankDoc->InitFeaturePolicy(); - // create a content viewer for us and the new document docFactory->CreateInstanceForDocument( NS_ISUPPORTS_CAST(nsIDocShell*, this), blankDoc, "view", @@ -6605,6 +6603,12 @@ nsresult nsDocShell::CreateAboutBlankDocumentViewer( /* aLocationFlags */ 0); rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; } + + if (Element* embedderElement = blankDoc->GetEmbedderElement()) { + blankDoc->InitFeaturePolicy(AsVariant(embedderElement)); + } else { + blankDoc->InitFeaturePolicy(AsVariant(Nothing{})); + } } } diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 81d2db6d1dc4..c6cb09e1955d 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -180,6 +180,7 @@ #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLCollectionBinding.h" #include "mozilla/dom/HTMLDialogElement.h" +#include "mozilla/dom/HTMLEmbedElement.h" #include "mozilla/dom/HTMLFormElement.h" #include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/dom/HTMLImageElement.h" @@ -187,6 +188,7 @@ #include "mozilla/dom/HTMLLinkElement.h" #include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/dom/HTMLMetaElement.h" +#include "mozilla/dom/HTMLObjectElement.h" #include "mozilla/dom/HTMLSharedElement.h" #include "mozilla/dom/HTMLTextAreaElement.h" #include "mozilla/dom/ImageTracker.h" @@ -3869,74 +3871,68 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { return NS_OK; } -static Document* GetInProcessParentDocumentFrom(BrowsingContext* aContext) { - BrowsingContext* parentContext = aContext->GetParent(); - if (!parentContext) { +static FeaturePolicy* GetFeaturePolicyFromElement(Element* aElement) { + if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(aElement)) { + return iframe->FeaturePolicy(); + } + + if (!HTMLObjectElement::FromNodeOrNull(aElement) && + !HTMLEmbedElement::FromNodeOrNull(aElement)) { return nullptr; } - WindowContext* windowContext = parentContext->GetCurrentWindowContext(); - if (!windowContext) { - return nullptr; - } - - return windowContext->GetDocument(); + return aElement->OwnerDoc()->FeaturePolicy(); } -already_AddRefed Document::GetParentFeaturePolicy() { - BrowsingContext* browsingContext = GetBrowsingContext(); - if (!browsingContext) { - return nullptr; - } - if (!browsingContext->IsContentSubframe()) { - return nullptr; - } - - HTMLIFrameElement* iframe = - HTMLIFrameElement::FromNodeOrNull(browsingContext->GetEmbedderElement()); - if (iframe) { - return do_AddRef(iframe->FeaturePolicy()); - } - - if (XRE_IsParentProcess()) { - return do_AddRef(browsingContext->Canonical()->GetContainerFeaturePolicy()); - } - - if (Document* parentDocument = - GetInProcessParentDocumentFrom(browsingContext)) { - return do_AddRef(parentDocument->FeaturePolicy()); - } - - WindowContext* windowContext = browsingContext->GetCurrentWindowContext(); - if (!windowContext) { - return nullptr; - } - - WindowGlobalChild* child = windowContext->GetWindowGlobalChild(); - if (!child) { - return nullptr; - } - - return do_AddRef(child->GetContainerFeaturePolicy()); -} - -void Document::InitFeaturePolicy() { +void Document::InitFeaturePolicy( + const Variant& + aContainerFeaturePolicy) { MOZ_ASSERT(mFeaturePolicy, "we should have FeaturePolicy created"); mFeaturePolicy->ResetDeclaredPolicy(); mFeaturePolicy->SetDefaultOrigin(NodePrincipal()); - RefPtr parentPolicy = GetParentFeaturePolicy(); - if (parentPolicy) { - // Let's inherit the policy from the parent HTMLIFrameElement if it exists. - mFeaturePolicy->InheritPolicy(parentPolicy); - mFeaturePolicy->SetSrcOrigin(parentPolicy->GetSrcOrigin()); + RefPtr featurePolicy = mFeaturePolicy; + aContainerFeaturePolicy.match( + [](const Nothing&) {}, + [featurePolicy](const FeaturePolicyInfo& aContainerFeaturePolicy) { + // Let's inherit the policy from the possibly cross-origin container. + featurePolicy->InheritPolicy(aContainerFeaturePolicy); + featurePolicy->SetSrcOrigin(aContainerFeaturePolicy.mSrcOrigin); + }, + [featurePolicy](Element* aContainer) { + // Let's inherit the policy from the parent container element if it + // exists. + if (RefPtr containerFeaturePolicy = + GetFeaturePolicyFromElement(aContainer)) { + featurePolicy->InheritPolicy(containerFeaturePolicy); + featurePolicy->SetSrcOrigin(containerFeaturePolicy->GetSrcOrigin()); + } + }); +} + +Element* GetEmbedderElementFrom(BrowsingContext* aBrowsingContext) { + if (!aBrowsingContext) { + return nullptr; } + if (!aBrowsingContext->IsContentSubframe()) { + return nullptr; + } + + return aBrowsingContext->GetEmbedderElement(); } nsresult Document::InitFeaturePolicy(nsIChannel* aChannel) { - InitFeaturePolicy(); + nsCOMPtr loadInfo = aChannel->LoadInfo(); + if (Element* embedderElement = GetEmbedderElementFrom(GetBrowsingContext())) { + InitFeaturePolicy(AsVariant(embedderElement)); + } else if (Maybe featurePolicyContainer = + loadInfo->GetContainerFeaturePolicyInfo()) { + InitFeaturePolicy(AsVariant(*featurePolicyContainer)); + } else { + InitFeaturePolicy(AsVariant(Nothing{})); + } // We don't want to parse the http Feature-Policy header if this pref is off. if (!StaticPrefs::dom_security_featurePolicy_header_enabled()) { diff --git a/dom/base/Document.h b/dom/base/Document.h index 0d8ccd7baff6..7eea29947d91 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -1503,7 +1503,8 @@ class Document : public nsINode, void DoNotifyPossibleTitleChange(); - void InitFeaturePolicy(); + void InitFeaturePolicy(const Variant& + aContainerFeaturePolicy); nsresult InitFeaturePolicy(nsIChannel* aChannel); void EnsureNotEnteringAndExitFullscreen(); diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index ab87c58e8713..f97621e44754 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1838,7 +1838,8 @@ void nsObjectLoadingContent::MaybeStoreCrossOriginFeaturePolicy() { FeaturePolicy* featurePolicy = el->OwnerDoc()->FeaturePolicy(); - if (ContentChild* cc = ContentChild::GetSingleton()) { - Unused << cc->SendSetContainerFeaturePolicy(browsingContext, featurePolicy); + if (ContentChild* cc = ContentChild::GetSingleton(); cc && featurePolicy) { + Unused << cc->SendSetContainerFeaturePolicy( + browsingContext, Some(featurePolicy->ToFeaturePolicyInfo())); } } diff --git a/dom/html/HTMLIFrameElement.cpp b/dom/html/HTMLIFrameElement.cpp index 97363ccbff68..b54bb267b921 100644 --- a/dom/html/HTMLIFrameElement.cpp +++ b/dom/html/HTMLIFrameElement.cpp @@ -255,8 +255,8 @@ void HTMLIFrameElement::MaybeStoreCrossOriginFeaturePolicy() { } if (ContentChild* cc = ContentChild::GetSingleton()) { - Unused << cc->SendSetContainerFeaturePolicy(browsingContext, - mFeaturePolicy); + Unused << cc->SendSetContainerFeaturePolicy( + browsingContext, Some(mFeaturePolicy->ToFeaturePolicyInfo())); } } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 59bee0676a6f..7c335a228415 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -8238,13 +8238,13 @@ IPCResult ContentParent::RecvFOGData(ByteBuf&& buf) { mozilla::ipc::IPCResult ContentParent::RecvSetContainerFeaturePolicy( const MaybeDiscardedBrowsingContext& aContainerContext, - FeaturePolicy* aContainerFeaturePolicy) { + MaybeFeaturePolicyInfo&& aContainerFeaturePolicyInfo) { if (aContainerContext.IsNullOrDiscarded()) { return IPC_OK(); } auto* context = aContainerContext.get_canonical(); - context->SetContainerFeaturePolicy(aContainerFeaturePolicy); + context->SetContainerFeaturePolicy(std::move(aContainerFeaturePolicyInfo)); return IPC_OK(); } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 25804538584b..1c644dbe9afc 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -1389,7 +1389,7 @@ class ContentParent final : public PContentParent, mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy( const MaybeDiscardedBrowsingContext& aContainerContext, - FeaturePolicy* aContainerFeaturePolicy); + MaybeFeaturePolicyInfo&& aContainerFeaturePolicyInfo); mozilla::ipc::IPCResult RecvGetSystemIcon(nsIURI* aURI, GetSystemIconResolver&& aResolver); diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index c2404a5ee26c..1749721c7200 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -132,16 +132,6 @@ struct FrameScriptInfo bool runInGlobalScope; }; -struct FeaturePolicyInfo -{ - nsString[] inheritedDeniedFeatureNames; - nsString[] attributeEnabledFeatureNames; - nsString declaredString; - nullable nsIPrincipal defaultOrigin; - nullable nsIPrincipal selfOrigin; - nullable nsIPrincipal srcOrigin; -}; - /** * The information required to complete a window creation request. */ diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 238663ad746c..1c961af7dc13 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -154,7 +154,7 @@ using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHi using mozilla::media::MediaCodecsSupported from "MediaCodecsSupport.h"; using mozilla::RemoteDecodeIn from "mozilla/RemoteDecoderManagerChild.h"; using mozilla::dom::PerformanceTimingData from "mozilla/dom/PerformanceTiming.h"; -[RefCounted] using mozilla::dom::FeaturePolicy from "mozilla/dom/FeaturePolicy.h"; +using mozilla::dom::MaybeFeaturePolicyInfo from "mozilla/dom/FeaturePolicy.h"; using mozilla::dom::Wireframe from "mozilla/dom/DocumentBinding.h"; using mozilla::PerfStats::MetricMask from "mozilla/PerfStats.h"; [RefCounted] using class nsIX509Cert from "nsIX509Cert.h"; @@ -1958,7 +1958,7 @@ child: parent: async SetContainerFeaturePolicy(MaybeDiscardedBrowsingContext aContainerContext, - nullable FeaturePolicy aContainerFeaturePolicy); + MaybeFeaturePolicyInfo aContainerFeaturePolicyInfo); // Obtain an icon from the system widget toolkit, in nsIconDecoder // format. Not supported (or needed) on all platforms; see the diff --git a/dom/ipc/PWindowGlobal.ipdl b/dom/ipc/PWindowGlobal.ipdl index 37e6206e385c..88f8b4107017 100644 --- a/dom/ipc/PWindowGlobal.ipdl +++ b/dom/ipc/PWindowGlobal.ipdl @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include "mozilla/dom/DocShellMessageUtils.h"; -include "mozilla/dom/FeaturePolicyUtils.h"; include "mozilla/dom/IdentityCredentialSerializationHelpers.h"; include "mozilla/dom/PermissionMessageUtils.h"; include "mozilla/dom/SessionStoreMessageUtils.h"; @@ -34,7 +33,6 @@ using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h"; [RefCounted] using class nsITransportSecurityInfo from "nsITransportSecurityInfo.h"; using mozilla::UseCounters from "mozilla/UseCounter.h"; using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h"; -[RefCounted] using mozilla::dom::FeaturePolicy from "mozilla/dom/FeaturePolicy.h"; [RefCounted] using mozilla::dom::SessionStoreRestoreData from "mozilla/dom/SessionStoreRestoreData.h"; using mozilla::dom::IdentityCredentialInit from "mozilla/dom/IdentityCredentialBinding.h"; using mozilla::dom::IdentityCredentialRequestOptions from "mozilla/dom/IdentityCredentialBinding.h"; @@ -89,8 +87,6 @@ child: */ async ResetScalingZoom(); - async SetContainerFeaturePolicy(nullable FeaturePolicy aContainerFeaturePolicy); - async RestoreDocShellState(DocShellRestoreState aState) returns (bool success); diff --git a/dom/ipc/WindowGlobalChild.cpp b/dom/ipc/WindowGlobalChild.cpp index 7fb95709ee89..f567085cdfb8 100644 --- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -513,12 +513,6 @@ mozilla::ipc::IPCResult WindowGlobalChild::RecvResetScalingZoom() { return IPC_OK(); } -mozilla::ipc::IPCResult WindowGlobalChild::RecvSetContainerFeaturePolicy( - dom::FeaturePolicy* aContainerFeaturePolicy) { - mContainerFeaturePolicy = aContainerFeaturePolicy; - return IPC_OK(); -} - mozilla::ipc::IPCResult WindowGlobalChild::RecvRestoreDocShellState( const dom::sessionstore::DocShellRestoreState& aState, RestoreDocShellStateResolver&& aResolve) { diff --git a/dom/ipc/WindowGlobalChild.h b/dom/ipc/WindowGlobalChild.h index 107b3f471d2d..7adfa00a3437 100644 --- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -21,7 +21,6 @@ class nsDocShell; namespace mozilla::dom { class BrowsingContext; -class FeaturePolicy; class WindowContext; class WindowGlobalParent; class JSWindowActorChild; @@ -144,10 +143,6 @@ class WindowGlobalChild final : public WindowGlobalActor, JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - dom::FeaturePolicy* GetContainerFeaturePolicy() const { - return mContainerFeaturePolicy; - } - void UnblockBFCacheFor(BFCacheStatus aStatus); void BlockBFCacheFor(BFCacheStatus aStatus); @@ -189,9 +184,6 @@ class WindowGlobalChild final : public WindowGlobalActor, mozilla::ipc::IPCResult RecvResetScalingZoom(); - mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy( - dom::FeaturePolicy* aContainerFeaturePolicy); - mozilla::ipc::IPCResult RecvRestoreDocShellState( const dom::sessionstore::DocShellRestoreState& aState, RestoreDocShellStateResolver&& aResolve); diff --git a/dom/ipc/WindowGlobalParent.cpp b/dom/ipc/WindowGlobalParent.cpp index ffbb0b270df1..5af387a8a843 100644 --- a/dom/ipc/WindowGlobalParent.cpp +++ b/dom/ipc/WindowGlobalParent.cpp @@ -179,9 +179,6 @@ void WindowGlobalParent::Init() { if (!BrowsingContext()->IsDiscarded()) { MOZ_ALWAYS_SUCCEEDS( BrowsingContext()->SetCurrentInnerWindowId(InnerWindowId())); - - Unused << SendSetContainerFeaturePolicy( - BrowsingContext()->GetContainerFeaturePolicy()); } if (BrowsingContext()->IsTopContent()) { diff --git a/dom/security/featurepolicy/FeaturePolicy.cpp b/dom/security/featurepolicy/FeaturePolicy.cpp index cb5c1ea44a3c..d71ac1cc5fa6 100644 --- a/dom/security/featurepolicy/FeaturePolicy.cpp +++ b/dom/security/featurepolicy/FeaturePolicy.cpp @@ -6,10 +6,12 @@ #include "FeaturePolicy.h" #include "mozilla/BasePrincipal.h" +#include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/Feature.h" #include "mozilla/dom/FeaturePolicyBinding.h" #include "mozilla/dom/FeaturePolicyParser.h" #include "mozilla/dom/FeaturePolicyUtils.h" +#include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/StaticPrefs_dom.h" #include "nsContentUtils.h" #include "nsNetUtil.h" @@ -69,6 +71,30 @@ void FeaturePolicy::InheritPolicy(FeaturePolicy* aParentPolicy) { }); } +void FeaturePolicy::InheritPolicy( + const FeaturePolicyInfo& aContainerFeaturePolicyInfo) { + // We create a temporary FeaturePolicy from the FeaturePolicyInfo to be able + // to re-use the inheriting functionality from FeaturePolicy. + RefPtr featurePolicy = new dom::FeaturePolicy(nullptr); + featurePolicy->SetDefaultOrigin(aContainerFeaturePolicyInfo.mDefaultOrigin); + featurePolicy->SetInheritedDeniedFeatureNames( + aContainerFeaturePolicyInfo.mInheritedDeniedFeatureNames); + + const auto& declaredString = aContainerFeaturePolicyInfo.mDeclaredString; + if (aContainerFeaturePolicyInfo.mSelfOrigin && !declaredString.IsEmpty()) { + featurePolicy->SetDeclaredPolicy(nullptr, declaredString, + aContainerFeaturePolicyInfo.mSelfOrigin, + aContainerFeaturePolicyInfo.mSrcOrigin); + } + + for (const auto& featureName : + aContainerFeaturePolicyInfo.mAttributeEnabledFeatureNames) { + featurePolicy->MaybeSetAllowedPolicy(featureName); + } + + InheritPolicy(featurePolicy); +} + void FeaturePolicy::SetInheritedDeniedFeature(const nsAString& aFeatureName) { MOZ_ASSERT(!HasInheritedDeniedFeature(aFeatureName)); mInheritedDeniedFeatureNames.AppendElement(aFeatureName); @@ -331,4 +357,13 @@ void FeaturePolicy::MaybeSetAllowedPolicy(const nsAString& aFeatureName) { mAttributeEnabledFeatureNames.AppendElement(aFeatureName); } +FeaturePolicyInfo FeaturePolicy::ToFeaturePolicyInfo() const { + return {mInheritedDeniedFeatureNames.Clone(), + mAttributeEnabledFeatureNames.Clone(), + mDeclaredString, + mDefaultOrigin, + mSelfOrigin, + mSrcOrigin}; +} + } // namespace mozilla::dom diff --git a/dom/security/featurepolicy/FeaturePolicy.h b/dom/security/featurepolicy/FeaturePolicy.h index 65f525974902..841b9e0f0444 100644 --- a/dom/security/featurepolicy/FeaturePolicy.h +++ b/dom/security/featurepolicy/FeaturePolicy.h @@ -56,12 +56,24 @@ class nsINode; namespace mozilla::dom { class Document; +class BrowsingContext; class Feature; template class Optional; class FeaturePolicyUtils; +struct FeaturePolicyInfo final { + CopyableTArray mInheritedDeniedFeatureNames; + CopyableTArray mAttributeEnabledFeatureNames; + nsString mDeclaredString; + nsCOMPtr mDefaultOrigin; + nsCOMPtr mSelfOrigin; + nsCOMPtr mSrcOrigin; +}; + +using MaybeFeaturePolicyInfo = Maybe; + class FeaturePolicy final : public nsISupports, public nsWrapperCache { friend class FeaturePolicyUtils; @@ -85,6 +97,9 @@ class FeaturePolicy final : public nsISupports, public nsWrapperCache { // Inherits the policy from the 'parent' context if it exists. void InheritPolicy(FeaturePolicy* aParentFeaturePolicy); + // Inherits the policy from the 'parent' context if it exists. + void InheritPolicy(const FeaturePolicyInfo& aContainerFeaturePolicyInfo); + // Sets the declarative part of the policy. This can be from the HTTP header // or for the 'allow' HTML attribute. void SetDeclaredPolicy(mozilla::dom::Document* aDocument, @@ -154,6 +169,8 @@ class FeaturePolicy final : public nsISupports, public nsWrapperCache { nsIPrincipal* GetSelfOrigin() const { return mSelfOrigin; } nsIPrincipal* GetSrcOrigin() const { return mSrcOrigin; } + FeaturePolicyInfo ToFeaturePolicyInfo() const; + private: ~FeaturePolicy() = default; diff --git a/dom/security/featurepolicy/FeaturePolicyUtils.cpp b/dom/security/featurepolicy/FeaturePolicyUtils.cpp index 4e0bb92e0aec..8423a62a6a84 100644 --- a/dom/security/featurepolicy/FeaturePolicyUtils.cpp +++ b/dom/security/featurepolicy/FeaturePolicyUtils.cpp @@ -7,8 +7,9 @@ #include "FeaturePolicyUtils.h" #include "nsIOService.h" -#include "mozilla/dom/DOMTypes.h" #include "mozilla/ipc/IPDLParamTraits.h" +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/PermissionMessageUtils.h" #include "mozilla/dom/FeaturePolicyViolationReportBody.h" #include "mozilla/dom/ReportingUtils.h" #include "mozilla/StaticPrefs_dom.h" @@ -248,66 +249,46 @@ void FeaturePolicyUtils::ReportViolation(Document* aDocument, } // namespace dom namespace ipc { -void IPDLParamTraits::Write(IPC::MessageWriter* aWriter, - IProtocol* aActor, - dom::FeaturePolicy* aParam) { - if (!aParam) { - WriteIPDLParam(aWriter, aActor, false); - return; - } - WriteIPDLParam(aWriter, aActor, true); - - dom::FeaturePolicyInfo info; - info.defaultOrigin() = aParam->DefaultOrigin(); - info.selfOrigin() = aParam->GetSelfOrigin(); - info.srcOrigin() = aParam->GetSrcOrigin(); - - info.declaredString() = aParam->DeclaredString(); - info.inheritedDeniedFeatureNames() = - aParam->InheritedDeniedFeatureNames().Clone(); - info.attributeEnabledFeatureNames() = - aParam->AttributeEnabledFeatureNames().Clone(); - - WriteIPDLParam(aWriter, aActor, info); +void IPDLParamTraits::Write( + IPC::MessageWriter* aWriter, IProtocol* aActor, + const dom::FeaturePolicyInfo& aParam) { + WriteIPDLParam(aWriter, aActor, aParam.mInheritedDeniedFeatureNames); + WriteIPDLParam(aWriter, aActor, aParam.mAttributeEnabledFeatureNames); + WriteIPDLParam(aWriter, aActor, aParam.mDeclaredString); + WriteIPDLParam(aWriter, aActor, aParam.mDefaultOrigin); + WriteIPDLParam(aWriter, aActor, aParam.mSelfOrigin); + WriteIPDLParam(aWriter, aActor, aParam.mSrcOrigin); } -bool IPDLParamTraits::Read( +bool IPDLParamTraits::Read( IPC::MessageReader* aReader, IProtocol* aActor, - RefPtr* aResult) { - *aResult = nullptr; - bool notnull = false; - if (!ReadIPDLParam(aReader, aActor, ¬null)) { + dom::FeaturePolicyInfo* aResult) { + if (!ReadIPDLParam(aReader, aActor, &aResult->mInheritedDeniedFeatureNames)) { return false; } - if (!notnull) { - return true; - } - - dom::FeaturePolicyInfo info; - if (!ReadIPDLParam(aReader, aActor, &info)) { + if (!ReadIPDLParam(aReader, aActor, + &aResult->mAttributeEnabledFeatureNames)) { return false; } - // Note that we only do IPC for feature policy to inherit policy from parent - // to child document. That does not need to bind feature policy with a node. - RefPtr featurePolicy = new dom::FeaturePolicy(nullptr); - featurePolicy->SetDefaultOrigin(info.defaultOrigin()); - featurePolicy->SetInheritedDeniedFeatureNames( - info.inheritedDeniedFeatureNames()); - - const auto& declaredString = info.declaredString(); - if (info.selfOrigin() && !declaredString.IsEmpty()) { - featurePolicy->SetDeclaredPolicy(nullptr, declaredString, info.selfOrigin(), - info.srcOrigin()); + if (!ReadIPDLParam(aReader, aActor, &aResult->mDeclaredString)) { + return false; } - for (auto& featureName : info.attributeEnabledFeatureNames()) { - featurePolicy->MaybeSetAllowedPolicy(featureName); + if (!ReadIPDLParam(aReader, aActor, &aResult->mDefaultOrigin)) { + return false; + } + + if (!ReadIPDLParam(aReader, aActor, &aResult->mSelfOrigin)) { + return false; + } + + if (!ReadIPDLParam(aReader, aActor, &aResult->mSrcOrigin)) { + return false; } - *aResult = std::move(featurePolicy); return true; } } // namespace ipc diff --git a/dom/security/featurepolicy/FeaturePolicyUtils.h b/dom/security/featurepolicy/FeaturePolicyUtils.h index 380806433d67..ceb60923c00f 100644 --- a/dom/security/featurepolicy/FeaturePolicyUtils.h +++ b/dom/security/featurepolicy/FeaturePolicyUtils.h @@ -7,7 +7,6 @@ #ifndef mozilla_dom_FeaturePolicyUtils_h #define mozilla_dom_FeaturePolicyUtils_h -#include "nsString.h" #include #include "mozilla/dom/FeaturePolicy.h" @@ -79,12 +78,13 @@ template struct IPDLParamTraits; template <> -struct IPDLParamTraits { +struct IPDLParamTraits { static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor, - mozilla::dom::FeaturePolicy* aParam); + const mozilla::dom::FeaturePolicyInfo& aParam); static bool Read(IPC::MessageReader* aReader, IProtocol* aActor, - RefPtr* aResult); + dom::FeaturePolicyInfo* aResult); }; + } // namespace ipc } // namespace mozilla diff --git a/dom/xslt/xslt/txMozillaXMLOutput.cpp b/dom/xslt/xslt/txMozillaXMLOutput.cpp index 3ef89d31a4f3..75f9f4e69a35 100644 --- a/dom/xslt/xslt/txMozillaXMLOutput.cpp +++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp @@ -6,6 +6,7 @@ #include "txMozillaXMLOutput.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/FeaturePolicy.h" #include "nsIDocShell.h" #include "nsIScriptElement.h" #include "nsCharsetSource.h" diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index eb1e46fb4225..40fae18bdeb3 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -962,10 +962,11 @@ void LoadInfoToParentLoadInfoForwarder( aLoadInfo->GetServiceWorkerTaintingSynthesized(), aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetAllowListFutureDocumentsCreatedFromThisRedirectChain(), - cookieJarSettingsArgs, aLoadInfo->GetRequestBlockingReason(), - aLoadInfo->GetStoragePermission(), overriddenFingerprintingSettingsArg, - aLoadInfo->GetIsMetaRefresh(), isThirdPartyContextToTopWindow, - aLoadInfo->GetIsInThirdPartyContext(), unstrippedURI); + cookieJarSettingsArgs, aLoadInfo->GetContainerFeaturePolicyInfo(), + aLoadInfo->GetRequestBlockingReason(), aLoadInfo->GetStoragePermission(), + overriddenFingerprintingSettingsArg, aLoadInfo->GetIsMetaRefresh(), + isThirdPartyContextToTopWindow, aLoadInfo->GetIsInThirdPartyContext(), + unstrippedURI); } nsresult MergeParentLoadInfoForwarder( @@ -1071,6 +1072,11 @@ nsresult MergeParentLoadInfoForwarder( rv = aLoadInfo->SetUnstrippedURI(aForwarderArgs.unstrippedURI()); NS_ENSURE_SUCCESS(rv, rv); + if (aForwarderArgs.containerFeaturePolicyInfo()) { + aLoadInfo->SetContainerFeaturePolicyInfo( + *aForwarderArgs.containerFeaturePolicyInfo()); + } + return NS_OK; } diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 7a9f8905b6a6..5ff1c5ad8b26 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -14,6 +14,7 @@ #include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/ClientSource.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/Performance.h" #include "mozilla/dom/PerformanceStorage.h" #include "mozilla/dom/BrowserChild.h" @@ -606,6 +607,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) mChannelCreationOriginalURI(rhs.mChannelCreationOriginalURI), mCookieJarSettings(rhs.mCookieJarSettings), mCspToInherit(rhs.mCspToInherit), + mContainerFeaturePolicyInfo(rhs.mContainerFeaturePolicyInfo), mTriggeringRemoteType(rhs.mTriggeringRemoteType), mSandboxedNullPrincipalID(rhs.mSandboxedNullPrincipalID), mClientInfo(rhs.mClientInfo), @@ -2371,6 +2373,15 @@ already_AddRefed LoadInfo::GetCspToInherit() { return cspToInherit.forget(); } +Maybe LoadInfo::GetContainerFeaturePolicyInfo() { + return mContainerFeaturePolicyInfo; +} + +void LoadInfo::SetContainerFeaturePolicyInfo( + const FeaturePolicyInfo& aContainerFeaturePolicyInfo) { + mContainerFeaturePolicyInfo = Some(aContainerFeaturePolicyInfo); +} + nsIInterceptionInfo* LoadInfo::InterceptionInfo() { return mInterceptionInfo; } void LoadInfo::SetInterceptionInfo(nsIInterceptionInfo* aInfo) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index a8631b09b267..e6badeeee816 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -7,6 +7,7 @@ #ifndef mozilla_LoadInfo_h #define mozilla_LoadInfo_h +#include "mozilla/dom/FeaturePolicy.h" #include "nsIContentSecurityPolicy.h" #include "nsIInterceptionInfo.h" #include "nsILoadInfo.h" @@ -195,6 +196,11 @@ class LoadInfo final : public nsILoadInfo { mIsThirdPartyContextToTopWindow.reset(); } + void SetContinerFeaturePolicy( + const Maybe& aContainerFeaturePolicy) { + mContainerFeaturePolicyInfo = aContainerFeaturePolicy; + } + #ifdef DEBUG void MarkOverriddenFingerprintingSettingsAsSet() { mOverriddenFingerprintingSettingsIsSet = true; @@ -299,6 +305,7 @@ class LoadInfo final : public nsILoadInfo { nsCOMPtr mCSPEventListener; nsCOMPtr mCookieJarSettings; nsCOMPtr mCspToInherit; + Maybe mContainerFeaturePolicyInfo; nsCString mTriggeringRemoteType; nsID mSandboxedNullPrincipalID; diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp index 920e7623a7f9..48560a8b3be4 100644 --- a/netwerk/base/TRRLoadInfo.cpp +++ b/netwerk/base/TRRLoadInfo.cpp @@ -6,6 +6,8 @@ #include "TRRLoadInfo.h" #include "mozilla/dom/ClientSource.h" +#include "mozilla/dom/FeaturePolicy.h" +#include "mozilla/dom/DOMTypes.h" #include "nsContentUtils.h" #include "nsIRedirectHistoryEntry.h" @@ -724,6 +726,13 @@ already_AddRefed TRRLoadInfo::GetCspToInherit() { return nullptr; } +Maybe TRRLoadInfo::GetContainerFeaturePolicyInfo() { + return Nothing(); +} + +void TRRLoadInfo::SetContainerFeaturePolicyInfo( + const FeaturePolicyInfo& aContainerFeaturePolicyInfo) {} + NS_IMETHODIMP TRRLoadInfo::GetHttpsOnlyStatus(uint32_t* aHttpsOnlyStatus) { return NS_ERROR_NOT_IMPLEMENTED; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index ddfcb223e612..8ff5e556c986 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -32,6 +32,7 @@ namespace mozilla { namespace dom { class ClientInfo; class ClientSource; +struct FeaturePolicyInfo; class PerformanceStorage; class ServiceWorkerDescriptor; } // namespace dom @@ -56,6 +57,8 @@ native OriginAttributes(mozilla::OriginAttributes); [ptr] native PerformanceStoragePtr(mozilla::dom::PerformanceStorage); native LoadTainting(mozilla::LoadTainting); native CSPRef(already_AddRefed); + native MaybeFeaturePolicyInfo(mozilla::Maybe); +[ref] native const_FeaturePolicyInfoRef(const mozilla::dom::FeaturePolicyInfo); typedef unsigned long nsSecurityFlags; @@ -1333,6 +1336,15 @@ interface nsILoadInfo : nsISupports [notxpcom,nostdcall] CSPRef GetPreloadCsp(); [notxpcom,nostdcall] CSPRef GetCspToInherit(); + /** + * The possibly cross-origin container feature policy required to + * initialize the feature policy of a document load. + */ + [noscript, nostdcall, notxpcom] + MaybeFeaturePolicyInfo GetContainerFeaturePolicyInfo(); + [noscript, nostdcall, notxpcom] + void SetContainerFeaturePolicyInfo(in const_FeaturePolicyInfoRef aContainerFeaturePolicy); + /** * The service worker and fetch specifications require returning the * exact tainting level of the Response passed to FetchEvent.respondWith(). diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp index dd162b82902c..dfd80e8867ec 100644 --- a/netwerk/ipc/DocumentLoadListener.cpp +++ b/netwerk/ipc/DocumentLoadListener.cpp @@ -640,6 +640,9 @@ auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState, OriginAttributes attrs; loadingContext->GetOriginAttributes(attrs); + aLoadInfo->SetContinerFeaturePolicy( + loadingContext->GetContainerFeaturePolicy()); + mLoadIdentifier = aLoadState->GetLoadIdentifier(); // See description of mFileName in nsDocShellLoadState.h mIsDownload = !aLoadState->FileName().IsVoid(); diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 62b272e99c24..2b3fddd54c9a 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -15,6 +15,7 @@ include DOMTypes; include ProtocolTypes; include "mozilla/dom/FetchIPCTypes.h"; +include "mozilla/dom/FeaturePolicyUtils.h"; include "mozilla/dom/PropertyBagUtils.h"; include "mozilla/dom/ReferrerInfoUtils.h"; include "mozilla/ipc/URIUtils.h"; @@ -37,6 +38,7 @@ using nsILoadInfo::StoragePermissionState from "nsILoadInfo.h"; using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h"; using mozilla::dom::RequestMode from "mozilla/dom/RequestBinding.h"; using mozilla::net::LinkHeader from "nsNetUtil.h"; +using mozilla::dom::FeaturePolicyInfo from "mozilla/dom/FeaturePolicy.h"; namespace mozilla { namespace net { @@ -258,6 +260,8 @@ struct ParentLoadInfoForwarderArgs CookieJarSettingsArgs? cookieJarSettings; + FeaturePolicyInfo? containerFeaturePolicyInfo; + uint32_t requestBlockingReason; StoragePermissionState storagePermission;