Loading dom/base/nsContentUtils.cpp +82 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,8 @@ #include "mozilla/dom/UserActivation.h" #include "mozilla/dom/ViewTransition.h" #include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowGlobalChild.h" #include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WorkerCommon.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" Loading Loading @@ -2378,6 +2380,86 @@ nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal( return contentPrin; } // static bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource, mozilla::dom::BrowsingContext* aTarget, nsIPrincipal* aDocumentPrincipal, bool aConsiderOpener) { MOZ_DIAGNOSTIC_ASSERT( aSource->Group() == aTarget->Group(), "Source and target BrowsingContexts must be in the same group"); if (aSource->Group() != aTarget->Group()) { return false; } auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool { // NOTE: This code previously checked for a file scheme using // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer // use GetURI, as it has been deprecated, and it makes more sense to take // advantage of the pre-computed origin, which will already use the // innermost URI (bug 1810619) nsAutoCString origin, scheme; return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin)) && NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme)) && scheme == "file"_ns; }; // A frame can navigate itself and its own root. if (aTarget == aSource || aTarget == aSource->Top()) { return true; } // If the target frame doesn't yet have a WindowContext, start checking // principals from its direct ancestor instead. It would inherit its principal // from this document upon creation. dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext(); if (!initialWc) { initialWc = aTarget->GetParentWindowContext(); } // A frame can navigate any frame with a same-origin ancestor. bool isFileDocument = isFileScheme(aDocumentPrincipal); for (dom::WindowContext* wc = initialWc; wc; wc = wc->GetParentWindowContext()) { nsIPrincipal* documentPrincipal = nullptr; if (XRE_IsParentProcess()) { dom::WindowGlobalParent* wgp = wc->Canonical(); if (!wgp) { continue; } documentPrincipal = wgp->DocumentPrincipal(); } else { dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild(); if (!wgc) { continue; // not same-origin. } documentPrincipal = wgc->DocumentPrincipal(); } if (aDocumentPrincipal->Equals(documentPrincipal)) { return true; } // Not strictly equal, special case if both are file: URIs. // // file: URIs are considered the same domain for the purpose of frame // navigation, regardless of script accessibility (bug 420425). if (isFileDocument && isFileScheme(documentPrincipal)) { return true; } } // If the target is a top-level document, a frame can navigate it // when the source is allowed to navigate the opener if (aConsiderOpener && !aTarget->GetParent()) { if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) { return CanNavigate(aSource, opener, aDocumentPrincipal, false); } } return false; } // static bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) { nsAutoCString scheme; Loading dom/base/nsContentUtils.h +8 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ enum class ShadowRootMode : uint8_t; class ShadowRoot; struct StructuredSerializeOptions; class TrustedHTMLOrString; class WindowContext; class WorkerPrivate; enum class ElementCallbackType; enum class ReferrerPolicy : uint8_t; Loading Loading @@ -950,6 +951,13 @@ class nsContentUtils { nsIContent* aContent, const nsAString& aAttrValue, nsIPrincipal* aSubjectPrincipal); /* Returns true if browser allowed to navigate aTarget BrowsingContext using * aSource BrowsingContext and aDocumentPrincipal */ static bool CanNavigate(mozilla::dom::BrowsingContext* aSource, mozilla::dom::BrowsingContext* aTarget, nsIPrincipal* aDocumentPrincipal, bool aConsiderOpener); /** * Returns true if the given string is guaranteed to be treated as an absolute * URL, rather than a relative URL. In practice, this means any complete URL Loading dom/ipc/WindowGlobalChild.cpp +2 −60 Original line number Diff line number Diff line Loading @@ -718,66 +718,8 @@ bool WindowGlobalChild::SameOriginWithTop() { // Bug 1810619: Crash at null in nsDocShell::ValidateOrigin bool WindowGlobalChild::CanNavigate(dom::BrowsingContext* aTarget, bool aConsiderOpener) { MOZ_DIAGNOSTIC_ASSERT(WindowContext()->Group() == aTarget->Group(), "A WindowGlobalChild should never try to navigate a " "BrowsingContext from another group"); auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool { // NOTE: This code previously checked for a file scheme using // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer // use GetURI, as it has been deprecated, and it makes more sense to take // advantage of the pre-computed origin, which will already use the // innermost URI (bug 1810619) nsAutoCString origin, scheme; return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin)) && NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme)) && scheme == "file"_ns; }; // A frame can navigate itself and its own root. if (aTarget == BrowsingContext() || aTarget == BrowsingContext()->Top()) { return true; } // If the target frame doesn't yet have a WindowContext, start checking // principals from its direct ancestor instead. It would inherit its principal // from this document upon creation. dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext(); if (!initialWc) { initialWc = aTarget->GetParentWindowContext(); } // A frame can navigate any frame with a same-origin ancestor. bool isFileDocument = isFileScheme(DocumentPrincipal()); for (dom::WindowContext* wc = initialWc; wc; wc = wc->GetParentWindowContext()) { dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild(); if (!wgc) { continue; // out-of process, so not same-origin. } if (DocumentPrincipal()->Equals(wgc->DocumentPrincipal())) { return true; } // Not strictly equal, special case if both are file: URIs. // // file: URIs are considered the same domain for the purpose of frame // navigation, regardless of script accessibility (bug 420425). if (isFileDocument && isFileScheme(wgc->DocumentPrincipal())) { return true; } } // If the target is a top-level document, a frame can navigate it if it can // navigate its opener. if (aConsiderOpener && !aTarget->GetParent()) { if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) { return CanNavigate(opener, false); } } return false; return nsContentUtils::CanNavigate(BrowsingContext(), aTarget, DocumentPrincipal(), aConsiderOpener); } // FindWithName follows the rules for choosing a browsing context, Loading dom/ipc/WindowGlobalParent.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -338,13 +338,16 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI( RefPtr<CanonicalBrowsingContext> targetBC = aTargetBC.get_canonical(); // FIXME: For cross-process loads, we should double check CanAccess() for the // source browsing context in the parent process. if (targetBC->Group() != BrowsingContext()->Group()) { return IPC_FAIL(this, "Illegal cross-group BrowsingContext load"); } if (!nsContentUtils::CanNavigate(BrowsingContext(), targetBC.get(), DocumentPrincipal(), true)) { return IPC_FAIL(this, "Illegal cross-process load attempt (!CanNavigate())"); } // FIXME: We should really initiate the load in the parent before bouncing // back down to the child. Loading Loading @@ -372,13 +375,16 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvInternalLoad( RefPtr<CanonicalBrowsingContext> targetBC = aLoadState->TargetBrowsingContext().get_canonical(); // FIXME: For cross-process loads, we should double check CanAccess() for the // source browsing context in the parent process. if (targetBC->Group() != BrowsingContext()->Group()) { return IPC_FAIL(this, "Illegal cross-group BrowsingContext load"); } if (!nsContentUtils::CanNavigate(BrowsingContext(), targetBC.get(), DocumentPrincipal(), true)) { return IPC_FAIL(this, "Illegal cross-process load attempt (!CanNavigate())"); } // FIXME: We should really initiate the load in the parent before bouncing // back down to the child. Loading Loading
dom/base/nsContentUtils.cpp +82 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,8 @@ #include "mozilla/dom/UserActivation.h" #include "mozilla/dom/ViewTransition.h" #include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowGlobalChild.h" #include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WorkerCommon.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" Loading Loading @@ -2378,6 +2380,86 @@ nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal( return contentPrin; } // static bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource, mozilla::dom::BrowsingContext* aTarget, nsIPrincipal* aDocumentPrincipal, bool aConsiderOpener) { MOZ_DIAGNOSTIC_ASSERT( aSource->Group() == aTarget->Group(), "Source and target BrowsingContexts must be in the same group"); if (aSource->Group() != aTarget->Group()) { return false; } auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool { // NOTE: This code previously checked for a file scheme using // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer // use GetURI, as it has been deprecated, and it makes more sense to take // advantage of the pre-computed origin, which will already use the // innermost URI (bug 1810619) nsAutoCString origin, scheme; return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin)) && NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme)) && scheme == "file"_ns; }; // A frame can navigate itself and its own root. if (aTarget == aSource || aTarget == aSource->Top()) { return true; } // If the target frame doesn't yet have a WindowContext, start checking // principals from its direct ancestor instead. It would inherit its principal // from this document upon creation. dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext(); if (!initialWc) { initialWc = aTarget->GetParentWindowContext(); } // A frame can navigate any frame with a same-origin ancestor. bool isFileDocument = isFileScheme(aDocumentPrincipal); for (dom::WindowContext* wc = initialWc; wc; wc = wc->GetParentWindowContext()) { nsIPrincipal* documentPrincipal = nullptr; if (XRE_IsParentProcess()) { dom::WindowGlobalParent* wgp = wc->Canonical(); if (!wgp) { continue; } documentPrincipal = wgp->DocumentPrincipal(); } else { dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild(); if (!wgc) { continue; // not same-origin. } documentPrincipal = wgc->DocumentPrincipal(); } if (aDocumentPrincipal->Equals(documentPrincipal)) { return true; } // Not strictly equal, special case if both are file: URIs. // // file: URIs are considered the same domain for the purpose of frame // navigation, regardless of script accessibility (bug 420425). if (isFileDocument && isFileScheme(documentPrincipal)) { return true; } } // If the target is a top-level document, a frame can navigate it // when the source is allowed to navigate the opener if (aConsiderOpener && !aTarget->GetParent()) { if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) { return CanNavigate(aSource, opener, aDocumentPrincipal, false); } } return false; } // static bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) { nsAutoCString scheme; Loading
dom/base/nsContentUtils.h +8 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ enum class ShadowRootMode : uint8_t; class ShadowRoot; struct StructuredSerializeOptions; class TrustedHTMLOrString; class WindowContext; class WorkerPrivate; enum class ElementCallbackType; enum class ReferrerPolicy : uint8_t; Loading Loading @@ -950,6 +951,13 @@ class nsContentUtils { nsIContent* aContent, const nsAString& aAttrValue, nsIPrincipal* aSubjectPrincipal); /* Returns true if browser allowed to navigate aTarget BrowsingContext using * aSource BrowsingContext and aDocumentPrincipal */ static bool CanNavigate(mozilla::dom::BrowsingContext* aSource, mozilla::dom::BrowsingContext* aTarget, nsIPrincipal* aDocumentPrincipal, bool aConsiderOpener); /** * Returns true if the given string is guaranteed to be treated as an absolute * URL, rather than a relative URL. In practice, this means any complete URL Loading
dom/ipc/WindowGlobalChild.cpp +2 −60 Original line number Diff line number Diff line Loading @@ -718,66 +718,8 @@ bool WindowGlobalChild::SameOriginWithTop() { // Bug 1810619: Crash at null in nsDocShell::ValidateOrigin bool WindowGlobalChild::CanNavigate(dom::BrowsingContext* aTarget, bool aConsiderOpener) { MOZ_DIAGNOSTIC_ASSERT(WindowContext()->Group() == aTarget->Group(), "A WindowGlobalChild should never try to navigate a " "BrowsingContext from another group"); auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool { // NOTE: This code previously checked for a file scheme using // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer // use GetURI, as it has been deprecated, and it makes more sense to take // advantage of the pre-computed origin, which will already use the // innermost URI (bug 1810619) nsAutoCString origin, scheme; return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin)) && NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme)) && scheme == "file"_ns; }; // A frame can navigate itself and its own root. if (aTarget == BrowsingContext() || aTarget == BrowsingContext()->Top()) { return true; } // If the target frame doesn't yet have a WindowContext, start checking // principals from its direct ancestor instead. It would inherit its principal // from this document upon creation. dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext(); if (!initialWc) { initialWc = aTarget->GetParentWindowContext(); } // A frame can navigate any frame with a same-origin ancestor. bool isFileDocument = isFileScheme(DocumentPrincipal()); for (dom::WindowContext* wc = initialWc; wc; wc = wc->GetParentWindowContext()) { dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild(); if (!wgc) { continue; // out-of process, so not same-origin. } if (DocumentPrincipal()->Equals(wgc->DocumentPrincipal())) { return true; } // Not strictly equal, special case if both are file: URIs. // // file: URIs are considered the same domain for the purpose of frame // navigation, regardless of script accessibility (bug 420425). if (isFileDocument && isFileScheme(wgc->DocumentPrincipal())) { return true; } } // If the target is a top-level document, a frame can navigate it if it can // navigate its opener. if (aConsiderOpener && !aTarget->GetParent()) { if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) { return CanNavigate(opener, false); } } return false; return nsContentUtils::CanNavigate(BrowsingContext(), aTarget, DocumentPrincipal(), aConsiderOpener); } // FindWithName follows the rules for choosing a browsing context, Loading
dom/ipc/WindowGlobalParent.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -338,13 +338,16 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI( RefPtr<CanonicalBrowsingContext> targetBC = aTargetBC.get_canonical(); // FIXME: For cross-process loads, we should double check CanAccess() for the // source browsing context in the parent process. if (targetBC->Group() != BrowsingContext()->Group()) { return IPC_FAIL(this, "Illegal cross-group BrowsingContext load"); } if (!nsContentUtils::CanNavigate(BrowsingContext(), targetBC.get(), DocumentPrincipal(), true)) { return IPC_FAIL(this, "Illegal cross-process load attempt (!CanNavigate())"); } // FIXME: We should really initiate the load in the parent before bouncing // back down to the child. Loading Loading @@ -372,13 +375,16 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvInternalLoad( RefPtr<CanonicalBrowsingContext> targetBC = aLoadState->TargetBrowsingContext().get_canonical(); // FIXME: For cross-process loads, we should double check CanAccess() for the // source browsing context in the parent process. if (targetBC->Group() != BrowsingContext()->Group()) { return IPC_FAIL(this, "Illegal cross-group BrowsingContext load"); } if (!nsContentUtils::CanNavigate(BrowsingContext(), targetBC.get(), DocumentPrincipal(), true)) { return IPC_FAIL(this, "Illegal cross-process load attempt (!CanNavigate())"); } // FIXME: We should really initiate the load in the parent before bouncing // back down to the child. Loading