Bug 1890747 - Track Navigation history entries. r=dom-core,farre
Differential Revision: https://phabricator.services.mozilla.com/D219007
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
#include "mozilla/dom/Location.h"
|
#include "mozilla/dom/Location.h"
|
||||||
#include "mozilla/dom/LocationBinding.h"
|
#include "mozilla/dom/LocationBinding.h"
|
||||||
#include "mozilla/dom/MediaDevices.h"
|
#include "mozilla/dom/MediaDevices.h"
|
||||||
|
#include "mozilla/dom/Navigation.h"
|
||||||
#include "mozilla/dom/PopupBlocker.h"
|
#include "mozilla/dom/PopupBlocker.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/dom/SessionStoreChild.h"
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
@@ -88,6 +89,7 @@
|
|||||||
#include "GVAutoplayRequestStatusIPC.h"
|
#include "GVAutoplayRequestStatusIPC.h"
|
||||||
|
|
||||||
extern mozilla::LazyLogModule gAutoplayPermissionLog;
|
extern mozilla::LazyLogModule gAutoplayPermissionLog;
|
||||||
|
extern mozilla::LazyLogModule gNavigationLog;
|
||||||
extern mozilla::LazyLogModule gTimeoutDeferralLog;
|
extern mozilla::LazyLogModule gTimeoutDeferralLog;
|
||||||
|
|
||||||
#define AUTOPLAY_LOG(msg, ...) \
|
#define AUTOPLAY_LOG(msg, ...) \
|
||||||
@@ -3924,6 +3926,25 @@ void BrowsingContext::ClearCachedValuesOfLocations() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowsingContext::GetContiguousHistoryEntries(
|
||||||
|
SessionHistoryInfo& aActiveEntry, Navigation* aNavigation) {
|
||||||
|
if (!aNavigation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (XRE_IsContentProcess()) {
|
||||||
|
MOZ_ASSERT(ContentChild::GetSingleton());
|
||||||
|
ContentChild::GetSingleton()->SendGetContiguousSessionHistoryInfos(
|
||||||
|
this, aActiveEntry,
|
||||||
|
[aActiveEntry, navigation = RefPtr(aNavigation)](auto aInfos) mutable {
|
||||||
|
navigation->InitializeHistoryEntries(aInfos, &aActiveEntry);
|
||||||
|
},
|
||||||
|
[](auto aReason) { MOZ_ASSERT(false, "How did this happen?"); });
|
||||||
|
} else {
|
||||||
|
auto infos = Canonical()->GetContiguousSessionHistoryInfos(aActiveEntry);
|
||||||
|
aNavigation->InitializeHistoryEntries(infos, &aActiveEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|||||||
@@ -975,6 +975,9 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||||||
void LocationCreated(dom::Location* aLocation);
|
void LocationCreated(dom::Location* aLocation);
|
||||||
void ClearCachedValuesOfLocations();
|
void ClearCachedValuesOfLocations();
|
||||||
|
|
||||||
|
void GetContiguousHistoryEntries(SessionHistoryInfo& aActiveEntry,
|
||||||
|
Navigation* aNavigation);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~BrowsingContext();
|
virtual ~BrowsingContext();
|
||||||
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
|
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/dom/BrowsingContextGroup.h"
|
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
#include "mozilla/dom/EventTarget.h"
|
#include "mozilla/dom/EventTarget.h"
|
||||||
|
#include "mozilla/dom/Navigation.h"
|
||||||
#include "mozilla/dom/PBrowserParent.h"
|
#include "mozilla/dom/PBrowserParent.h"
|
||||||
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
|
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
|
||||||
#include "mozilla/dom/PWindowGlobalParent.h"
|
#include "mozilla/dom/PWindowGlobalParent.h"
|
||||||
@@ -671,6 +672,26 @@ CanonicalBrowsingContext::ReplaceLoadingSessionHistoryEntryForLoad(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::Span<const SessionHistoryInfo>
|
||||||
|
CanonicalBrowsingContext::GetContiguousSessionHistoryInfos(
|
||||||
|
SessionHistoryInfo& aInfo) {
|
||||||
|
MOZ_ASSERT(Navigation::IsAPIEnabled());
|
||||||
|
|
||||||
|
nsISHistory* history = GetSessionHistory();
|
||||||
|
if (!history) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
mActiveContiguousEntries.ClearAndRetainStorage();
|
||||||
|
nsSHistory::WalkContiguousEntriesInOrder(mActiveEntry, [&](auto* aEntry) {
|
||||||
|
if (nsCOMPtr<SessionHistoryEntry> entry = do_QueryObject(aEntry)) {
|
||||||
|
mActiveContiguousEntries.AppendElement(entry->Info());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return mActiveContiguousEntries;
|
||||||
|
}
|
||||||
|
|
||||||
using PrintPromise = CanonicalBrowsingContext::PrintPromise;
|
using PrintPromise = CanonicalBrowsingContext::PrintPromise;
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
// Clients must call StaticCloneForPrintingCreated or
|
// Clients must call StaticCloneForPrintingCreated or
|
||||||
|
|||||||
@@ -325,6 +325,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||||||
void GetLoadingSessionHistoryInfoFromParent(
|
void GetLoadingSessionHistoryInfoFromParent(
|
||||||
Maybe<LoadingSessionHistoryInfo>& aLoadingInfo);
|
Maybe<LoadingSessionHistoryInfo>& aLoadingInfo);
|
||||||
|
|
||||||
|
mozilla::Span<const SessionHistoryInfo> GetContiguousSessionHistoryInfos(
|
||||||
|
SessionHistoryInfo& aInfo);
|
||||||
|
|
||||||
void HistoryCommitIndexAndLength();
|
void HistoryCommitIndexAndLength();
|
||||||
|
|
||||||
void SynchronizeLayoutHistoryState();
|
void SynchronizeLayoutHistoryState();
|
||||||
@@ -637,6 +640,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||||||
bool mFullyDiscarded = false;
|
bool mFullyDiscarded = false;
|
||||||
|
|
||||||
nsTArray<std::function<void(uint64_t)>> mFullyDiscardedListeners;
|
nsTArray<std::function<void(uint64_t)>> mFullyDiscardedListeners;
|
||||||
|
|
||||||
|
nsTArray<SessionHistoryInfo> mActiveContiguousEntries;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|||||||
@@ -68,6 +68,9 @@
|
|||||||
#include "mozilla/dom/FragmentDirective.h"
|
#include "mozilla/dom/FragmentDirective.h"
|
||||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
#include "mozilla/dom/HTMLIFrameElement.h"
|
#include "mozilla/dom/HTMLIFrameElement.h"
|
||||||
|
#include "mozilla/dom/Navigation.h"
|
||||||
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
#include "mozilla/dom/PerformanceNavigation.h"
|
#include "mozilla/dom/PerformanceNavigation.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
#include "mozilla/dom/PopupBlocker.h"
|
#include "mozilla/dom/PopupBlocker.h"
|
||||||
@@ -280,6 +283,7 @@ static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
|
|||||||
#endif
|
#endif
|
||||||
static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
|
static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
|
||||||
extern mozilla::LazyLogModule gPageCacheLog;
|
extern mozilla::LazyLogModule gPageCacheLog;
|
||||||
|
extern mozilla::LazyLogModule gNavigationLog;
|
||||||
mozilla::LazyLogModule gSHLog("SessionHistory");
|
mozilla::LazyLogModule gSHLog("SessionHistory");
|
||||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||||
|
|
||||||
@@ -9059,6 +9063,21 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
|
|||||||
// destroy the docshell, nulling out mScriptGlobal. Hold a stack
|
// destroy the docshell, nulling out mScriptGlobal. Hold a stack
|
||||||
// reference to avoid null derefs. See bug 914521.
|
// reference to avoid null derefs. See bug 914521.
|
||||||
if (win) {
|
if (win) {
|
||||||
|
if (RefPtr navigation = win->Navigation()) {
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("nsDocShell %p triggering a navigation event from "
|
||||||
|
"HandleSameDocumentNavigation",
|
||||||
|
this));
|
||||||
|
// Corresponds to step 6.4.2 from the Updating the document algorithm:
|
||||||
|
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document
|
||||||
|
navigation->UpdateEntriesForSameDocumentNavigation(
|
||||||
|
mActiveEntry.get(),
|
||||||
|
LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)
|
||||||
|
? NavigationType::Replace
|
||||||
|
: aLoadState->LoadIsFromSessionHistory() ? NavigationType::Traverse
|
||||||
|
: NavigationType::Push);
|
||||||
|
}
|
||||||
|
|
||||||
// Fire a hashchange event URIs differ, and only in their hashes.
|
// Fire a hashchange event URIs differ, and only in their hashes.
|
||||||
// If the fragment contains a directive, compare hasRef.
|
// If the fragment contains a directive, compare hasRef.
|
||||||
bool doHashchange = aState.mSameExceptHashes &&
|
bool doHashchange = aState.mSameExceptHashes &&
|
||||||
@@ -11323,19 +11342,23 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
|||||||
} // end of same-origin check
|
} // end of same-origin check
|
||||||
|
|
||||||
// Step 8: call "URL and history update steps"
|
// Step 8: call "URL and history update steps"
|
||||||
rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
|
rv = UpdateURLAndHistory(document, newURI, scContainer,
|
||||||
|
aReplace ? NavigationHistoryBehavior::Replace
|
||||||
|
: NavigationHistoryBehavior::Push,
|
||||||
currentURI, equalURIs);
|
currentURI, equalURIs);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
nsresult nsDocShell::UpdateURLAndHistory(
|
||||||
nsIStructuredCloneContainer* aData,
|
Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData,
|
||||||
const nsAString& aTitle, bool aReplace,
|
NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI,
|
||||||
nsIURI* aCurrentURI, bool aEqualURIs) {
|
bool aEqualURIs) {
|
||||||
// Implements
|
// Implements
|
||||||
// https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
|
// https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
|
||||||
|
MOZ_ASSERT(aHistoryHandling != NavigationHistoryBehavior::Auto);
|
||||||
|
bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace;
|
||||||
|
|
||||||
// If we have a pending title change, handle it before creating a new entry.
|
// If we have a pending title change, handle it before creating a new entry.
|
||||||
aDocument->DoNotifyPossibleTitleChange();
|
aDocument->DoNotifyPossibleTitleChange();
|
||||||
@@ -11344,7 +11367,7 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||||||
// history. This will erase all SHEntries after the new entry and make this
|
// history. This will erase all SHEntries after the new entry and make this
|
||||||
// entry the current one. This operation may modify mOSHE, which we need
|
// entry the current one. This operation may modify mOSHE, which we need
|
||||||
// later, so we keep a reference here.
|
// later, so we keep a reference here.
|
||||||
NS_ENSURE_TRUE(mOSHE || mActiveEntry || aReplace, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mOSHE || mActiveEntry || isReplace, NS_ERROR_FAILURE);
|
||||||
nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
|
nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
|
||||||
|
|
||||||
// If this push/replaceState changed the document's current URI and the new
|
// If this push/replaceState changed the document's current URI and the new
|
||||||
@@ -11367,7 +11390,7 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||||||
mLoadType = LOAD_PUSHSTATE;
|
mLoadType = LOAD_PUSHSTATE;
|
||||||
|
|
||||||
nsCOMPtr<nsISHEntry> newSHEntry;
|
nsCOMPtr<nsISHEntry> newSHEntry;
|
||||||
if (!aReplace) {
|
if (!isReplace) {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
|
|
||||||
// Step 2.2, "Remove any tasks queued by the history traversal task
|
// Step 2.2, "Remove any tasks queued by the history traversal task
|
||||||
@@ -11520,7 +11543,7 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||||||
RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
|
RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
|
||||||
if (rootSH) {
|
if (rootSH) {
|
||||||
rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
|
rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
|
||||||
aReplace);
|
isReplace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11560,6 +11583,19 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||||||
}
|
}
|
||||||
aDocument->SetStateObject(aData);
|
aDocument->SetStateObject(aData);
|
||||||
|
|
||||||
|
if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) {
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("nsDocShell %p triggering a navigation event for a same-document "
|
||||||
|
"navigation from UpdateURLAndHistory -> isReplace: %s",
|
||||||
|
this, isReplace ? "true" : "false"));
|
||||||
|
// Step 11: Update the navigation API entries for a same-document
|
||||||
|
// navigation given document's relevant global object's navigation API,
|
||||||
|
// newEntry, and historyHandling.
|
||||||
|
navigation->UpdateEntriesForSameDocumentNavigation(
|
||||||
|
mActiveEntry.get(),
|
||||||
|
isReplace ? NavigationType::Replace : NavigationType::Push);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13659,6 +13695,16 @@ void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
|
|||||||
*loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
|
*loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
|
||||||
aPersist, false, aExpired, aCacheKey);
|
aPersist, false, aExpired, aCacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only update navigation if the new entry will be persisted (i.e., is not
|
||||||
|
// an about: page).
|
||||||
|
if (aPersist && GetWindow() && GetWindow()->GetCurrentInnerWindow()) {
|
||||||
|
if (RefPtr navigation =
|
||||||
|
GetWindow()->GetCurrentInnerWindow()->Navigation()) {
|
||||||
|
mBrowsingContext->GetContiguousHistoryEntries(*mActiveEntry,
|
||||||
|
navigation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13802,3 +13848,8 @@ void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
|
|||||||
mChannelToDisconnectOnPageHide = 0;
|
mChannelToDisconnectOnPageHide = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsDocShell::IsSameDocumentAsActiveEntry(
|
||||||
|
const mozilla::dom::SessionHistoryInfo& aSHInfo) {
|
||||||
|
return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace dom {
|
|||||||
class ClientInfo;
|
class ClientInfo;
|
||||||
class ClientSource;
|
class ClientSource;
|
||||||
class EventTarget;
|
class EventTarget;
|
||||||
|
enum class NavigationHistoryBehavior : uint8_t;
|
||||||
class SessionHistoryInfo;
|
class SessionHistoryInfo;
|
||||||
struct LoadingSessionHistoryInfo;
|
struct LoadingSessionHistoryInfo;
|
||||||
struct Wireframe;
|
struct Wireframe;
|
||||||
@@ -1111,8 +1112,7 @@ class nsDocShell final : public nsDocLoader,
|
|||||||
* URI.
|
* URI.
|
||||||
* @param aNewURI the new URI.
|
* @param aNewURI the new URI.
|
||||||
* @param aData The serialized state data. May be null.
|
* @param aData The serialized state data. May be null.
|
||||||
* @param aTitle The new title. May be empty.
|
* @param aHistoryHandling how to handle updating the history entries.
|
||||||
* @param aReplace whether this should replace the exising SHEntry.
|
|
||||||
*
|
*
|
||||||
* Arguments we need internally because deriving them from the
|
* Arguments we need internally because deriving them from the
|
||||||
* others is a bit complicated:
|
* others is a bit complicated:
|
||||||
@@ -1120,11 +1120,14 @@ class nsDocShell final : public nsDocLoader,
|
|||||||
* @param aCurrentURI the current URI we're working with. Might be null.
|
* @param aCurrentURI the current URI we're working with. Might be null.
|
||||||
* @param aEqualURIs whether the two URIs involved are equal.
|
* @param aEqualURIs whether the two URIs involved are equal.
|
||||||
*/
|
*/
|
||||||
nsresult UpdateURLAndHistory(mozilla::dom::Document* aDocument,
|
nsresult UpdateURLAndHistory(
|
||||||
nsIURI* aNewURI,
|
mozilla::dom::Document* aDocument, nsIURI* aNewURI,
|
||||||
nsIStructuredCloneContainer* aData,
|
nsIStructuredCloneContainer* aData,
|
||||||
const nsAString& aTitle, bool aReplace,
|
mozilla::dom::NavigationHistoryBehavior aHistoryHandling,
|
||||||
nsIURI* aCurrentURI, bool aEqualURIs);
|
nsIURI* aCurrentURI, bool aEqualURIs);
|
||||||
|
|
||||||
|
bool IsSameDocumentAsActiveEntry(
|
||||||
|
const mozilla::dom::SessionHistoryInfo& aSHInfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetCurrentURIInternal(nsIURI* aURI);
|
void SetCurrentURIInternal(nsIURI* aURI);
|
||||||
|
|||||||
@@ -242,6 +242,10 @@ bool SessionHistoryInfo::IsSubFrame() const {
|
|||||||
return mSharedState.Get()->mIsFrameNavigation;
|
return mSharedState.Get()->mIsFrameNavigation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsStructuredCloneContainer* SessionHistoryInfo::GetNavigationState() const {
|
||||||
|
return mSharedState.Get()->mNavigationState.get();
|
||||||
|
}
|
||||||
|
|
||||||
void SessionHistoryInfo::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
|
void SessionHistoryInfo::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
static_cast<SHEntrySharedParentState*>(mSharedState.Get())->mSaveLayoutState =
|
static_cast<SHEntrySharedParentState*>(mSharedState.Get())->mSaveLayoutState =
|
||||||
@@ -1557,6 +1561,8 @@ void IPDLParamTraits<dom::SessionHistoryInfo>::Write(
|
|||||||
WriteIPDLParam(aWriter, aActor, stateData);
|
WriteIPDLParam(aWriter, aActor, stateData);
|
||||||
WriteIPDLParam(aWriter, aActor, aParam.mSrcdocData);
|
WriteIPDLParam(aWriter, aActor, aParam.mSrcdocData);
|
||||||
WriteIPDLParam(aWriter, aActor, aParam.mBaseURI);
|
WriteIPDLParam(aWriter, aActor, aParam.mBaseURI);
|
||||||
|
WriteIPDLParam(aWriter, aActor, aParam.mNavigationKey);
|
||||||
|
WriteIPDLParam(aWriter, aActor, aParam.mNavigationId);
|
||||||
WriteIPDLParam(aWriter, aActor, aParam.mLoadReplace);
|
WriteIPDLParam(aWriter, aActor, aParam.mLoadReplace);
|
||||||
WriteIPDLParam(aWriter, aActor, aParam.mURIWasModified);
|
WriteIPDLParam(aWriter, aActor, aParam.mURIWasModified);
|
||||||
WriteIPDLParam(aWriter, aActor, aParam.mScrollRestorationIsManual);
|
WriteIPDLParam(aWriter, aActor, aParam.mScrollRestorationIsManual);
|
||||||
@@ -1599,6 +1605,8 @@ bool IPDLParamTraits<dom::SessionHistoryInfo>::Read(
|
|||||||
!ReadIPDLParam(aReader, aActor, &stateData) ||
|
!ReadIPDLParam(aReader, aActor, &stateData) ||
|
||||||
!ReadIPDLParam(aReader, aActor, &aResult->mSrcdocData) ||
|
!ReadIPDLParam(aReader, aActor, &aResult->mSrcdocData) ||
|
||||||
!ReadIPDLParam(aReader, aActor, &aResult->mBaseURI) ||
|
!ReadIPDLParam(aReader, aActor, &aResult->mBaseURI) ||
|
||||||
|
!ReadIPDLParam(aReader, aActor, &aResult->mNavigationKey) ||
|
||||||
|
!ReadIPDLParam(aReader, aActor, &aResult->mNavigationId) ||
|
||||||
!ReadIPDLParam(aReader, aActor, &aResult->mLoadReplace) ||
|
!ReadIPDLParam(aReader, aActor, &aResult->mLoadReplace) ||
|
||||||
!ReadIPDLParam(aReader, aActor, &aResult->mURIWasModified) ||
|
!ReadIPDLParam(aReader, aActor, &aResult->mURIWasModified) ||
|
||||||
!ReadIPDLParam(aReader, aActor, &aResult->mScrollRestorationIsManual) ||
|
!ReadIPDLParam(aReader, aActor, &aResult->mScrollRestorationIsManual) ||
|
||||||
|
|||||||
@@ -161,6 +161,12 @@ class SessionHistoryInfo {
|
|||||||
|
|
||||||
bool GetPersist() const { return mPersist; }
|
bool GetPersist() const { return mPersist; }
|
||||||
|
|
||||||
|
nsID& NavigationKey() { return mNavigationKey; }
|
||||||
|
const nsID& NavigationKey() const { return mNavigationKey; }
|
||||||
|
const nsID& NavigationId() const { return mNavigationId; }
|
||||||
|
|
||||||
|
nsStructuredCloneContainer* GetNavigationState() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SessionHistoryEntry;
|
friend class SessionHistoryEntry;
|
||||||
friend struct mozilla::ipc::IPDLParamTraits<SessionHistoryInfo>;
|
friend struct mozilla::ipc::IPDLParamTraits<SessionHistoryInfo>;
|
||||||
@@ -182,6 +188,10 @@ class SessionHistoryInfo {
|
|||||||
Maybe<nsString> mSrcdocData;
|
Maybe<nsString> mSrcdocData;
|
||||||
nsCOMPtr<nsIURI> mBaseURI;
|
nsCOMPtr<nsIURI> mBaseURI;
|
||||||
|
|
||||||
|
// Fields needed for NavigationHistoryEntry.
|
||||||
|
nsID mNavigationKey = nsID::GenerateUUID();
|
||||||
|
nsID mNavigationId = nsID::GenerateUUID();
|
||||||
|
|
||||||
bool mLoadReplace = false;
|
bool mLoadReplace = false;
|
||||||
bool mURIWasModified = false;
|
bool mURIWasModified = false;
|
||||||
bool mScrollRestorationIsManual = false;
|
bool mScrollRestorationIsManual = false;
|
||||||
@@ -353,12 +363,8 @@ class HistoryEntryCounterForBrowsingContext {
|
|||||||
// SessionHistoryEntry is used to store session history data in the parent
|
// SessionHistoryEntry is used to store session history data in the parent
|
||||||
// process. It holds a SessionHistoryInfo, some state shared amongst multiple
|
// process. It holds a SessionHistoryInfo, some state shared amongst multiple
|
||||||
// SessionHistoryEntries, a parent and children.
|
// SessionHistoryEntries, a parent and children.
|
||||||
#define NS_SESSIONHISTORYENTRY_IID \
|
#define NS_SESSIONHISTORYENTRY_IID \
|
||||||
{ \
|
{0x5b66a244, 0x8cec, 0x4caa, {0xaa, 0x0a, 0x78, 0x92, 0xfd, 0x17, 0xa6, 0x67}}
|
||||||
0x5b66a244, 0x8cec, 0x4caa, { \
|
|
||||||
0xaa, 0x0a, 0x78, 0x92, 0xfd, 0x17, 0xa6, 0x67 \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
class SessionHistoryEntry : public nsISHEntry, public nsSupportsWeakReference {
|
class SessionHistoryEntry : public nsISHEntry, public nsSupportsWeakReference {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ void SHEntrySharedParentState::CopyFrom(SHEntrySharedParentState* aEntry) {
|
|||||||
mDynamicallyCreated = aEntry->mDynamicallyCreated;
|
mDynamicallyCreated = aEntry->mDynamicallyCreated;
|
||||||
mCacheKey = aEntry->mCacheKey;
|
mCacheKey = aEntry->mCacheKey;
|
||||||
mLastTouched = aEntry->mLastTouched;
|
mLastTouched = aEntry->mLastTouched;
|
||||||
|
mNavigationState = aEntry->mNavigationState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dom::SHEntrySharedParentState::NotifyListenersDocumentViewerEvicted() {
|
void dom::SHEntrySharedParentState::NotifyListenersDocumentViewerEvicted() {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "nsIWeakReferenceUtils.h"
|
#include "nsIWeakReferenceUtils.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
#include "nsStructuredCloneContainer.h"
|
||||||
#include "nsStubMutationObserver.h"
|
#include "nsStubMutationObserver.h"
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
@@ -63,7 +64,8 @@ struct SHEntrySharedState {
|
|||||||
mPrincipalToInherit(aPrincipalToInherit),
|
mPrincipalToInherit(aPrincipalToInherit),
|
||||||
mPartitionedPrincipalToInherit(aPartitionedPrincipalToInherit),
|
mPartitionedPrincipalToInherit(aPartitionedPrincipalToInherit),
|
||||||
mCsp(aCsp),
|
mCsp(aCsp),
|
||||||
mContentType(aContentType) {}
|
mContentType(aContentType),
|
||||||
|
mNavigationState(MakeRefPtr<nsStructuredCloneContainer>()) {}
|
||||||
|
|
||||||
// These members aren't copied by SHEntrySharedParentState::CopyFrom() because
|
// These members aren't copied by SHEntrySharedParentState::CopyFrom() because
|
||||||
// they're specific to a particular content viewer.
|
// they're specific to a particular content viewer.
|
||||||
@@ -83,6 +85,8 @@ struct SHEntrySharedState {
|
|||||||
bool mIsFrameNavigation = false;
|
bool mIsFrameNavigation = false;
|
||||||
bool mSaveLayoutState = true;
|
bool mSaveLayoutState = true;
|
||||||
|
|
||||||
|
RefPtr<nsStructuredCloneContainer> mNavigationState;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static uint64_t GenerateId();
|
static uint64_t GenerateId();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ LazyLogModule gSHistoryLog("nsSHistory");
|
|||||||
#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
|
#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
|
||||||
|
|
||||||
extern mozilla::LazyLogModule gPageCacheLog;
|
extern mozilla::LazyLogModule gPageCacheLog;
|
||||||
|
extern mozilla::LazyLogModule gNavigationLog;
|
||||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||||
|
|
||||||
// This macro makes it easier to print a log message which includes a URI's
|
// This macro makes it easier to print a log message which includes a URI's
|
||||||
@@ -616,6 +617,63 @@ void nsSHistory::WalkContiguousEntries(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void nsSHistory::WalkContiguousEntriesInOrder(
|
||||||
|
nsISHEntry* aEntry, const std::function<void(nsISHEntry*)>& aCallback) {
|
||||||
|
MOZ_ASSERT(aEntry);
|
||||||
|
|
||||||
|
nsCOMPtr<nsISHistory> shistory = aEntry->GetShistory();
|
||||||
|
if (!shistory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t index = shistory->GetIndexOfEntry(aEntry);
|
||||||
|
int32_t count = shistory->GetCount();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> targetURI = aEntry->GetURI();
|
||||||
|
|
||||||
|
// Walk backward to find the entries that have the same origin as the
|
||||||
|
// input entry.
|
||||||
|
int32_t lowerBound = index;
|
||||||
|
for (int32_t i = index - 1; i >= 0; i--) {
|
||||||
|
RefPtr<nsISHEntry> entry;
|
||||||
|
shistory->GetEntryAtIndex(i, getter_AddRefs(entry));
|
||||||
|
if (!entry) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIURI> uri = entry->GetURI();
|
||||||
|
if (NS_FAILED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(
|
||||||
|
targetURI, uri, false, false))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lowerBound = i;
|
||||||
|
}
|
||||||
|
for (int32_t i = lowerBound; i < index; i++) {
|
||||||
|
RefPtr<nsISHEntry> entry;
|
||||||
|
shistory->GetEntryAtIndex(i, getter_AddRefs(entry));
|
||||||
|
MOZ_ASSERT(entry);
|
||||||
|
aCallback(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, call the callback on the input entry.
|
||||||
|
aCallback(aEntry);
|
||||||
|
|
||||||
|
// Then, Walk forward.
|
||||||
|
for (int32_t i = index + 1; i < count; i++) {
|
||||||
|
RefPtr<nsISHEntry> entry;
|
||||||
|
shistory->GetEntryAtIndex(i, getter_AddRefs(entry));
|
||||||
|
if (!entry) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIURI> uri = entry->GetURI();
|
||||||
|
if (NS_FAILED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(
|
||||||
|
targetURI, uri, false, false))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aCallback(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
|
nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
|
||||||
BrowsingContext* aRootBC,
|
BrowsingContext* aRootBC,
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
|
|||||||
// works for the root entries. It will do nothing for non-root entries.
|
// works for the root entries. It will do nothing for non-root entries.
|
||||||
static void WalkContiguousEntries(
|
static void WalkContiguousEntries(
|
||||||
nsISHEntry* aEntry, const std::function<void(nsISHEntry*)>& aCallback);
|
nsISHEntry* aEntry, const std::function<void(nsISHEntry*)>& aCallback);
|
||||||
|
// Same as above, but calls aCallback on the entries in their history order.
|
||||||
|
static void WalkContiguousEntriesInOrder(
|
||||||
|
nsISHEntry* aEntry, const std::function<void(nsISHEntry*)>& aCallback);
|
||||||
|
|
||||||
nsTArray<nsCOMPtr<nsISHEntry>>& Entries() { return mEntries; }
|
nsTArray<nsCOMPtr<nsISHEntry>>& Entries() { return mEntries; }
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,7 @@
|
|||||||
#include "mozilla/dom/FeaturePolicyUtils.h"
|
#include "mozilla/dom/FeaturePolicyUtils.h"
|
||||||
#include "mozilla/dom/FontFaceSet.h"
|
#include "mozilla/dom/FontFaceSet.h"
|
||||||
#include "mozilla/dom/FragmentDirective.h"
|
#include "mozilla/dom/FragmentDirective.h"
|
||||||
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
#include "mozilla/dom/fragmentdirectives_ffi_generated.h"
|
#include "mozilla/dom/fragmentdirectives_ffi_generated.h"
|
||||||
#include "mozilla/dom/FromParser.h"
|
#include "mozilla/dom/FromParser.h"
|
||||||
#include "mozilla/dom/HighlightRegistry.h"
|
#include "mozilla/dom/HighlightRegistry.h"
|
||||||
@@ -10148,9 +10149,9 @@ Document* Document::Open(const Optional<nsAString>& /* unused */,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIStructuredCloneContainer> stateContainer(mStateObjectContainer);
|
nsCOMPtr<nsIStructuredCloneContainer> stateContainer(mStateObjectContainer);
|
||||||
rv = shell->UpdateURLAndHistory(this, newURI, stateContainer, u""_ns,
|
rv = shell->UpdateURLAndHistory(this, newURI, stateContainer,
|
||||||
/* aReplace = */ true, currentURI,
|
NavigationHistoryBehavior::Replace,
|
||||||
equalURIs);
|
currentURI, equalURIs);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
aError.Throw(rv);
|
aError.Throw(rv);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -1170,6 +1170,8 @@ void nsGlobalWindowInner::FreeInnerObjects() {
|
|||||||
|
|
||||||
mHistory = nullptr;
|
mHistory = nullptr;
|
||||||
|
|
||||||
|
mNavigation = nullptr;
|
||||||
|
|
||||||
if (mNavigator) {
|
if (mNavigator) {
|
||||||
mNavigator->OnNavigation();
|
mNavigator->OnNavigation();
|
||||||
mNavigator->Invalidate();
|
mNavigator->Invalidate();
|
||||||
@@ -1390,6 +1392,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigation)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
|
||||||
@@ -1496,6 +1500,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
|
|||||||
JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper));
|
JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigation)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
|
||||||
@@ -2412,6 +2418,14 @@ WindowProxyHolder nsGlobalWindowInner::Window() {
|
|||||||
return WindowProxyHolder(GetBrowsingContext());
|
return WindowProxyHolder(GetBrowsingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Navigation* nsPIDOMWindowInner::Navigation() {
|
||||||
|
if (!mNavigation && Navigation::IsAPIEnabled()) {
|
||||||
|
mNavigation = new mozilla::dom::Navigation(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mNavigation;
|
||||||
|
}
|
||||||
|
|
||||||
Navigator* nsPIDOMWindowInner::Navigator() {
|
Navigator* nsPIDOMWindowInner::Navigator() {
|
||||||
if (!mNavigator) {
|
if (!mNavigator) {
|
||||||
mNavigator = new mozilla::dom::Navigator(this);
|
mNavigator = new mozilla::dom::Navigator(this);
|
||||||
@@ -2445,14 +2459,6 @@ nsHistory* nsGlobalWindowInner::GetHistory(ErrorResult& aError) {
|
|||||||
return mHistory;
|
return mHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigation* nsGlobalWindowInner::Navigation() {
|
|
||||||
if (!mNavigation && Navigation::IsAPIEnabled(nullptr, nullptr)) {
|
|
||||||
mNavigation = new mozilla::dom::Navigation();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mNavigation;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomElementRegistry* nsGlobalWindowInner::CustomElements() {
|
CustomElementRegistry* nsGlobalWindowInner::CustomElements() {
|
||||||
if (!mCustomElements) {
|
if (!mCustomElements) {
|
||||||
mCustomElements = new CustomElementRegistry(this);
|
mCustomElements = new CustomElementRegistry(this);
|
||||||
@@ -6663,6 +6669,10 @@ void nsGlobalWindowInner::AddSizeOfIncludingThis(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mNavigation) {
|
||||||
|
aWindowSizes.mDOMSizes.mDOMOtherSize +=
|
||||||
|
aWindowSizes.mState.mMallocSizeOf(mNavigation.get());
|
||||||
|
}
|
||||||
if (mNavigator) {
|
if (mNavigator) {
|
||||||
aWindowSizes.mDOMSizes.mDOMOtherSize +=
|
aWindowSizes.mDOMSizes.mDOMOtherSize +=
|
||||||
mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
|
mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ class IdleRequestCallback;
|
|||||||
class InstallTriggerImpl;
|
class InstallTriggerImpl;
|
||||||
class IntlUtils;
|
class IntlUtils;
|
||||||
class MediaQueryList;
|
class MediaQueryList;
|
||||||
class Navigation;
|
|
||||||
class OwningExternalOrWindowProxy;
|
class OwningExternalOrWindowProxy;
|
||||||
class Promise;
|
class Promise;
|
||||||
class PostMessageEvent;
|
class PostMessageEvent;
|
||||||
@@ -618,7 +617,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||||||
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
|
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||||
mozilla::dom::Location* Location() override;
|
mozilla::dom::Location* Location() override;
|
||||||
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
||||||
mozilla::dom::Navigation* Navigation();
|
|
||||||
mozilla::dom::CustomElementRegistry* CustomElements() override;
|
mozilla::dom::CustomElementRegistry* CustomElements() override;
|
||||||
mozilla::dom::CustomElementRegistry* GetExistingCustomElements();
|
mozilla::dom::CustomElementRegistry* GetExistingCustomElements();
|
||||||
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
|
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
|
||||||
@@ -1388,7 +1386,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||||||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||||
RefPtr<mozilla::dom::Location> mLocation;
|
RefPtr<mozilla::dom::Location> mLocation;
|
||||||
RefPtr<nsHistory> mHistory;
|
RefPtr<nsHistory> mHistory;
|
||||||
RefPtr<mozilla::dom::Navigation> mNavigation;
|
|
||||||
RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
|
RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
|
||||||
|
|
||||||
nsTObserverArray<RefPtr<mozilla::dom::SharedWorker>> mSharedWorkers;
|
nsTObserverArray<RefPtr<mozilla::dom::SharedWorker>> mSharedWorkers;
|
||||||
|
|||||||
@@ -308,6 +308,9 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
|||||||
|
|
||||||
void DetachFromDocShell(bool aIsBeingDiscarded);
|
void DetachFromDocShell(bool aIsBeingDiscarded);
|
||||||
|
|
||||||
|
// aState is only non-null if we are restoring from the bfcache.
|
||||||
|
// aForceReuseInnerWindow is only true if we are being triggered via XSLT.
|
||||||
|
// aActor is only non-null if the new document is about:blank.
|
||||||
virtual nsresult SetNewDocument(
|
virtual nsresult SetNewDocument(
|
||||||
Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
|
Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
|
||||||
mozilla::dom::WindowGlobalChild* aActor = nullptr) override;
|
mozilla::dom::WindowGlobalChild* aActor = nullptr) override;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class Element;
|
|||||||
class Location;
|
class Location;
|
||||||
class MediaDevices;
|
class MediaDevices;
|
||||||
class MediaKeys;
|
class MediaKeys;
|
||||||
|
class Navigation;
|
||||||
class Navigator;
|
class Navigator;
|
||||||
class Performance;
|
class Performance;
|
||||||
class Selection;
|
class Selection;
|
||||||
@@ -590,6 +591,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
|
|||||||
|
|
||||||
uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
|
uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
|
||||||
|
|
||||||
|
mozilla::dom::Navigation* Navigation();
|
||||||
mozilla::dom::Navigator* Navigator();
|
mozilla::dom::Navigator* Navigator();
|
||||||
mozilla::dom::MediaDevices* GetExtantMediaDevices() const;
|
mozilla::dom::MediaDevices* GetExtantMediaDevices() const;
|
||||||
virtual mozilla::dom::Location* Location() = 0;
|
virtual mozilla::dom::Location* Location() = 0;
|
||||||
@@ -661,6 +663,8 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
|
|||||||
RefPtr<mozilla::dom::Performance> mPerformance;
|
RefPtr<mozilla::dom::Performance> mPerformance;
|
||||||
mozilla::UniquePtr<mozilla::dom::TimeoutManager> mTimeoutManager;
|
mozilla::UniquePtr<mozilla::dom::TimeoutManager> mTimeoutManager;
|
||||||
|
|
||||||
|
RefPtr<mozilla::dom::Navigation> mNavigation;
|
||||||
|
|
||||||
RefPtr<mozilla::dom::Navigator> mNavigator;
|
RefPtr<mozilla::dom::Navigator> mNavigator;
|
||||||
|
|
||||||
// These variables are only used on inner windows.
|
// These variables are only used on inner windows.
|
||||||
|
|||||||
@@ -7654,6 +7654,18 @@ ContentParent::RecvGetLoadingSessionHistoryInfoFromParent(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult ContentParent::RecvGetContiguousSessionHistoryInfos(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aContext, SessionHistoryInfo&& aInfo,
|
||||||
|
GetContiguousSessionHistoryInfosResolver&& aResolver) {
|
||||||
|
if (aContext.IsNullOrDiscarded()) {
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
aResolver(aContext.get_canonical()->GetContiguousSessionHistoryInfos(aInfo));
|
||||||
|
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvRemoveFromBFCache(
|
mozilla::ipc::IPCResult ContentParent::RecvRemoveFromBFCache(
|
||||||
const MaybeDiscarded<BrowsingContext>& aContext) {
|
const MaybeDiscarded<BrowsingContext>& aContext) {
|
||||||
if (aContext.IsNullOrDiscarded()) {
|
if (aContext.IsNullOrDiscarded()) {
|
||||||
|
|||||||
@@ -1335,6 +1335,11 @@ class ContentParent final : public PContentParent,
|
|||||||
const MaybeDiscarded<BrowsingContext>& aContext,
|
const MaybeDiscarded<BrowsingContext>& aContext,
|
||||||
GetLoadingSessionHistoryInfoFromParentResolver&& aResolver);
|
GetLoadingSessionHistoryInfoFromParentResolver&& aResolver);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvGetContiguousSessionHistoryInfos(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aContext,
|
||||||
|
SessionHistoryInfo&& aInfo,
|
||||||
|
GetContiguousSessionHistoryInfosResolver&& aResolver);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvRemoveFromBFCache(
|
mozilla::ipc::IPCResult RecvRemoveFromBFCache(
|
||||||
const MaybeDiscarded<BrowsingContext>& aContext);
|
const MaybeDiscarded<BrowsingContext>& aContext);
|
||||||
|
|
||||||
|
|||||||
@@ -1061,6 +1061,10 @@ parent:
|
|||||||
async GetLoadingSessionHistoryInfoFromParent(MaybeDiscardedBrowsingContext aContext)
|
async GetLoadingSessionHistoryInfoFromParent(MaybeDiscardedBrowsingContext aContext)
|
||||||
returns (LoadingSessionHistoryInfo? aLoadingInfo);
|
returns (LoadingSessionHistoryInfo? aLoadingInfo);
|
||||||
|
|
||||||
|
async GetContiguousSessionHistoryInfos(MaybeDiscardedBrowsingContext aContext,
|
||||||
|
SessionHistoryInfo aInfo)
|
||||||
|
returns (SessionHistoryInfo[] infos);
|
||||||
|
|
||||||
async RemoveFromBFCache(MaybeDiscardedBrowsingContext aContext);
|
async RemoveFromBFCache(MaybeDiscardedBrowsingContext aContext);
|
||||||
|
|
||||||
async InitBackground(Endpoint<PBackgroundStarterParent> aEndpoint);
|
async InitBackground(Endpoint<PBackgroundStarterParent> aEndpoint);
|
||||||
|
|||||||
@@ -5,20 +5,39 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/dom/Navigation.h"
|
#include "mozilla/dom/Navigation.h"
|
||||||
#include "mozilla/dom/NavigationBinding.h"
|
|
||||||
|
|
||||||
|
#include "mozilla/CycleCollectedJSContext.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/Event.h"
|
||||||
|
#include "mozilla/dom/FeaturePolicy.h"
|
||||||
|
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
||||||
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
||||||
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
#include "nsIXULRuntime.h"
|
#include "nsIXULRuntime.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
|
mozilla::LazyLogModule gNavigationLog("Navigation");
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(Navigation, DOMEventTargetHelper);
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(Navigation, DOMEventTargetHelper, mEntries);
|
||||||
NS_IMPL_ADDREF_INHERITED(Navigation, DOMEventTargetHelper)
|
NS_IMPL_ADDREF_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
NS_IMPL_RELEASE_INHERITED(Navigation, DOMEventTargetHelper)
|
NS_IMPL_RELEASE_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigation)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigation)
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
Navigation::Navigation(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
JSObject* Navigation::WrapObject(JSContext* aCx,
|
JSObject* Navigation::WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) {
|
JS::Handle<JSObject*> aGivenProto) {
|
||||||
return Navigation_Binding::Wrap(aCx, this, aGivenProto);
|
return Navigation_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
@@ -30,4 +49,228 @@ bool Navigation::IsAPIEnabled(JSContext* /* unused */, JSObject* /* unused */) {
|
|||||||
StaticPrefs::dom_navigation_webidl_enabled_DoNotUseDirectly();
|
StaticPrefs::dom_navigation_webidl_enabled_DoNotUseDirectly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Navigation::Entries(
|
||||||
|
nsTArray<RefPtr<NavigationHistoryEntry>>& aResult) const {
|
||||||
|
aResult = mEntries.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<NavigationHistoryEntry> Navigation::GetCurrentEntry() const {
|
||||||
|
if (HasEntriesAndEventsDisabled()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCurrentEntryIndex) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("Current Entry: %d; Amount of Entries: %d", int(*mCurrentEntryIndex),
|
||||||
|
int(mEntries.Length())));
|
||||||
|
MOZ_ASSERT(*mCurrentEntryIndex < mEntries.Length());
|
||||||
|
|
||||||
|
RefPtr entry{mEntries[*mCurrentEntryIndex]};
|
||||||
|
return entry.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigation-updatecurrententry
|
||||||
|
void Navigation::UpdateCurrentEntry(
|
||||||
|
JSContext* aCx, const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||||
|
ErrorResult& aRv) {
|
||||||
|
RefPtr currentEntry(GetCurrentEntry());
|
||||||
|
if (!currentEntry) {
|
||||||
|
aRv.ThrowInvalidStateError(
|
||||||
|
"Can't call updateCurrentEntry without a valid entry.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> state(aCx, aOptions.mState);
|
||||||
|
auto serializedState = MakeRefPtr<nsStructuredCloneContainer>();
|
||||||
|
nsresult rv = serializedState->InitFromJSVal(state, aCx);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aRv.ThrowDataCloneError(
|
||||||
|
"Failed to serialize value for updateCurrentEntry.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentEntry->SetState(serializedState);
|
||||||
|
|
||||||
|
NavigationCurrentEntryChangeEventInit init;
|
||||||
|
init.mFrom = currentEntry;
|
||||||
|
// Leaving the navigation type unspecified means it will be initialized to
|
||||||
|
// null.
|
||||||
|
RefPtr event = NavigationCurrentEntryChangeEvent::Constructor(
|
||||||
|
this, u"currententrychange"_ns, init);
|
||||||
|
DispatchEvent(*event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||||
|
bool Navigation::HasEntriesAndEventsDisabled() const {
|
||||||
|
Document* doc = mWindow->GetDoc();
|
||||||
|
return !doc->IsCurrentActiveDocument() ||
|
||||||
|
(NS_IsAboutBlank(doc->GetDocumentURI()) && doc->IsInitialDocument()) ||
|
||||||
|
doc->GetPrincipal()->GetIsNullPrincipal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#initialize-the-navigation-api-entries-for-a-new-document
|
||||||
|
void Navigation::InitializeHistoryEntries(
|
||||||
|
mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
|
||||||
|
const SessionHistoryInfo* aInitialSHInfo) {
|
||||||
|
mEntries.Clear();
|
||||||
|
mCurrentEntryIndex.reset();
|
||||||
|
if (HasEntriesAndEventsDisabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0ul; i < aNewSHInfos.Length(); i++) {
|
||||||
|
mEntries.AppendElement(
|
||||||
|
MakeRefPtr<NavigationHistoryEntry>(mWindow, &aNewSHInfos[i], i));
|
||||||
|
if (aNewSHInfos[i].NavigationKey() == aInitialSHInfo->NavigationKey()) {
|
||||||
|
mCurrentEntryIndex = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHistory();
|
||||||
|
|
||||||
|
nsID key = aInitialSHInfo->NavigationKey();
|
||||||
|
nsID id = aInitialSHInfo->NavigationId();
|
||||||
|
MOZ_LOG(
|
||||||
|
gNavigationLog, LogLevel::Debug,
|
||||||
|
("aInitialSHInfo: %s %s\n", key.ToString().get(), id.ToString().get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
||||||
|
void Navigation::UpdateEntriesForSameDocumentNavigation(
|
||||||
|
SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType) {
|
||||||
|
// Step 1.
|
||||||
|
if (HasEntriesAndEventsDisabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("Updating entries for same-document navigation"));
|
||||||
|
|
||||||
|
// Steps 2-7.
|
||||||
|
RefPtr<NavigationHistoryEntry> oldCurrentEntry = GetCurrentEntry();
|
||||||
|
nsTArray<RefPtr<NavigationHistoryEntry>> disposedEntries;
|
||||||
|
switch (aNavigationType) {
|
||||||
|
case NavigationType::Traverse:
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug, ("Traverse navigation"));
|
||||||
|
mCurrentEntryIndex.reset();
|
||||||
|
for (auto i = 0ul; i < mEntries.Length(); i++) {
|
||||||
|
if (mEntries[i]->IsSameEntry(aDestinationSHE)) {
|
||||||
|
mCurrentEntryIndex = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(mCurrentEntryIndex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NavigationType::Push:
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug, ("Push navigation"));
|
||||||
|
mCurrentEntryIndex =
|
||||||
|
Some(mCurrentEntryIndex ? *mCurrentEntryIndex + 1 : 0);
|
||||||
|
while (*mCurrentEntryIndex < mEntries.Length()) {
|
||||||
|
disposedEntries.AppendElement(mEntries.PopLastElement());
|
||||||
|
}
|
||||||
|
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
||||||
|
mWindow, aDestinationSHE, *mCurrentEntryIndex));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NavigationType::Replace:
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug, ("Replace navigation"));
|
||||||
|
disposedEntries.AppendElement(oldCurrentEntry);
|
||||||
|
aDestinationSHE->NavigationKey() = oldCurrentEntry->Key();
|
||||||
|
mEntries[*mCurrentEntryIndex] = MakeRefPtr<NavigationHistoryEntry>(
|
||||||
|
mWindow, aDestinationSHE, *mCurrentEntryIndex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NavigationType::Reload:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Step 8.
|
||||||
|
|
||||||
|
// Steps 9-12.
|
||||||
|
{
|
||||||
|
nsAutoMicroTask mt;
|
||||||
|
AutoEntryScript aes(mWindow->AsGlobal(),
|
||||||
|
"UpdateEntriesForSameDocumentNavigation");
|
||||||
|
|
||||||
|
ScheduleEventsFromNavigation(aNavigationType, oldCurrentEntry,
|
||||||
|
std::move(disposedEntries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-reactivation
|
||||||
|
void Navigation::UpdateForReactivation(SessionHistoryInfo* aReactivatedEntry) {
|
||||||
|
// NAV-TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Navigation::ScheduleEventsFromNavigation(
|
||||||
|
NavigationType aType, const RefPtr<NavigationHistoryEntry>& aPreviousEntry,
|
||||||
|
nsTArray<RefPtr<NavigationHistoryEntry>>&& aDisposedEntries) {
|
||||||
|
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
|
||||||
|
"mozilla::dom::Navigation::ScheduleEventsFromNavigation",
|
||||||
|
[self = RefPtr(this), previousEntry = RefPtr(aPreviousEntry),
|
||||||
|
disposedEntries = std::move(aDisposedEntries), aType]() {
|
||||||
|
if (previousEntry) {
|
||||||
|
NavigationCurrentEntryChangeEventInit init;
|
||||||
|
init.mFrom = previousEntry;
|
||||||
|
init.mNavigationType.SetValue(aType);
|
||||||
|
RefPtr event = NavigationCurrentEntryChangeEvent::Constructor(
|
||||||
|
self, u"currententrychange"_ns, init);
|
||||||
|
self->DispatchEvent(*event);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& entry : disposedEntries) {
|
||||||
|
RefPtr<Event> event = NS_NewDOMEvent(entry, nullptr, nullptr);
|
||||||
|
event->InitEvent(u"dispose"_ns, false, false);
|
||||||
|
event->SetTrusted(true);
|
||||||
|
event->SetTarget(entry);
|
||||||
|
entry->DispatchEvent(*event);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void LogEntry(NavigationHistoryEntry* aEntry, uint64_t aIndex, uint64_t aTotal,
|
||||||
|
bool aIsCurrent) {
|
||||||
|
if (!aEntry) {
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
(" +- %d NHEntry null\n", int(aIndex)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString key, id;
|
||||||
|
aEntry->GetKey(key);
|
||||||
|
aEntry->GetId(id);
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("%s+- %d NHEntry %p %s %s\n", aIsCurrent ? ">" : " ", int(aIndex),
|
||||||
|
aEntry, NS_ConvertUTF16toUTF8(key).get(),
|
||||||
|
NS_ConvertUTF16toUTF8(id).get()));
|
||||||
|
|
||||||
|
nsAutoString url;
|
||||||
|
aEntry->GetUrl(url);
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
(" URL = %s\n", NS_ConvertUTF16toUTF8(url).get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Navigation::LogHistory() const {
|
||||||
|
if (!MOZ_LOG_TEST(gNavigationLog, LogLevel::Debug)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_LOG(gNavigationLog, LogLevel::Debug,
|
||||||
|
("Navigation %p (current entry index: %d)\n", this,
|
||||||
|
mCurrentEntryIndex ? int(*mCurrentEntryIndex) : -1));
|
||||||
|
auto length = mEntries.Length();
|
||||||
|
for (uint64_t i = 0; i < length; i++) {
|
||||||
|
LogEntry(mEntries[i], i, length,
|
||||||
|
mCurrentEntryIndex && i == *mCurrentEntryIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define mozilla_dom_Navigation_h___
|
#define mozilla_dom_Navigation_h___
|
||||||
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
@@ -20,21 +21,33 @@ struct NavigationUpdateCurrentEntryOptions;
|
|||||||
struct NavigationReloadOptions;
|
struct NavigationReloadOptions;
|
||||||
struct NavigationResult;
|
struct NavigationResult;
|
||||||
|
|
||||||
|
class SessionHistoryInfo;
|
||||||
|
|
||||||
class Navigation final : public DOMEventTargetHelper {
|
class Navigation final : public DOMEventTargetHelper {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Navigation, DOMEventTargetHelper)
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
|
|
||||||
void Entries(nsTArray<RefPtr<NavigationHistoryEntry>>& aResult) {}
|
explicit Navigation(nsPIDOMWindowInner* aWindow);
|
||||||
already_AddRefed<NavigationHistoryEntry> GetCurrentEntry() { return {}; }
|
|
||||||
|
// Navigation.webidl
|
||||||
|
void Entries(nsTArray<RefPtr<NavigationHistoryEntry>>& aResult) const;
|
||||||
|
already_AddRefed<NavigationHistoryEntry> GetCurrentEntry() const;
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void UpdateCurrentEntry(JSContext* aCx,
|
void UpdateCurrentEntry(JSContext* aCx,
|
||||||
const NavigationUpdateCurrentEntryOptions& aOptions,
|
const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||||
ErrorResult& aRv) {}
|
ErrorResult& aRv);
|
||||||
already_AddRefed<NavigationTransition> GetTransition() { return {}; }
|
already_AddRefed<NavigationTransition> GetTransition() { return {}; }
|
||||||
already_AddRefed<NavigationActivation> GetActivation() { return {}; }
|
already_AddRefed<NavigationActivation> GetActivation() { return {}; }
|
||||||
|
|
||||||
bool CanGoBack() { return {}; }
|
bool CanGoBack() {
|
||||||
bool CanGoForward() { return {}; }
|
return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
|
||||||
|
*mCurrentEntryIndex != 0;
|
||||||
|
}
|
||||||
|
bool CanGoForward() {
|
||||||
|
return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
|
||||||
|
*mCurrentEntryIndex != mEntries.Length() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void Navigate(JSContext* aCx, const nsAString& aUrl,
|
void Navigate(JSContext* aCx, const nsAString& aUrl,
|
||||||
const NavigationNavigateOptions& aOptions,
|
const NavigationNavigateOptions& aOptions,
|
||||||
@@ -55,15 +68,45 @@ class Navigation final : public DOMEventTargetHelper {
|
|||||||
IMPL_EVENT_HANDLER(navigateerror);
|
IMPL_EVENT_HANDLER(navigateerror);
|
||||||
IMPL_EVENT_HANDLER(currententrychange);
|
IMPL_EVENT_HANDLER(currententrychange);
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#initialize-the-navigation-api-entries-for-a-new-document
|
||||||
|
void InitializeHistoryEntries(
|
||||||
|
mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
|
||||||
|
const SessionHistoryInfo* aInitialSHInfo);
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-reactivation
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
|
void UpdateForReactivation(SessionHistoryInfo* aReactivatedEntry);
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
||||||
|
void UpdateEntriesForSameDocumentNavigation(
|
||||||
|
SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType);
|
||||||
|
|
||||||
JSObject* WrapObject(JSContext* aCx,
|
JSObject* WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
// The Navigation API is only enabled if both SessionHistoryInParent and
|
// The Navigation API is only enabled if both SessionHistoryInParent and
|
||||||
// the dom.navigation.webidl.enabled pref are set.
|
// the dom.navigation.webidl.enabled pref are set.
|
||||||
static bool IsAPIEnabled(JSContext* /* unused */, JSObject* /* unused */);
|
static bool IsAPIEnabled(JSContext* /* unused */ = nullptr,
|
||||||
|
JSObject* /* unused */ = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~Navigation() = default;
|
~Navigation() = default;
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||||
|
bool HasEntriesAndEventsDisabled() const;
|
||||||
|
|
||||||
|
void ScheduleEventsFromNavigation(
|
||||||
|
NavigationType aType,
|
||||||
|
const RefPtr<NavigationHistoryEntry>& aPreviousEntry,
|
||||||
|
nsTArray<RefPtr<NavigationHistoryEntry>>&& aDisposedEntries);
|
||||||
|
|
||||||
|
void LogHistory() const;
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
|
||||||
|
nsTArray<RefPtr<NavigationHistoryEntry>> mEntries;
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry
|
||||||
|
Maybe<uint64_t> mCurrentEntryIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -7,19 +7,131 @@
|
|||||||
#include "mozilla/dom/NavigationHistoryEntry.h"
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
#include "mozilla/dom/NavigationHistoryEntryBinding.h"
|
#include "mozilla/dom/NavigationHistoryEntryBinding.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
|
#include "nsDocShell.h"
|
||||||
|
|
||||||
|
extern mozilla::LazyLogModule gNavigationLog;
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper,
|
||||||
DOMEventTargetHelper);
|
mWindow);
|
||||||
NS_IMPL_ADDREF_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
NS_IMPL_ADDREF_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
||||||
NS_IMPL_RELEASE_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
NS_IMPL_RELEASE_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NavigationHistoryEntry)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NavigationHistoryEntry)
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
NavigationHistoryEntry::NavigationHistoryEntry(
|
||||||
|
nsPIDOMWindowInner* aWindow, const SessionHistoryInfo* aSHInfo,
|
||||||
|
int64_t aIndex)
|
||||||
|
: mWindow(aWindow),
|
||||||
|
mSHInfo(MakeUnique<SessionHistoryInfo>(*aSHInfo)),
|
||||||
|
mIndex(aIndex) {}
|
||||||
|
|
||||||
|
NavigationHistoryEntry::~NavigationHistoryEntry() = default;
|
||||||
|
|
||||||
|
void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
||||||
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SameDocument()) {
|
||||||
|
auto referrerPolicy = GetCurrentDocument()->ReferrerPolicy();
|
||||||
|
if (referrerPolicy == ReferrerPolicy::No_referrer ||
|
||||||
|
referrerPolicy == ReferrerPolicy::Origin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mSHInfo);
|
||||||
|
nsCOMPtr<nsIURI> uri = mSHInfo->GetURI();
|
||||||
|
MOZ_ASSERT(uri);
|
||||||
|
nsCString uriSpec;
|
||||||
|
uri->GetSpec(uriSpec);
|
||||||
|
CopyUTF8toUTF16(uriSpec, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
||||||
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIDToCString keyString(mSHInfo->NavigationKey());
|
||||||
|
// Omit the curly braces and NUL.
|
||||||
|
CopyUTF8toUTF16(Substring(keyString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
||||||
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIDToCString idString(mSHInfo->NavigationId());
|
||||||
|
// Omit the curly braces and NUL.
|
||||||
|
CopyUTF8toUTF16(Substring(idString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t NavigationHistoryEntry::Index() const {
|
||||||
|
MOZ_ASSERT(mSHInfo);
|
||||||
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NavigationHistoryEntry::SameDocument() const {
|
||||||
|
MOZ_ASSERT(mSHInfo);
|
||||||
|
auto* docShell = static_cast<nsDocShell*>(mWindow->GetDocShell());
|
||||||
|
return docShell->IsSameDocumentAsActiveEntry(*mSHInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationHistoryEntry::GetState(JSContext* aCx,
|
||||||
|
JS::MutableHandle<JS::Value> aResult,
|
||||||
|
ErrorResult& aRv) const {
|
||||||
|
if (!mSHInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RefPtr<nsStructuredCloneContainer> state = mSHInfo->GetNavigationState();
|
||||||
|
if (!state) {
|
||||||
|
aResult.setUndefined();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = state->DeserializeToJsval(aCx, aResult);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// TODO change this to specific exception
|
||||||
|
aRv.Throw(rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationHistoryEntry::SetState(nsStructuredCloneContainer* aState) {
|
||||||
|
RefPtr<nsStructuredCloneContainer> state = mSHInfo->GetNavigationState();
|
||||||
|
state->Copy(*aState);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NavigationHistoryEntry::IsSameEntry(
|
||||||
|
const SessionHistoryInfo* aSHInfo) const {
|
||||||
|
return mSHInfo->NavigationId() == aSHInfo->NavigationId();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NavigationHistoryEntry::SharesDocumentWith(
|
||||||
|
const SessionHistoryInfo& aSHInfo) const {
|
||||||
|
return mSHInfo->SharesDocumentWith(aSHInfo);
|
||||||
|
}
|
||||||
|
|
||||||
JSObject* NavigationHistoryEntry::WrapObject(
|
JSObject* NavigationHistoryEntry::WrapObject(
|
||||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
||||||
return NavigationHistoryEntry_Binding::Wrap(aCx, this, aGivenProto);
|
return NavigationHistoryEntry_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Document* NavigationHistoryEntry::GetCurrentDocument() const {
|
||||||
|
return mWindow->GetDoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsID& NavigationHistoryEntry::Key() const {
|
||||||
|
return mSHInfo->NavigationKey();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -9,30 +9,50 @@
|
|||||||
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
|
||||||
|
class nsStructuredCloneContainer;
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class SessionHistoryInfo;
|
||||||
|
|
||||||
class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NavigationHistoryEntry,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NavigationHistoryEntry,
|
||||||
DOMEventTargetHelper)
|
DOMEventTargetHelper)
|
||||||
|
|
||||||
void GetUrl(nsAString& aResult) const {}
|
NavigationHistoryEntry(nsPIDOMWindowInner* aWindow,
|
||||||
void GetKey(nsAString& aResult) const {}
|
const SessionHistoryInfo* aSHInfo, int64_t aIndex);
|
||||||
void GetId(nsAString& aResult) const {}
|
|
||||||
int64_t Index() const { return {}; }
|
void GetUrl(nsAString& aResult) const;
|
||||||
bool SameDocument() const { return {}; }
|
void GetKey(nsAString& aResult) const;
|
||||||
|
void GetId(nsAString& aResult) const;
|
||||||
|
int64_t Index() const;
|
||||||
|
bool SameDocument() const;
|
||||||
|
|
||||||
void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||||
ErrorResult& aRv) {}
|
ErrorResult& aRv) const;
|
||||||
|
void SetState(nsStructuredCloneContainer* aState);
|
||||||
|
|
||||||
IMPL_EVENT_HANDLER(dispose);
|
IMPL_EVENT_HANDLER(dispose);
|
||||||
|
|
||||||
JSObject* WrapObject(JSContext* aCx,
|
JSObject* WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
bool IsSameEntry(const SessionHistoryInfo* aSHInfo) const;
|
||||||
|
|
||||||
|
bool SharesDocumentWith(const SessionHistoryInfo& aSHInfo) const;
|
||||||
|
|
||||||
|
const nsID& Key() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~NavigationHistoryEntry() = default;
|
~NavigationHistoryEntry();
|
||||||
|
|
||||||
|
Document* GetCurrentDocument() const;
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
|
UniquePtr<SessionHistoryInfo> mSHInfo;
|
||||||
|
int64_t mIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
[entries-array-equality.html]
|
[entries-array-equality.html]
|
||||||
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[navigation.entries() should not return an identical object on repeated invocations]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[navigation.entries() should not return an identical object on repeated invocations]
|
|
||||||
expected: FAIL
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
[entries-when-inactive.html]
|
[entries-when-inactive.html]
|
||||||
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[A non-active entry in navigation.entries() should not be modified when a different entry is modified]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[A non-active entry in navigation.entries() should not be modified when a different entry is modified]
|
|
||||||
expected: FAIL
|
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
[key-id-back-same-document.html]
|
[key-id-back-same-document.html]
|
||||||
[NavigationHistoryEntry's key and id on same-document back navigation]
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
expected: FAIL
|
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
[opaque-origin-data-url.html]
|
[opaque-origin-data-url.html]
|
||||||
expected: TIMEOUT
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
[entries() and currentEntry after navigation to a data: URL (which has an opaque origin)]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
[opaque-origin.html]
|
[opaque-origin.html]
|
||||||
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[navigation.currentEntry/entries()/canGoBack/canGoForward in an opaque origin iframe]
|
|
||||||
expected: FAIL
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
[sameDocument-after-fragment-navigate.html]
|
[sameDocument-after-fragment-navigate.html]
|
||||||
|
prefs: [dom.navigation.webidl.enabled:true]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[entry.sameDocument after same-document navigations]
|
|
||||||
expected: FAIL
|
|
||||||
|
|||||||
Reference in New Issue
Block a user