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;
|
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(
|
nsresult nsDocShell::HandleSameDocumentNavigation(
|
||||||
nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
|
nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
|
||||||
bool& aSameDocument) {
|
bool& aSameDocument) {
|
||||||
@@ -8707,13 +8730,6 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
|
|||||||
|
|
||||||
RefPtr<Document> doc = GetDocument();
|
RefPtr<Document> doc = GetDocument();
|
||||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
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;
|
nsCOMPtr<nsIURI> currentURI = mCurrentURI;
|
||||||
|
|
||||||
@@ -8725,33 +8741,57 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
|
|||||||
("Upgraded URI to %s", newURI->GetSpecOrDefault().get()));
|
("Upgraded URI to %s", newURI->GetSpecOrDefault().get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StaticPrefs::dom_security_setdocumenturi()) {
|
// check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same
|
||||||
// check if aLoadState->URI(), principalURI, mCurrentURI are same origin
|
// origin skip handling otherwise
|
||||||
// skip handling otherwise
|
if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
|
||||||
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,
|
|
||||||
newURI)) {
|
newURI)) {
|
||||||
aSameDocument = false;
|
|
||||||
MOZ_LOG(gSHLog, LogLevel::Debug,
|
MOZ_LOG(gSHLog, LogLevel::Debug,
|
||||||
("nsDocShell[%p]: possible violation of the same origin policy "
|
("nsDocShell[%p]: possible violation of the same origin policy "
|
||||||
"during same document navigation",
|
"during same document navigation",
|
||||||
this));
|
this));
|
||||||
return NS_OK;
|
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
|
#ifdef DEBUG
|
||||||
if (aState.mSameExceptHashes) {
|
if (aState.mSameExceptHashes) {
|
||||||
bool sameExceptHashes = false;
|
bool sameExceptHashes = false;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "mozilla/dom/BrowsingContext.h"
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
#include "mozilla/dom/WindowProxyHolder.h"
|
#include "mozilla/dom/WindowProxyHolder.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsCharsetSource.h"
|
#include "nsCharsetSource.h"
|
||||||
|
|||||||
@@ -755,6 +755,20 @@ bool nsDocShellLoadState::LoadIsFromSessionHistory() const {
|
|||||||
: !!mSHEntry;
|
: !!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(
|
void nsDocShellLoadState::MaybeStripTrackerQueryStrings(
|
||||||
BrowsingContext* aContext) {
|
BrowsingContext* aContext) {
|
||||||
MOZ_ASSERT(aContext);
|
MOZ_ASSERT(aContext);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define nsDocShellLoadState_h__
|
#define nsDocShellLoadState_h__
|
||||||
|
|
||||||
#include "mozilla/dom/BrowsingContext.h"
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/dom/UserNavigationInvolvement.h"
|
#include "mozilla/dom/UserNavigationInvolvement.h"
|
||||||
|
|
||||||
@@ -195,6 +196,14 @@ class nsDocShellLoadState final {
|
|||||||
|
|
||||||
bool LoadIsFromSessionHistory() const;
|
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;
|
const nsString& Target() const;
|
||||||
|
|
||||||
void SetTarget(const nsAString& aTarget);
|
void SetTarget(const nsAString& aTarget);
|
||||||
@@ -552,6 +561,8 @@ class nsDocShellLoadState final {
|
|||||||
mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
|
mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
|
||||||
mLoadingSessionHistoryInfo;
|
mLoadingSessionHistoryInfo;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStructuredCloneContainer> mNavigationAPIState;
|
||||||
|
|
||||||
// Target for load, like _content, _blank etc.
|
// Target for load, like _content, _blank etc.
|
||||||
nsString mTarget;
|
nsString mTarget;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user