Bug 1962710 - Part 3: Fire NavigateEvent for regular navigations. r=smaug,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D249242
This commit is contained in:
Andreas Farre
2025-05-19 09:01:13 +00:00
committed by afarre@mozilla.com
parent d2e41c93c1
commit e10114d313
12 changed files with 162 additions and 42 deletions

View File

@@ -7,6 +7,7 @@
#include "nsDocShell.h"
#include <algorithm>
#include "mozilla/dom/HTMLFormElement.h"
#ifdef XP_WIN
# include <process.h>
@@ -3930,7 +3931,7 @@ nsresult nsDocShell::ReloadNavigable(
if (!navigation->FirePushReplaceReloadNavigateEvent(
aCx, NavigationType::Reload, destinationURL,
/* aIsSameDocument */ false, Some(aUserInvolvement),
/* aSourceElement*/ nullptr, /* aFormDataEntryList */ Nothing{},
/* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr,
destinationNavigationAPIState,
/* aClassiCHistoryAPIState */ nullptr)) {
return NS_OK;
@@ -8772,7 +8773,7 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
jsapi.cx(), aLoadState->GetNavigationType(), newURI,
/* aIsSameDocument */ true,
Some(aLoadState->UserNavigationInvolvement()), sourceElement,
/* aFormDataEntryList */ Nothing(),
/* aFormDataEntryList */ nullptr,
/* aNavigationAPIState */ destinationNavigationAPIState,
/* aClassicHistoryAPIState */ nullptr);
@@ -9276,6 +9277,8 @@ uint32_t nsDocShell::GetLoadTypeForFormSubmission(
: LOAD_LINK;
}
// InternalLoad performs several of the steps from
// https://html.spec.whatwg.org/#navigate.
nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
Maybe<uint32_t> aCacheKey) {
MOZ_ASSERT(aLoadState, "need a load state!");
@@ -9485,6 +9488,52 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
if (mTiming && !isDownload) {
mTiming->NotifyBeforeUnload();
}
// The following steps are from https://html.spec.whatwg.org/#navigate
// Step 20
if (RefPtr<Document> document = GetDocument();
document &&
aLoadState->UserNavigationInvolvement() !=
UserNavigationInvolvement::BrowserUI &&
!document->IsInitialDocument() &&
!NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) &&
NS_IsFetchScheme(aLoadState->URI()) &&
document->NodePrincipal()->Subsumes(aLoadState->TriggeringPrincipal())) {
if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
// Step 20.1
if (RefPtr<Navigation> navigation = window->Navigation()) {
AutoJSAPI jsapi;
if (jsapi.Init(window)) {
RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
// Step 20.2
RefPtr<FormData> formData = aLoadState->GetFormDataEntryList();
// Step 20.3
RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring =
aLoadState->GetNavigationAPIState();
if (!navigationAPIStateForFiring) {
navigationAPIStateForFiring = nullptr;
}
nsCOMPtr<nsIURI> destinationURL = aLoadState->URI();
// Step 20.4
bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
jsapi.cx(), aLoadState->GetNavigationType(), destinationURL,
/* aIsSameDocument */ false,
Some(aLoadState->UserNavigationInvolvement()), sourceElement,
formData.forget(), navigationAPIStateForFiring,
/* aClassicHistoryAPIState */ nullptr);
// Step 20.5
if (!shouldContinue) {
return NS_OK;
}
}
}
}
}
// Check if the page doesn't want to be unloaded. The javascript:
// protocol handler deals with this for javascript: URLs.
// NOTE(emilio): As of this writing, other browsers fire beforeunload for
@@ -11450,7 +11499,7 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
aCx, aReplace ? NavigationType::Replace : NavigationType::Push,
newURI,
/* aIsSameDocument */ true, /* aUserInvolvement */ Nothing(),
/* aSourceElement */ nullptr, /* aFormDataEntryList */ Nothing(),
/* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr,
/* aNavigationAPIState */ nullptr, scContainer);
// Step 9
@@ -13265,6 +13314,7 @@ nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
aLoadState->SetLoadType(loadType);
aLoadState->SetSourceBrowsingContext(mBrowsingContext);
aLoadState->SetSourceElement(aContent->AsElement());
nsresult rv = InternalLoad(aLoadState);

View File

@@ -24,6 +24,7 @@
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/LoadURIOptionsBinding.h"
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
#include "mozilla/StaticPrefs_browser.h"
@@ -755,20 +756,6 @@ 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);
@@ -1424,3 +1411,26 @@ already_AddRefed<Element> nsDocShellLoadState::GetSourceElement() const {
nsCOMPtr<Element> element = do_QueryReferent(mSourceElement);
return element.forget();
}
nsIStructuredCloneContainer* nsDocShellLoadState::GetNavigationAPIState()
const {
return mNavigationAPIState;
}
void nsDocShellLoadState::SetNavigationAPIState(
nsIStructuredCloneContainer* aNavigationAPIState) {
mNavigationAPIState = aNavigationAPIState;
}
NavigationType nsDocShellLoadState::GetNavigationType() const {
return LoadReplace() ? NavigationType::Replace : NavigationType::Push;
}
mozilla::dom::FormData* nsDocShellLoadState::GetFormDataEntryList() {
return nullptr;
}
void nsDocShellLoadState::SetFormDataEntryList(
mozilla::dom::FormData* aFormDataEntryList) {
mFormDataEntryList = aFormDataEntryList;
}

View File

@@ -34,6 +34,7 @@ class OriginAttributes;
template <typename, class>
class UniquePtr;
namespace dom {
class FormData;
class DocShellLoadStateInit;
} // namespace dom
} // namespace mozilla
@@ -196,14 +197,6 @@ 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);
@@ -417,9 +410,23 @@ class nsDocShellLoadState final {
void MaybeStripTrackerQueryStrings(mozilla::dom::BrowsingContext* aContext);
// This is used as the parameter for https://html.spec.whatwg.org/#navigate
void SetSourceElement(mozilla::dom::Element* aElement);
already_AddRefed<mozilla::dom::Element> GetSourceElement() const;
// This is used as the parameter for https://html.spec.whatwg.org/#navigate,
// but it's currently missing. See bug 1966674
nsIStructuredCloneContainer* GetNavigationAPIState() const;
void SetNavigationAPIState(nsIStructuredCloneContainer* aNavigationAPIState);
// This is used as the parameter for https://html.spec.whatwg.org/#navigate
mozilla::dom::NavigationType GetNavigationType() const;
// This is used as the parameter for https://html.spec.whatwg.org/#navigate
// It should only ever be set if the method is POST.
mozilla::dom::FormData* GetFormDataEntryList();
void SetFormDataEntryList(mozilla::dom::FormData* aFormDataEntryList);
protected:
// Destructor can't be defaulted or inlined, as header doesn't have all type
// includes it needs to do so.
@@ -561,8 +568,6 @@ class nsDocShellLoadState final {
mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
mLoadingSessionHistoryInfo;
nsCOMPtr<nsIStructuredCloneContainer> mNavigationAPIState;
// Target for load, like _content, _blank etc.
nsString mTarget;
@@ -674,6 +679,10 @@ class nsDocShellLoadState final {
nsILoadInfo::NOT_INITIALIZED;
nsWeakPtr mSourceElement;
nsCOMPtr<nsIStructuredCloneContainer> mNavigationAPIState;
RefPtr<mozilla::dom::FormData> mFormDataEntryList;
};
#endif /* nsDocShellLoadState_h__ */