From af192f668f53a09b5f89839903f4c7eb3f3c0c35 Mon Sep 17 00:00:00 2001 From: "evilpies@gmail.com" Date: Mon, 2 Oct 2017 11:05:33 -0700 Subject: [PATCH] Bug 1305237 LoadInfo changes to include all ancestors principals and window IDs, r=bz MozReview-Commit-ID: ADVtxjSQjk5 --HG-- extra : rebase_source : 6e0ddf49328d7ae71937b7bbe5e5bea736c49bef --- docshell/base/nsDocShell.h | 24 +++++++++++++++++++++ dom/base/nsDocument.cpp | 1 + dom/base/nsFrameLoader.cpp | 12 ++++++++++- dom/base/nsIDocument.h | 11 ++++++++++ ipc/glue/BackgroundUtils.cpp | 20 +++++++++++++++++ netwerk/base/LoadInfo.cpp | 24 +++++++++++++++++++++ netwerk/base/LoadInfo.h | 4 ++++ netwerk/base/nsILoadInfo.idl | 32 ++++++++++++++++++++++++++++ netwerk/ipc/NeckoChannelParams.ipdlh | 8 +++++++ 9 files changed, 135 insertions(+), 1 deletion(-) diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 42f703f58b01..226226112982 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -329,6 +329,28 @@ public: mAncestorPrincipals = mozilla::Move(aAncestorPrincipals); } + /** + * Get the list of ancestor outerWindowIDs for this docshell. The list is meant + * to be the list of outer window IDs that correspond to the ancestorPrincipals + * above. For each ancestor principal, we store the parent window ID. + */ + const nsTArray& AncestorOuterWindowIDs() const + { + return mAncestorOuterWindowIDs; + } + + /** + * Set the list of ancestor outer window IDs for this docshell. We call this + * from frameloader as well in order to keep the array matched with the + * ancestor principals. + * + * This method steals the data from the passed-in array. + */ + void SetAncestorOuterWindowIDs(nsTArray&& aAncestorOuterWindowIDs) + { + mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs); + } + private: bool CanSetOriginAttributes(); @@ -1135,6 +1157,8 @@ private: // Our list of ancestor principals. nsTArray> mAncestorPrincipals; + // Our list of ancestor outerWindowIDs. + nsTArray mAncestorOuterWindowIDs; // Separate function to do the actual name (i.e. not _top, _self etc.) // searching for FindItemWithName. diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 1aa056278917..323dfed3ea70 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -4969,6 +4969,7 @@ nsIDocument::SetContainer(nsDocShell* aContainer) } mAncestorPrincipals = aContainer->AncestorPrincipals(); + mAncestorOuterWindowIDs = aContainer->AncestorOuterWindowIDs(); } nsISupports* diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 187e6d0b4def..4839a7d6ebdb 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2711,14 +2711,24 @@ nsFrameLoader::MaybeCreateDocShell() nsDocShell::Cast(mDocShell)->SetOriginAttributes(attrs); + // Typically there will be a window, however for some cases such as printing + // the document is cloned with a docshell that has no window. We check + // IsStaticDocument to ensure we don't try to gather ancestors for those cases. if (!mDocShell->GetIsMozBrowser() && - parentType == mDocShell->ItemType()) { + parentType == mDocShell->ItemType() && + !doc->IsStaticDocument()) { // Propagate through the ancestor principals. nsTArray> ancestorPrincipals; // Make a copy, so we can modify it. ancestorPrincipals = doc->AncestorPrincipals(); ancestorPrincipals.InsertElementAt(0, doc->NodePrincipal()); nsDocShell::Cast(mDocShell)->SetAncestorPrincipals(Move(ancestorPrincipals)); + + // Repeat for outer window IDs. + nsTArray ancestorOuterWindowIDs; + ancestorOuterWindowIDs = doc->AncestorOuterWindowIDs(); + ancestorOuterWindowIDs.InsertElementAt(0, doc->GetWindow()->WindowID()); + nsDocShell::Cast(mDocShell)->SetAncestorOuterWindowIDs(Move(ancestorOuterWindowIDs)); } ReallyLoadFrameScripts(); diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index eeffe405ca12..8bc88782b11b 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -464,6 +464,15 @@ public: return mAncestorPrincipals; } + /** + * Get the list of ancestor outerWindowIDs for a document that correspond to + * the ancestor principals (see above for more details). + */ + const nsTArray& AncestorOuterWindowIDs() const + { + return mAncestorOuterWindowIDs; + } + /** * Return the LoadGroup for the document. May return null. */ @@ -3616,6 +3625,8 @@ protected: // List of ancestor principals. This is set at the point a document // is connected to a docshell and not mutated thereafter. nsTArray> mAncestorPrincipals; + // List of ancestor outerWindowIDs that correspond to the ancestor principals. + nsTArray mAncestorOuterWindowIDs; // Restyle root for servo's style system. // diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index f9f5ede6d556..c0d7957ebf11 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -370,6 +370,13 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, NS_ENSURE_SUCCESS(rv, rv); } + nsTArray ancestorPrincipals; + ancestorPrincipals.SetCapacity(aLoadInfo->AncestorPrincipals().Length()); + for (const auto& principal : aLoadInfo->AncestorPrincipals()) { + rv = PrincipalToPrincipalInfo(principal, ancestorPrincipals.AppendElement()); + NS_ENSURE_SUCCESS(rv, rv); + } + *aOptionalLoadInfoArgs = LoadInfoArgs( loadingPrincipalInfo, @@ -395,6 +402,8 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, aLoadInfo->GetOriginAttributes(), redirectChainIncludingInternalRedirects, redirectChain, + ancestorPrincipals, + aLoadInfo->AncestorOuterWindowIDs(), aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), @@ -467,6 +476,15 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, redirectChain.AppendElement(redirectHistoryEntry.forget()); } + nsTArray> ancestorPrincipals; + ancestorPrincipals.SetCapacity(loadInfoArgs.ancestorPrincipals().Length()); + for (const PrincipalInfo& principalInfo : loadInfoArgs.ancestorPrincipals()) { + nsCOMPtr ancestorPrincipal = + PrincipalInfoToPrincipal(principalInfo, &rv); + NS_ENSURE_SUCCESS(rv, rv); + ancestorPrincipals.AppendElement(ancestorPrincipal.forget()); + } + nsCOMPtr loadInfo = new mozilla::LoadInfo(loadingPrincipal, triggeringPrincipal, @@ -491,6 +509,8 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, loadInfoArgs.originAttributes(), redirectChainIncludingInternalRedirects, redirectChain, + Move(ancestorPrincipals), + loadInfoArgs.ancestorOuterWindowIDs(), loadInfoArgs.corsUnsafeHeaders(), loadInfoArgs.forcePreflight(), loadInfoArgs.isPreflight(), diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 594df3474bdb..09350d580e63 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -118,6 +118,9 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, } mInnerWindowID = aLoadingContext->OwnerDoc()->InnerWindowID(); + mAncestorPrincipals = aLoadingContext->OwnerDoc()->AncestorPrincipals(); + mAncestorOuterWindowIDs = aLoadingContext->OwnerDoc()->AncestorOuterWindowIDs(); + MOZ_DIAGNOSTIC_ASSERT(mAncestorPrincipals.Length() == mAncestorOuterWindowIDs.Length()); // When the element being loaded is a frame, we choose the frame's window // for the window ID and the frame element's window as the parent @@ -277,6 +280,9 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsCOMPtr docShell = aOuterWindow->GetDocShell(); MOZ_ASSERT(docShell); mOriginAttributes = nsDocShell::Cast(docShell)->GetOriginAttributes(); + mAncestorPrincipals = nsDocShell::Cast(docShell)->AncestorPrincipals(); + mAncestorOuterWindowIDs = nsDocShell::Cast(docShell)->AncestorOuterWindowIDs(); + MOZ_DIAGNOSTIC_ASSERT(mAncestorPrincipals.Length() == mAncestorOuterWindowIDs.Length()); #ifdef DEBUG if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) { @@ -313,6 +319,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mRedirectChainIncludingInternalRedirects( rhs.mRedirectChainIncludingInternalRedirects) , mRedirectChain(rhs.mRedirectChain) + , mAncestorPrincipals(rhs.mAncestorPrincipals) + , mAncestorOuterWindowIDs(rhs.mAncestorOuterWindowIDs) , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders) , mForcePreflight(rhs.mForcePreflight) , mIsPreflight(rhs.mIsPreflight) @@ -346,6 +354,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, const OriginAttributes& aOriginAttributes, RedirectHistoryArray& aRedirectChainIncludingInternalRedirects, RedirectHistoryArray& aRedirectChain, + nsTArray>&& aAncestorPrincipals, + const nsTArray& aAncestorOuterWindowIDs, const nsTArray& aCorsUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, @@ -373,6 +383,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInitialSecurityCheckDone(aInitialSecurityCheckDone) , mIsThirdPartyContext(aIsThirdPartyContext) , mOriginAttributes(aOriginAttributes) + , mAncestorPrincipals(Move(aAncestorPrincipals)) + , mAncestorOuterWindowIDs(aAncestorOuterWindowIDs) , mCorsUnsafeHeaders(aCorsUnsafeHeaders) , mForcePreflight(aForcePreflight) , mIsPreflight(aIsPreflight) @@ -914,6 +926,18 @@ LoadInfo::RedirectChain() return mRedirectChain; } +const nsTArray>& +LoadInfo::AncestorPrincipals() +{ + return mAncestorPrincipals; +} + +const nsTArray& +LoadInfo::AncestorOuterWindowIDs() +{ + return mAncestorOuterWindowIDs; +} + void LoadInfo::SetCorsPreflightInfo(const nsTArray& aHeaders, bool aForcePreflight) diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 2f97d3276fe3..50140969cb31 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -115,6 +115,8 @@ private: const OriginAttributes& aOriginAttributes, RedirectHistoryArray& aRedirectChainIncludingInternalRedirects, RedirectHistoryArray& aRedirectChain, + nsTArray>&& aAncestorPrincipals, + const nsTArray& aAncestorOuterWindowIDs, const nsTArray& aUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, @@ -168,6 +170,8 @@ private: OriginAttributes mOriginAttributes; RedirectHistoryArray mRedirectChainIncludingInternalRedirects; RedirectHistoryArray mRedirectChain; + nsTArray> mAncestorPrincipals; + nsTArray mAncestorOuterWindowIDs; nsTArray mCorsUnsafeHeaders; bool mForcePreflight; bool mIsPreflight; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 1fcc33e5e579..91a8c8d6c8a7 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -23,6 +23,8 @@ interface nsIURI; native OriginAttributes(mozilla::OriginAttributes); [ref] native const_OriginAttributesRef(const mozilla::OriginAttributes); [ref] native StringArrayRef(const nsTArray); +[ref] native Uint64ArrayRef(const nsTArray); +[ref] native PrincipalArrayRef(const nsTArray>); typedef unsigned long nsSecurityFlags; @@ -642,6 +644,36 @@ interface nsILoadInfo : nsISupports [noscript, notxpcom, nostdcall, binaryname(RedirectChain)] nsIRedirectHistoryEntryArray binaryRedirectChain(); + /** + * An array of nsIPrincipals which stores the principals of the parent frames, + * not including the frame loading this request. The closest ancestor is at + * index zero and the top level ancestor is at the last index. + * + * The ancestorPrincipals[0] entry for an iframe load will be the principal of + * the iframe element's owner document. + * The ancestorPrincipals[0] entry for an image loaded in an iframe will be the + * principal of the iframe element's owner document. + * + * See nsIDocument::AncestorPrincipals for more information. + * + * Please note that this array has the same lifetime as the + * loadInfo object - use with caution! + */ + [noscript, notxpcom, nostdcall] + PrincipalArrayRef AncestorPrincipals(); + + + /** + * An array of outerWindowIDs which correspond to nsILoadInfo::AncestorPrincipals + * above. AncestorOuterWindowIDs[0] is the outerWindowID of the frame + * associated with the principal at ancestorPrincipals[0], and so forth. + * + * Please note that this array has the same lifetime as the + * loadInfo object - use with caution! + */ + [noscript, notxpcom, nostdcall] + Uint64ArrayRef AncestorOuterWindowIDs(); + /** * Sets the list of unsafe headers according to CORS spec, as well as * potentially forces a preflight. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index dd0c4f279db0..786c5017247e 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -59,6 +59,14 @@ struct LoadInfoArgs OriginAttributes originAttributes; RedirectHistoryEntryInfo[] redirectChainIncludingInternalRedirects; RedirectHistoryEntryInfo[] redirectChain; + + /** + * Ancestor data for use with the WebRequest API. + * See nsILoadInfo.idl for details. + */ + PrincipalInfo[] ancestorPrincipals; + uint64_t[] ancestorOuterWindowIDs; + nsCString[] corsUnsafeHeaders; bool forcePreflight; bool isPreflight;