diff options
Diffstat (limited to 'docshell/shistory/SessionHistoryEntry.h')
-rw-r--r-- | docshell/shistory/SessionHistoryEntry.h | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/docshell/shistory/SessionHistoryEntry.h b/docshell/shistory/SessionHistoryEntry.h new file mode 100644 index 0000000000..1b42975390 --- /dev/null +++ b/docshell/shistory/SessionHistoryEntry.h @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_SessionHistoryEntry_h +#define mozilla_dom_SessionHistoryEntry_h + +#include "mozilla/UniquePtr.h" +#include "nsILayoutHistoryState.h" +#include "nsISHEntry.h" +#include "nsSHEntryShared.h" +#include "nsStructuredCloneContainer.h" +#include "nsDataHashtable.h" + +class nsDocShellLoadState; +class nsIChannel; +class nsIInputStream; +class nsIReferrerInfo; +class nsISHistory; +class nsIURI; + +namespace mozilla::ipc { +template <typename P> +struct IPDLParamTraits; +} + +namespace mozilla { +namespace dom { + +struct LoadingSessionHistoryInfo; +class SessionHistoryEntry; +class SHEntrySharedParentState; + +// SessionHistoryInfo stores session history data for a load. It can be sent +// over IPC and is used in both the parent and the child processes. +class SessionHistoryInfo { + public: + SessionHistoryInfo() = default; + SessionHistoryInfo(const SessionHistoryInfo& aInfo) = default; + SessionHistoryInfo(nsDocShellLoadState* aLoadState, nsIChannel* aChannel); + SessionHistoryInfo(const SessionHistoryInfo& aSharedStateFrom, nsIURI* aURI); + SessionHistoryInfo(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal, + nsIPrincipal* aPrincipalToInherit, + nsIPrincipal* aPartitionedPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, + const nsACString& aContentType); + SessionHistoryInfo(nsIChannel* aChannel, uint32_t aLoadType, + nsIPrincipal* aPartitionedPrincipalToInherit, + nsIContentSecurityPolicy* aCsp); + + void Reset(nsIURI* aURI, const nsID& aDocShellID, bool aDynamicCreation, + nsIPrincipal* aTriggeringPrincipal, + nsIPrincipal* aPrincipalToInherit, + nsIPrincipal* aPartitionedPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, const nsACString& aContentType); + + bool operator==(const SessionHistoryInfo& aInfo) const { + return false; // FIXME + } + + nsIURI* GetURI() const { return mURI; } + void SetURI(nsIURI* aURI) { mURI = aURI; } + + void SetOriginalURI(nsIURI* aOriginalURI) { mOriginalURI = aOriginalURI; } + + void SetResultPrincipalURI(nsIURI* aResultPrincipalURI) { + mResultPrincipalURI = aResultPrincipalURI; + } + + nsIInputStream* GetPostData() const { return mPostData; } + void SetPostData(nsIInputStream* aPostData) { mPostData = aPostData; } + + void GetScrollPosition(int32_t* aScrollPositionX, int32_t* aScrollPositionY) { + *aScrollPositionX = mScrollPositionX; + *aScrollPositionY = mScrollPositionY; + } + bool GetScrollRestorationIsManual() const { + return mScrollRestorationIsManual; + } + const nsAString& GetTitle() { return mTitle; } + void SetTitle(const nsAString& aTitle) { + mTitle = aTitle; + MaybeUpdateTitleFromURI(); + } + + const nsAString& GetName() { return mName; } + void SetName(const nsAString& aName) { mName = aName; } + + void SetScrollRestorationIsManual(bool aIsManual) { + mScrollRestorationIsManual = aIsManual; + } + + nsStructuredCloneContainer* GetStateData() const { return mStateData; } + void SetStateData(nsStructuredCloneContainer* aStateData) { + mStateData = aStateData; + } + + void SetLoadReplace(bool aLoadReplace) { mLoadReplace = aLoadReplace; } + + void SetURIWasModified(bool aURIWasModified) { + mURIWasModified = aURIWasModified; + } + bool GetURIWasModified() const { return mURIWasModified; } + + void SetHasUserInteraction(bool aHasUserInteraction) { + mHasUserInteraction = aHasUserInteraction; + } + bool GetHasUserInteraction() const { return mHasUserInteraction; } + + uint64_t SharedId() const; + + nsILayoutHistoryState* GetLayoutHistoryState(); + void SetLayoutHistoryState(nsILayoutHistoryState* aState); + + nsIPrincipal* GetTriggeringPrincipal() const; + + nsIPrincipal* GetPrincipalToInherit() const; + + nsIPrincipal* GetPartitionedPrincipalToInherit() const; + + nsIContentSecurityPolicy* GetCsp() const; + + uint32_t GetCacheKey() const; + void SetCacheKey(uint32_t aCacheKey); + + bool IsSubFrame() const; + + bool SharesDocumentWith(const SessionHistoryInfo& aOther) const { + return SharedId() == aOther.SharedId(); + } + + void FillLoadInfo(nsDocShellLoadState& aLoadState) const; + + uint32_t LoadType() { return mLoadType; } + + private: + friend class SessionHistoryEntry; + friend struct mozilla::ipc::IPDLParamTraits<SessionHistoryInfo>; + + void MaybeUpdateTitleFromURI(); + + nsCOMPtr<nsIURI> mURI; + nsCOMPtr<nsIURI> mOriginalURI; + nsCOMPtr<nsIURI> mResultPrincipalURI; + nsCOMPtr<nsIReferrerInfo> mReferrerInfo; + nsString mTitle; + nsString mName; + nsCOMPtr<nsIInputStream> mPostData; + uint32_t mLoadType = 0; + int32_t mScrollPositionX = 0; + int32_t mScrollPositionY = 0; + RefPtr<nsStructuredCloneContainer> mStateData; + nsString mSrcdocData; + nsCOMPtr<nsIURI> mBaseURI; + + bool mLoadReplace = false; + bool mURIWasModified = false; + bool mIsSrcdocEntry = false; + bool mScrollRestorationIsManual = false; + bool mPersist = true; + bool mHasUserInteraction = false; + + union SharedState { + SharedState(); + explicit SharedState(const SharedState& aOther); + explicit SharedState(const Maybe<const SharedState&>& aOther); + ~SharedState(); + + SharedState& operator=(const SharedState& aOther); + + SHEntrySharedState* Get() const; + + void Set(SHEntrySharedParentState* aState) { mParent = aState; } + + void ChangeId(uint64_t aId); + + static SharedState Create(nsIPrincipal* aTriggeringPrincipal, + nsIPrincipal* aPrincipalToInherit, + nsIPrincipal* aPartitionedPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, + const nsACString& aContentType); + + private: + explicit SharedState(SHEntrySharedParentState* aParent) + : mParent(aParent) {} + explicit SharedState(UniquePtr<SHEntrySharedState>&& aChild) + : mChild(std::move(aChild)) {} + + void Init(); + void Init(const SharedState& aOther); + + // In the parent process this holds a strong reference to the refcounted + // SHEntrySharedParentState. In the child processes this holds an owning + // pointer to a SHEntrySharedState. + RefPtr<SHEntrySharedParentState> mParent; + UniquePtr<SHEntrySharedState> mChild; + }; + + SharedState mSharedState; +}; + +struct LoadingSessionHistoryInfo { + LoadingSessionHistoryInfo() = default; + explicit LoadingSessionHistoryInfo(SessionHistoryEntry* aEntry); + LoadingSessionHistoryInfo(SessionHistoryEntry* aEntry, uint64_t aLoadId); + + already_AddRefed<nsDocShellLoadState> CreateLoadInfo() const; + + SessionHistoryInfo mInfo; + + uint64_t mLoadId = 0; + + // The following three member variables are used to inform about a load from + // the session history. The session-history-in-child approach has just + // an nsISHEntry in the nsDocShellLoadState and access to the nsISHistory, + // but session-history-in-parent needs to pass needed information explicitly + // to the relevant child process. + bool mLoadIsFromSessionHistory = false; + // mRequestedIndex, mSessionHistoryLength and mLoadingCurrentActiveEntry are + // relevant only if mLoadIsFromSessionHistory is true. + int32_t mRequestedIndex = -1; + int32_t mSessionHistoryLength = 0; + // If we're loading from the current active entry we want to treat it as not + // a same-document navigation (see nsDocShell::IsSameDocumentNavigation). + bool mLoadingCurrentActiveEntry = false; +}; + +// SessionHistoryEntry is used to store session history data in the parent +// process. It holds a SessionHistoryInfo, some state shared amongst multiple +// SessionHistoryEntries, a parent and children. +#define NS_SESSIONHISTORYENTRY_IID \ + { \ + 0x5b66a244, 0x8cec, 0x4caa, { \ + 0xaa, 0x0a, 0x78, 0x92, 0xfd, 0x17, 0xa6, 0x67 \ + } \ + } + +class SessionHistoryEntry : public nsISHEntry { + public: + SessionHistoryEntry(nsDocShellLoadState* aLoadState, nsIChannel* aChannel); + SessionHistoryEntry(); + explicit SessionHistoryEntry(SessionHistoryInfo* aInfo); + explicit SessionHistoryEntry(const SessionHistoryEntry& aEntry); + + NS_DECL_ISUPPORTS + NS_DECL_NSISHENTRY + NS_DECLARE_STATIC_IID_ACCESSOR(NS_SESSIONHISTORYENTRY_IID) + + void ReplaceWith(const SessionHistoryEntry& aSource); + + const SessionHistoryInfo& Info() const { return *mInfo; } + + SHEntrySharedParentState* SharedInfo() const; + + void AddChild(SessionHistoryEntry* aChild, int32_t aOffset, + bool aUseRemoteSubframes); + void RemoveChild(SessionHistoryEntry* aChild); + // Finds the child with the same docshell ID as aNewChild, replaces it with + // aNewChild and returns true. If there is no child with the same docshell ID + // then it returns false. + bool ReplaceChild(SessionHistoryEntry* aNewChild); + + void SetInfo(SessionHistoryInfo* aInfo); + + bool ForInitialLoad() { return mForInitialLoad; } + void SetForInitialLoad(bool aForInitialLoad) { + mForInitialLoad = aForInitialLoad; + } + + const nsID& DocshellID() const; + + void SetIsDynamicallyAdded(bool aDynamic); + + // Get an entry based on LoadingSessionHistoryInfo's mLoadId. Parent process + // only. + static SessionHistoryEntry* GetByLoadId(uint64_t aLoadId); + static void SetByLoadId(uint64_t aLoadId, SessionHistoryEntry* aEntry); + static void RemoveLoadId(uint64_t aLoadId); + + const nsTArray<RefPtr<SessionHistoryEntry>>& Children() { return mChildren; } + + private: + friend struct LoadingSessionHistoryInfo; + virtual ~SessionHistoryEntry(); + + UniquePtr<SessionHistoryInfo> mInfo; + nsISHEntry* mParent = nullptr; + uint32_t mID; + nsTArray<RefPtr<SessionHistoryEntry>> mChildren; + + bool mForInitialLoad = false; + + static nsDataHashtable<nsUint64HashKey, SessionHistoryEntry*>* sLoadIdToEntry; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(SessionHistoryEntry, NS_SESSIONHISTORYENTRY_IID) + +} // namespace dom + +namespace ipc { + +class IProtocol; + +// Allow sending SessionHistoryInfo objects over IPC. +template <> +struct IPDLParamTraits<dom::SessionHistoryInfo> { + static void Write(IPC::Message* aMsg, IProtocol* aActor, + const dom::SessionHistoryInfo& aParam); + static bool Read(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, dom::SessionHistoryInfo* aResult); +}; + +// Allow sending LoadingSessionHistoryInfo objects over IPC. +template <> +struct IPDLParamTraits<dom::LoadingSessionHistoryInfo> { + static void Write(IPC::Message* aMsg, IProtocol* aActor, + const dom::LoadingSessionHistoryInfo& aParam); + static bool Read(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, dom::LoadingSessionHistoryInfo* aResult); +}; + +// Allow sending nsILayoutHistoryState objects over IPC. +template <> +struct IPDLParamTraits<nsILayoutHistoryState*> { + static void Write(IPC::Message* aMsg, IProtocol* aActor, + nsILayoutHistoryState* aParam); + static bool Read(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, RefPtr<nsILayoutHistoryState>* aResult); +}; + +} // namespace ipc + +} // namespace mozilla + +#endif /* mozilla_dom_SessionHistoryEntry_h */ |