Bug 1962710 - Part 2: Fire NavigateEvent for same document navigation. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D249241
This commit is contained in:
committed by
afarre@mozilla.com
parent
51b4a22fa0
commit
d2e41c93c1
@@ -8691,6 +8691,29 @@ bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
|
||||
aState.mNewURIHasRef;
|
||||
}
|
||||
|
||||
static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal,
|
||||
nsIURI* aCurrentURI,
|
||||
nsIURI* aNewURI) {
|
||||
if (!StaticPrefs::dom_security_setdocumenturi()) {
|
||||
return true;
|
||||
}
|
||||
nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI();
|
||||
if (aCurrentPrincipal->GetIsNullPrincipal()) {
|
||||
nsCOMPtr<nsIPrincipal> precursor =
|
||||
aCurrentPrincipal->GetPrecursorPrincipal();
|
||||
if (precursor) {
|
||||
principalURI = precursor->GetURI();
|
||||
}
|
||||
}
|
||||
|
||||
return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
|
||||
aNewURI) &&
|
||||
!nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
|
||||
aCurrentURI) &&
|
||||
!nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI,
|
||||
aNewURI);
|
||||
}
|
||||
|
||||
nsresult nsDocShell::HandleSameDocumentNavigation(
|
||||
nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
|
||||
bool& aSameDocument) {
|
||||
@@ -8707,13 +8730,6 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
|
||||
|
||||
RefPtr<Document> doc = GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
doc->DoNotifyPossibleTitleChange();
|
||||
|
||||
// Store the pending uninvoked directives if it is a same document navigation.
|
||||
// We need to set it here, in case the navigation happens before the document
|
||||
// has actually finished loading.
|
||||
doc->FragmentDirective()->SetTextDirectives(
|
||||
std::move(aState.mTextDirectives));
|
||||
|
||||
nsCOMPtr<nsIURI> currentURI = mCurrentURI;
|
||||
|
||||
@@ -8725,33 +8741,57 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
|
||||
("Upgraded URI to %s", newURI->GetSpecOrDefault().get()));
|
||||
}
|
||||
|
||||
if (StaticPrefs::dom_security_setdocumenturi()) {
|
||||
// check if aLoadState->URI(), principalURI, mCurrentURI are same origin
|
||||
// skip handling otherwise
|
||||
nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal();
|
||||
nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI();
|
||||
if (origPrincipal->GetIsNullPrincipal()) {
|
||||
nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal();
|
||||
if (precursor) {
|
||||
principalURI = precursor->GetURI();
|
||||
}
|
||||
}
|
||||
|
||||
if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
|
||||
newURI) ||
|
||||
nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
|
||||
mCurrentURI) ||
|
||||
nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI,
|
||||
// check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same
|
||||
// origin skip handling otherwise
|
||||
if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
|
||||
newURI)) {
|
||||
aSameDocument = false;
|
||||
MOZ_LOG(gSHLog, LogLevel::Debug,
|
||||
("nsDocShell[%p]: possible violation of the same origin policy "
|
||||
"during same document navigation",
|
||||
this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) {
|
||||
// https://html.spec.whatwg.org/#navigate-fragid
|
||||
// Step 1
|
||||
if (RefPtr<Navigation> navigation = window->Navigation()) {
|
||||
// Step 2
|
||||
RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
|
||||
mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr;
|
||||
// Step 3
|
||||
if (aLoadState->GetNavigationAPIState()) {
|
||||
destinationNavigationAPIState = aLoadState->GetNavigationAPIState();
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (jsapi.Init(window)) {
|
||||
RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
|
||||
// Step 4
|
||||
bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
|
||||
jsapi.cx(), aLoadState->GetNavigationType(), newURI,
|
||||
/* aIsSameDocument */ true,
|
||||
Some(aLoadState->UserNavigationInvolvement()), sourceElement,
|
||||
/* aFormDataEntryList */ Nothing(),
|
||||
/* aNavigationAPIState */ destinationNavigationAPIState,
|
||||
/* aClassicHistoryAPIState */ nullptr);
|
||||
|
||||
// Step 5
|
||||
if (!shouldContinue) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc->DoNotifyPossibleTitleChange();
|
||||
|
||||
// Store the pending uninvoked directives if it is a same document
|
||||
// navigation. We need to set it here, in case the navigation happens before
|
||||
// the document has actually finished loading.
|
||||
doc->FragmentDirective()->SetTextDirectives(
|
||||
std::move(aState.mTextDirectives));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aState.mSameExceptHashes) {
|
||||
bool sameExceptHashes = false;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/NavigationBinding.h"
|
||||
#include "mozilla/dom/WindowProxyHolder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCharsetSource.h"
|
||||
|
||||
@@ -755,6 +755,20 @@ bool nsDocShellLoadState::LoadIsFromSessionHistory() const {
|
||||
: !!mSHEntry;
|
||||
}
|
||||
|
||||
nsIStructuredCloneContainer* nsDocShellLoadState::GetNavigationAPIState()
|
||||
const {
|
||||
return mNavigationAPIState;
|
||||
}
|
||||
|
||||
void nsDocShellLoadState::SetNavigationAPIState(
|
||||
nsIStructuredCloneContainer* aNavigationAPIState) {
|
||||
mNavigationAPIState = aNavigationAPIState;
|
||||
}
|
||||
|
||||
NavigationType nsDocShellLoadState::GetNavigationType() const {
|
||||
return LoadReplace() ? NavigationType::Replace : NavigationType::Push;
|
||||
}
|
||||
|
||||
void nsDocShellLoadState::MaybeStripTrackerQueryStrings(
|
||||
BrowsingContext* aContext) {
|
||||
MOZ_ASSERT(aContext);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define nsDocShellLoadState_h__
|
||||
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/NavigationBinding.h"
|
||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||
#include "mozilla/dom/UserNavigationInvolvement.h"
|
||||
|
||||
@@ -195,6 +196,14 @@ class nsDocShellLoadState final {
|
||||
|
||||
bool LoadIsFromSessionHistory() const;
|
||||
|
||||
nsIStructuredCloneContainer* GetNavigationAPIState() const;
|
||||
|
||||
// This is used as the parameter for https://html.spec.whatwg.org/#navigate,
|
||||
// but it's currently missing. See bug 1966674
|
||||
void SetNavigationAPIState(nsIStructuredCloneContainer* aNavigationAPIState);
|
||||
|
||||
mozilla::dom::NavigationType GetNavigationType() const;
|
||||
|
||||
const nsString& Target() const;
|
||||
|
||||
void SetTarget(const nsAString& aTarget);
|
||||
@@ -552,6 +561,8 @@ class nsDocShellLoadState final {
|
||||
mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
|
||||
mLoadingSessionHistoryInfo;
|
||||
|
||||
nsCOMPtr<nsIStructuredCloneContainer> mNavigationAPIState;
|
||||
|
||||
// Target for load, like _content, _blank etc.
|
||||
nsString mTarget;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user