diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index 968f5e2b0f2f..90de4ec2ae18 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -324,6 +324,7 @@ OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs mFirstPartyDomain = aAttrs.mFirstPartyDomain; } +/* static */ bool OriginAttributes::IsFirstPartyEnabled() { diff --git a/caps/BasePrincipal.h b/caps/BasePrincipal.h index 689bce901f90..6a526e636873 100644 --- a/caps/BasePrincipal.h +++ b/caps/BasePrincipal.h @@ -61,13 +61,13 @@ public: void SetFromGenericAttributes(const GenericOriginAttributes& aAttrs); + // check if "privacy.firstparty.isolate" is enabled. + static bool IsFirstPartyEnabled(); + protected: OriginAttributes() {} explicit OriginAttributes(const OriginAttributesDictionary& aOther) : OriginAttributesDictionary(aOther) {} - - // check if "privacy.firstparty.isolate" is enabled. - bool IsFirstPartyEnabled(); }; class PrincipalOriginAttributes; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 646378f0f366..5940d45aa44e 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -3573,8 +3573,54 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem, return false; } - if (static_cast(targetDS.get())->GetOriginAttributes() != - static_cast(accessingDS.get())->GetOriginAttributes()) { + nsCOMPtr accessingRoot; + aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot)); + nsCOMPtr accessingRootDS = do_QueryInterface(accessingRoot); + + nsCOMPtr targetRoot; + aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot)); + nsCOMPtr targetRootDS = do_QueryInterface(targetRoot); + + DocShellOriginAttributes targetOA = + static_cast(targetDS.get())->GetOriginAttributes(); + DocShellOriginAttributes accessingOA = + static_cast(accessingDS.get())->GetOriginAttributes(); + + // When the first party isolation is on, the top-level docShell may not have + // the firstPartyDomain in its originAttributes, but its document will have + // it. So we get the firstPartyDomain from the nodePrincipal of the document + // before we compare the originAttributes. + if (OriginAttributes::IsFirstPartyEnabled()) { + if (accessingDS == accessingRootDS && + aAccessingItem->ItemType() == nsIDocShellTreeItem::typeContent && + !accessingDS->GetIsMozBrowserOrApp()) { + + nsCOMPtr accessingDoc = aAccessingItem->GetDocument(); + + if (accessingDoc) { + nsCOMPtr accessingPrincipal = accessingDoc->NodePrincipal(); + + accessingOA.mFirstPartyDomain = + BasePrincipal::Cast(accessingPrincipal)->OriginAttributesRef().mFirstPartyDomain; + } + } + + if (targetDS == targetRootDS && + aTargetItem->ItemType() == nsIDocShellTreeItem::typeContent && + !targetDS->GetIsMozBrowserOrApp()) { + + nsCOMPtr targetDoc = aAccessingItem->GetDocument(); + + if (targetDoc) { + nsCOMPtr targetPrincipal = targetDoc->NodePrincipal(); + + targetOA.mFirstPartyDomain = + BasePrincipal::Cast(targetPrincipal)->OriginAttributesRef().mFirstPartyDomain; + } + } + } + + if (targetOA != accessingOA) { return false; } @@ -3584,10 +3630,6 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem, return false; } - - nsCOMPtr accessingRoot; - aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot)); - if (aTargetItem == accessingRoot) { // A frame can navigate its root. return true; @@ -3605,9 +3647,6 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem, parent.swap(target); } while (target); - nsCOMPtr targetRoot; - aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot)); - if (aTargetItem != targetRoot) { // target is a subframe, not in accessor's frame hierarchy, and all its // ancestors have origins different from that of the accessor. Don't