Backed out 4 changesets (bug 1629866, bug 1570255) for assertion failures on DocumentChannelChild.cpp. CLOSED TREE

Backed out changeset 214e4a11be0d (bug 1570255)
Backed out changeset db066dda1bb8 (bug 1570255)
Backed out changeset d9f75d88613e (bug 1570255)
Backed out changeset fe2d4790b73a (bug 1629866)
This commit is contained in:
Csoregi Natalia
2020-05-13 18:30:42 +03:00
parent 3d578044ee
commit 7f57791502
50 changed files with 4598 additions and 1466 deletions

View File

@@ -37,7 +37,6 @@
#include "mozilla/Logging.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/StaticPrefs_page_load.h"
#include "mozilla/StaticPtr.h"
#include "nsIURIFixup.h"
@@ -360,9 +359,6 @@ void BrowsingContext::CreateFromIPC(BrowsingContext::IPCInitializer&& aInit,
}
context->mWindowless = aInit.mWindowless;
if (aInit.mHasSessionHistory) {
context->InitSessionHistory();
}
// NOTE: Call through the `Set` methods for these values to ensure that any
// relevant process-local state is also updated.
@@ -408,9 +404,6 @@ void BrowsingContext::SetDocShell(nsIDocShell* aDocShell) {
mDocShell = aDocShell;
mDanglingRemoteOuterProxies = !mIsInProcess;
mIsInProcess = true;
if (mChildSessionHistory) {
mChildSessionHistory->SetIsInProcess(true);
}
}
// This class implements a callback that will return the remote window proxy for
@@ -524,10 +517,6 @@ void BrowsingContext::Attach(bool aFromIPC, ContentParent* aOriginProcess) {
PopupBlocker::RegisterOpenPopupSpam();
}
if (IsTop() && GetHasSessionHistory()) {
CreateChildSHistory();
}
if (XRE_IsContentProcess() && !aFromIPC) {
// Send attach to our parent if we need to.
ContentChild::GetSingleton()->SendCreateBrowsingContext(
@@ -637,11 +626,6 @@ void BrowsingContext::PrepareForProcessChange() {
// different process now. This may need to change in the future with
// Cross-Process BFCache.
mDocShell = nullptr;
if (mChildSessionHistory) {
// This can be removed once session history is stored exclusively in the
// parent process.
mChildSessionHistory->SetIsInProcess(false);
}
if (!mWindowProxy) {
return;
@@ -1402,16 +1386,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
tmp->mFields.SetWithoutSyncing<IDX_IsPopupSpam>(false);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(
mDocShell, mParentWindow, mGroup, mEmbedderElement, mWindowContexts,
mCurrentWindowContext, mSessionStorageManager, mChildSessionHistory)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mParentWindow, mGroup,
mEmbedderElement, mWindowContexts,
mCurrentWindowContext, mSessionStorageManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
mDocShell, mParentWindow, mGroup, mEmbedderElement, mWindowContexts,
mCurrentWindowContext, mSessionStorageManager, mChildSessionHistory)
mCurrentWindowContext, mSessionStorageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
class RemoteLocationProxy
@@ -1790,7 +1774,6 @@ BrowsingContext::IPCInitializer BrowsingContext::GetIPCInitializer() {
init.mUseRemoteTabs = mUseRemoteTabs;
init.mUseRemoteSubframes = mUseRemoteSubframes;
init.mOriginAttributes = mOriginAttributes;
init.mHasSessionHistory = mChildSessionHistory != nullptr;
init.mFields = mFields.Fields();
return init;
}
@@ -2216,55 +2199,6 @@ void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
EventQueuePriority::Idle);
}
void BrowsingContext::InitSessionHistory() {
MOZ_ASSERT(!IsDiscarded());
MOZ_ASSERT(IsTop());
MOZ_ASSERT(EverAttached());
if (!GetHasSessionHistory()) {
SetHasSessionHistory(true);
// If the top browsing context (this one) is loaded in this process then we
// also create the session history implementation for the child process.
// This can be removed once session history is stored exclusively in the
// parent process.
mChildSessionHistory->SetIsInProcess(mDocShell);
}
}
ChildSHistory* BrowsingContext::GetChildSessionHistory() {
if (!StaticPrefs::fission_sessionHistoryInParent()) {
// For now we're checking that the session history object for the child
// process is available before returning the ChildSHistory object, because
// it is the actual implementation that ChildSHistory forwards to. This can
// be removed once session history is stored exclusively in the parent
// process.
return mChildSessionHistory && mChildSessionHistory->IsInProcess()
? mChildSessionHistory.get()
: nullptr;
}
return mChildSessionHistory;
}
void BrowsingContext::CreateChildSHistory() {
MOZ_ASSERT(IsTop());
// Because session history is global in a browsing context tree, every process
// that has access to a browsing context tree needs access to its session
// history. That is why we create the ChildSHistory object in every process
// where we have access to this browsing context (which is the top one).
mChildSessionHistory = new ChildSHistory(this);
}
void BrowsingContext::DidSet(FieldIndex<IDX_HasSessionHistory>,
bool aOldValue) {
MOZ_ASSERT(GetHasSessionHistory() || !aOldValue,
"We don't support turning off session history.");
CreateChildSHistory();
}
} // namespace dom
namespace ipc {

View File

@@ -61,7 +61,6 @@ namespace dom {
class BrowsingContent;
class BrowsingContextGroup;
class CanonicalBrowsingContext;
class ChildSHistory;
class ContentParent;
class Element;
template <typename>
@@ -133,11 +132,7 @@ class WindowProxyHolder;
FIELD(WatchedByDevToolsInternal, bool) \
FIELD(TextZoom, float) \
/* See nsIRequest for possible flags. */ \
FIELD(DefaultLoadFlags, uint32_t) \
/* Signals that session history is enabled for this browsing context tree. \
* This is only ever set to true on the top BC, so consumers need to get \
* the value from the top BC! */ \
FIELD(HasSessionHistory, bool)
FIELD(DefaultLoadFlags, uint32_t)
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
@@ -562,7 +557,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool mWindowless = false;
bool mUseRemoteTabs = false;
bool mUseRemoteSubframes = false;
bool mHasSessionHistory = false;
OriginAttributes mOriginAttributes;
FieldTuple mFields;
@@ -603,13 +597,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
nsresult SetOriginAttributes(const OriginAttributes& aAttrs);
// This should only be called on the top browsing context.
void InitSessionHistory();
// This will only ever return a non-null value if called on the top browsing
// context.
ChildSHistory* GetChildSessionHistory();
protected:
virtual ~BrowsingContext();
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
@@ -750,8 +737,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_UseGlobalHistory>, const bool& aUseGlobalHistory,
ContentParent* aSource);
void DidSet(FieldIndex<IDX_HasSessionHistory>, bool aOldValue);
template <size_t I, typename T>
bool CanSet(FieldIndex<I>, const T&, ContentParent*) {
return true;
@@ -776,8 +761,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// process.
bool CheckOnlyEmbedderCanSet(ContentParent* aSource);
void CreateChildSHistory();
// Type of BrowsingContent
const Type mType;
@@ -872,8 +855,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
mozilla::LinkedList<DeprioritizedLoadRunner> mDeprioritizedLoadRunner;
RefPtr<SessionStorageManager> mSessionStorageManager;
RefPtr<ChildSHistory> mChildSessionHistory;
RefPtr<dom::SessionStorageManager> mSessionStorageManager;
};
/**

View File

@@ -18,14 +18,12 @@
#include "mozilla/dom/MediaController.h"
#include "mozilla/dom/MediaControlService.h"
#include "mozilla/dom/ContentPlaybackController.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/net/DocumentLoadListener.h"
#include "mozilla/NullPrincipal.h"
#include "nsGlobalWindowOuter.h"
#include "nsIWebBrowserChrome.h"
#include "nsNetUtil.h"
#include "nsSHistory.h"
using namespace mozilla::ipc;
@@ -188,77 +186,19 @@ CanonicalBrowsingContext::GetParentCrossChromeBoundary() {
}
nsISHistory* CanonicalBrowsingContext::GetSessionHistory() {
if (!IsTop()) {
return Cast(Top())->GetSessionHistory();
if (mSessionHistory) {
return mSessionHistory;
}
// Check GetChildSessionHistory() to make sure that this BrowsingContext has
// session history enabled.
if (!mSessionHistory && GetChildSessionHistory()) {
mSessionHistory = new nsSHistory(this);
}
return mSessionHistory;
}
static uint64_t gNextHistoryEntryId = 0;
UniquePtr<SessionHistoryInfoAndId>
CanonicalBrowsingContext::CreateSessionHistoryEntryForLoad(
nsDocShellLoadState* aLoadState, nsIChannel* aChannel) {
MOZ_ASSERT(GetSessionHistory(),
"Creating an entry but session history is not enabled for this "
"browsing context!");
uint64_t id = ++gNextHistoryEntryId;
RefPtr<SessionHistoryEntry> entry =
new SessionHistoryEntry(GetSessionHistory(), aLoadState, aChannel);
mLoadingEntries.AppendElement(SessionHistoryEntryAndId(id, entry));
return MakeUnique<SessionHistoryInfoAndId>(
id, MakeUnique<SessionHistoryInfo>(entry->GetInfo()));
}
void CanonicalBrowsingContext::SessionHistoryCommit(
uint64_t aSessionHistoryEntryId) {
for (size_t i = 0; i < mLoadingEntries.Length(); ++i) {
if (mLoadingEntries[i].mId == aSessionHistoryEntryId) {
RefPtr<SessionHistoryEntry> oldActiveEntry = mActiveEntry.forget();
mActiveEntry = mLoadingEntries[i].mEntry;
mLoadingEntries.RemoveElementAt(i);
if (IsTop()) {
GetSessionHistory()->AddEntry(mActiveEntry,
/* FIXME aPersist = */ true);
} else {
// FIXME Check if we're replacing before adding a child.
// FIXME The old implementations adds it to the parent's mLSHE if there
// is one, need to figure out if that makes sense here (peterv
// doesn't think it would).
if (oldActiveEntry) {
// FIXME Need to figure out the right value for aCloneChildren.
GetSessionHistory()->AddChildSHEntryHelper(oldActiveEntry,
mActiveEntry, Top(), true);
} else {
SessionHistoryEntry* parentEntry =
static_cast<CanonicalBrowsingContext*>(GetParent())->mActiveEntry;
if (parentEntry) {
// FIXME The docshell code sometime uses -1 for aChildOffset!
// FIXME Using IsInProcess for aUseRemoteSubframes isn't quite
// right, but aUseRemoteSubframes should be going away.
parentEntry->AddChild(mActiveEntry, Children().Length() - 1,
IsInProcess());
}
}
}
Group()->EachParent([&](ContentParent* aParent) {
// FIXME Should we return the length to the one process that committed
// as an async return value? Or should this use synced fields?
Unused << aParent->SendHistoryCommitLength(
Top(), GetSessionHistory()->GetCount());
});
return;
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(GetDocShell());
if (webNav) {
RefPtr<ChildSHistory> shistory = webNav->GetSessionHistory();
if (shistory) {
return shistory->LegacySHistory();
}
}
// FIXME Should we throw an error if we don't find an entry for
// aSessionHistoryEntryId?
return nullptr;
}
JSObject* CanonicalBrowsingContext::WrapObject(

View File

@@ -13,11 +13,10 @@
#include "mozilla/MozPromise.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
#include "nsHashKeys.h"
class nsISHistory;
#include "nsISHistory.h"
#include "nsISHEntry.h"
namespace mozilla {
namespace net {
@@ -26,20 +25,11 @@ class DocumentLoadListener;
namespace dom {
class WindowGlobalParent;
class BrowserParent;
class MediaController;
struct SessionHistoryInfoAndId;
class SessionHistoryEntry;
class WindowGlobalParent;
struct SessionHistoryEntryAndId {
SessionHistoryEntryAndId(uint64_t aId, SessionHistoryEntry* aEntry)
: mId(aId), mEntry(aEntry) {}
uint64_t mId;
RefPtr<SessionHistoryEntry> mEntry;
};
// CanonicalBrowsingContext is a BrowsingContext living in the parent
// process, with whatever extra data that a BrowsingContext in the
// parent needs.
@@ -93,10 +83,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {
already_AddRefed<CanonicalBrowsingContext> GetParentCrossChromeBoundary();
nsISHistory* GetSessionHistory();
UniquePtr<SessionHistoryInfoAndId> CreateSessionHistoryEntryForLoad(
nsDocShellLoadState* aLoadState, nsIChannel* aChannel);
void SessionHistoryCommit(uint64_t aSessionHistoryEntryId);
void SetSessionHistory(nsISHistory* aSHistory) {
mSessionHistory = aSHistory;
}
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@@ -141,6 +130,25 @@ class CanonicalBrowsingContext final : public BrowsingContext {
bool AttemptLoadURIInParent(nsDocShellLoadState* aLoadState,
uint32_t* aLoadIdentifier);
bool HasHistoryEntry(nsISHEntry* aEntry) const {
return aEntry && (aEntry == mOSHE || aEntry == mLSHE);
}
void UpdateSHEntries(nsISHEntry* aNewLSHE, nsISHEntry* aNewOSHE) {
mLSHE = aNewLSHE;
mOSHE = aNewOSHE;
}
void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry) {
if (aOldEntry == mOSHE) {
mOSHE = aNewEntry;
}
if (aOldEntry == mLSHE) {
mLSHE = aNewEntry;
}
}
protected:
// Called when the browsing context is being discarded.
void CanonicalDiscard();
@@ -214,8 +222,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<net::DocumentLoadListener> mCurrentLoad;
nsTArray<SessionHistoryEntryAndId> mLoadingEntries;
RefPtr<SessionHistoryEntry> mActiveEntry;
// These are being mirrored from docshell
nsCOMPtr<nsISHEntry> mOSHE;
nsCOMPtr<nsISHEntry> mLSHE;
};
} // namespace dom

View File

@@ -66,7 +66,6 @@
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ServiceWorkerInterceptController.h"
#include "mozilla/dom/ServiceWorkerUtils.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/SessionStorageManager.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/ToJSValue.h"
@@ -199,7 +198,7 @@
#include "nsSandboxFlags.h"
#include "nsSHEntry.h"
#include "nsSHistory.h"
#include "nsSHEntry.h"
#include "SHEntryChild.h"
#include "nsStructuredCloneContainer.h"
#include "nsSubDocumentFrame.h"
#include "nsView.h"
@@ -424,6 +423,10 @@ nsDocShell::~nsDocShell() {
Destroy();
if (mSessionHistory) {
mSessionHistory->LegacySHistory()->ClearRootBrowsingContext();
}
if (mContentViewer) {
mContentViewer->Close(nullptr);
mContentViewer->Destroy();
@@ -541,7 +544,7 @@ void nsDocShell::DestroyChildren() {
NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(nsDocShell, nsDocLoader,
mScriptGlobal, mInitialClientSource,
mBrowsingContext,
mSessionHistory, mBrowsingContext,
mChromeEventHandler)
NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
@@ -2952,8 +2955,8 @@ nsresult nsDocShell::AddChildSHEntryInternal(nsISHEntry* aCloneRef,
uint32_t aLoadType,
bool aCloneChildren) {
nsresult rv = NS_OK;
if (GetSessionHistory()) {
rv = GetSessionHistory()->LegacySHistory()->AddChildSHEntryHelper(
if (mSessionHistory) {
rv = mSessionHistory->LegacySHistory()->AddChildSHEntryHelper(
aCloneRef, aNewEntry, mBrowsingContext, aCloneChildren);
} else {
/* Just pass this along */
@@ -3007,8 +3010,13 @@ nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
NS_IMETHODIMP
nsDocShell::RemoveFromSessionHistory() {
RefPtr<ChildSHistory> sessionHistory =
mBrowsingContext->Top()->GetChildSessionHistory();
nsCOMPtr<nsIDocShellTreeItem> root;
GetInProcessSameTypeRootTreeItem(getter_AddRefs(root));
nsCOMPtr<nsIWebNavigation> rootAsWebnav = do_QueryInterface(root);
if (!rootAsWebnav) {
return NS_OK;
}
RefPtr<ChildSHistory> sessionHistory = rootAsWebnav->GetSessionHistory();
if (!sessionHistory) {
return NS_OK;
}
@@ -4073,10 +4081,26 @@ nsDocShell::GetCurrentURI(nsIURI** aURI) {
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::InitSessionHistory() {
MOZ_ASSERT(!mIsBeingDestroyed);
// Make sure that we are the root DocShell, and set a handle to root docshell
// in the session history.
nsCOMPtr<nsIDocShellTreeItem> root;
GetInProcessSameTypeRootTreeItem(getter_AddRefs(root));
if (root != this) {
return NS_ERROR_FAILURE;
}
mSessionHistory = new ChildSHistory(this);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
NS_ENSURE_ARG_POINTER(aSessionHistory);
RefPtr<ChildSHistory> shistory = GetSessionHistory();
RefPtr<ChildSHistory> shistory = mSessionHistory;
shistory.forget(aSessionHistory);
return NS_OK;
}
@@ -4297,11 +4321,12 @@ nsDocShell::Destroy() {
mScriptGlobal = nullptr;
}
if (GetSessionHistory()) {
if (mSessionHistory) {
// We want to destroy these content viewers now rather than
// letting their destruction wait for the session history
// entries to get garbage collected. (Bug 488394)
GetSessionHistory()->EvictLocalContentViewers();
mSessionHistory->EvictLocalContentViewers();
mSessionHistory = nullptr;
}
if (mWillChangeProcess) {
@@ -5470,18 +5495,6 @@ nsresult nsDocShell::Embed(nsIContentViewer* aContentViewer,
SetDocCurrentStateObj(mLSHE);
SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
if (StaticPrefs::fission_sessionHistoryInParent()) {
mActiveEntry = nullptr;
mLoadingEntry.swap(mActiveEntry);
if (XRE_IsParentProcess()) {
mBrowsingContext->Canonical()->SessionHistoryCommit(mLoadingEntryId);
} else {
ContentChild* cc = ContentChild::GetSingleton();
mozilla::Unused << cc->SendHistoryCommit(mBrowsingContext,
mLoadingEntryId);
}
mLoadingEntryId = 0;
}
}
bool updateHistory = true;
@@ -7507,13 +7520,13 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
// Be sure to have a correct mLSHE, it may have been cleared by
// EndPageLoad. See bug 302115.
ChildSHistory* shistory = GetSessionHistory();
if (shistory && !mLSHE) {
int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
if (mSessionHistory && !mLSHE) {
int32_t idx = mSessionHistory->LegacySHistory()->GetRequestedIndex();
if (idx == -1) {
idx = shistory->Index();
idx = mSessionHistory->Index();
}
shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
mSessionHistory->LegacySHistory()->GetEntryAtIndex(idx,
getter_AddRefs(mLSHE));
}
mLoadType = LOAD_ERROR_PAGE;
@@ -8433,11 +8446,11 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
/* Set the title for the SH entry for this target url. so that
* SH menus in go/back/forward buttons won't be empty for this.
*/
ChildSHistory* shistory = GetSessionHistory();
if (shistory) {
int32_t index = shistory->Index();
if (mSessionHistory) {
int32_t index = mSessionHistory->Index();
nsCOMPtr<nsISHEntry> shEntry;
shistory->LegacySHistory()->GetEntryAtIndex(index, getter_AddRefs(shEntry));
mSessionHistory->LegacySHistory()->GetEntryAtIndex(index,
getter_AddRefs(shEntry));
NS_ENSURE_TRUE(shEntry, NS_ERROR_FAILURE);
shEntry->SetTitle(mTitle);
}
@@ -9471,15 +9484,6 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
"DoURILoad thinks this is a document and InternalLoad does not");
}
// FIXME We still have a ton of codepaths that don't pass through
// DocumentLoadListener, so probably need to create session history info
// in more places.
if (aLoadState->GetSessionHistoryID() != 0) {
mLoadingEntry =
MakeUnique<SessionHistoryInfo>(aLoadState->GetSessionHistoryInfo());
mLoadingEntryId = aLoadState->GetSessionHistoryID();
}
// open a channel for the url
// If we have a pending channel, use the channel we've already created here.
@@ -10091,9 +10095,12 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
(IsForceReloadType(aLoadType) && IsFrame()));
// Create SH Entry (mLSHE) only if there is a SessionHistory object in the
// in the root browsing context.
RefPtr<ChildSHistory> rootSH =
mBrowsingContext->Top()->GetChildSessionHistory();
// current frame or in the root docshell.
RefPtr<ChildSHistory> rootSH = mSessionHistory;
if (!rootSH) {
// Get the handle to SH from the root docshell
rootSH = GetRootSessionHistory();
}
if (!rootSH) {
updateSHistory = false;
updateGHistory = false; // XXX Why global history too?
@@ -10196,11 +10203,11 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
aPrincipalToInherit, aStoragePrincipalToInherit,
aCsp, aCloneSHChildren, getter_AddRefs(mLSHE));
}
} else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
} else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
// Even if we don't add anything to SHistory, ensure the current index
// points to the same SHEntry as our mLSHE.
GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(mLSHE);
mSessionHistory->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(mLSHE);
}
// If this is a POST request, we do not want to include this in global
@@ -10710,7 +10717,9 @@ nsresult nsDocShell::AddToSessionHistory(
NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
RefPtr<ChildSHistory> shistory = webnav->GetSessionHistory();
entry = new nsSHEntry(shistory ? shistory->LegacySHistory() : nullptr);
entry = CreateSHEntryForDocShell(shistory ? shistory->LegacySHistory()
: nullptr);
NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
}
// Get the post data & referrer
@@ -10837,11 +10846,11 @@ nsresult nsDocShell::AddToSessionHistory(
loadReplace, referrerInfo, srcdoc, srcdocEntry, baseURI,
saveLayoutState, expired);
if (root == static_cast<nsIDocShellTreeItem*>(this) && GetSessionHistory()) {
if (root == static_cast<nsIDocShellTreeItem*>(this) && mSessionHistory) {
bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
Maybe<int32_t> previousEntryIndex;
Maybe<int32_t> loadedEntryIndex;
rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
rv = mSessionHistory->LegacySHistory()->AddToRootSessionHistory(
aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
shouldPersist, &previousEntryIndex, &loadedEntryIndex);
@@ -10999,6 +11008,24 @@ void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
MOZ_ASSERT(mOSHE.get() == aOSHE.value());
}
// Do not update the BC if the SH pref is off and we are not a parent process
// or if it is discarded
if ((!StaticPrefs::fission_sessionHistoryInParent() &&
XRE_IsContentProcess()) ||
mBrowsingContext->IsDiscarded()) {
return;
}
if (XRE_IsParentProcess()) {
// We are in the parent process, thus we can update the entries directly
mBrowsingContext->Canonical()->UpdateSHEntries(mLSHE, mOSHE);
} else {
ContentChild* cc = ContentChild::GetSingleton();
// We can't update canonical BC directly, so do it over IPC call
cc->SendUpdateSHEntriesInBC(static_cast<SHEntryChild*>(mLSHE.get()),
static_cast<SHEntryChild*>(mOSHE.get()),
mBrowsingContext);
}
}
already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
@@ -12232,9 +12259,9 @@ nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
// If we're performing a history load, locate the correct history entry,
// and set the relevant bits on our loadState.
if (aHistoryIndex >= 0 && self->GetSessionHistory()) {
if (aHistoryIndex >= 0 && self->mSessionHistory) {
nsCOMPtr<nsISHistory> legacySHistory =
self->GetSessionHistory()->LegacySHistory();
self->mSessionHistory->LegacySHistory();
nsCOMPtr<nsISHEntry> entry;
nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,

View File

@@ -64,7 +64,6 @@ namespace dom {
class ClientInfo;
class ClientSource;
class EventTarget;
class SessionHistoryInfo;
} // namespace dom
namespace net {
class LoadInfo;
@@ -663,10 +662,6 @@ class nsDocShell final : public nsDocLoader,
void SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
const Maybe<nsISHEntry*>& aOSHE);
mozilla::dom::ChildSHistory* GetSessionHistory() {
return mBrowsingContext->GetChildSessionHistory();
}
//
// URI Load
//
@@ -1133,11 +1128,6 @@ class nsDocShell final : public nsDocLoader,
// parent has loaded does. (This isn't the only purpose of mLSHE.)
nsCOMPtr<nsISHEntry> mLSHE;
// These are only set when fission.sessionHistoryInParent is set.
mozilla::UniquePtr<mozilla::dom::SessionHistoryInfo> mActiveEntry;
mozilla::UniquePtr<mozilla::dom::SessionHistoryInfo> mLoadingEntry;
uint64_t mLoadingEntryId;
// Holds a weak pointer to a RestorePresentationEvent object if any that
// holds a weak pointer back to us. We use this pointer to possibly revoke
// the event whenever necessary.

View File

@@ -6,6 +6,8 @@
#include "nsDocShellLoadState.h"
#include "nsIDocShell.h"
#include "SHEntryParent.h"
#include "SHEntryChild.h"
#include "nsDocShell.h"
#include "nsISHEntry.h"
#include "nsIURIFixup.h"
@@ -133,6 +135,14 @@ nsDocShellLoadState::nsDocShellLoadState(
mHeadersStream = aLoadState.HeadersStream();
mSrcdocData = aLoadState.SrcdocData();
mLoadIdentifier = aLoadState.LoadIdentifier();
if (!aLoadState.SHEntry() || !StaticPrefs::fission_sessionHistoryInParent()) {
return;
}
if (XRE_IsParentProcess()) {
mSHEntry = static_cast<LegacySHEntry*>(aLoadState.SHEntry());
} else {
mSHEntry = static_cast<SHEntryChild*>(aLoadState.SHEntry());
}
}
nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
@@ -488,20 +498,6 @@ void nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry) {
mSHEntry = aSHEntry;
}
void nsDocShellLoadState::SetSessionHistoryInfo(
const mozilla::dom::SessionHistoryInfoAndId& aIdAndInfo) {
mSessionHistoryInfo = aIdAndInfo;
}
uint64_t nsDocShellLoadState::GetSessionHistoryID() const {
return mSessionHistoryInfo.mId;
}
const mozilla::dom::SessionHistoryInfo&
nsDocShellLoadState::GetSessionHistoryInfo() const {
return *mSessionHistoryInfo.mInfo;
}
const nsString& nsDocShellLoadState::Target() const { return mTarget; }
void nsDocShellLoadState::SetTarget(const nsAString& aTarget) {
@@ -881,5 +877,18 @@ DocShellLoadStateInit nsDocShellLoadState::Serialize() {
loadState.SrcdocData() = mSrcdocData;
loadState.ResultPrincipalURI() = mResultPrincipalURI;
loadState.LoadIdentifier() = mLoadIdentifier;
if (!mSHEntry || !StaticPrefs::fission_sessionHistoryInParent()) {
// Without the pref, we don't have an actor for shentry and thus
// we can't serialize it. We could write custom (de)serializers,
// but a session history rewrite is on the way anyway.
return loadState;
}
if (XRE_IsParentProcess()) {
loadState.SHEntry() = static_cast<CrossProcessSHEntry*>(
static_cast<LegacySHEntry*>(mSHEntry.get()));
} else {
loadState.SHEntry() = static_cast<CrossProcessSHEntry*>(
static_cast<SHEntryChild*>(mSHEntry.get()));
}
return loadState;
}

View File

@@ -8,13 +8,11 @@
#define nsDocShellLoadState_h__
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/SessionHistoryEntry.h"
// Helper Classes
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsDocShellLoadTypes.h"
#include "nsTArrayForwardDeclare.h"
class nsIContentSecurityPolicy;
class nsIInputStream;
@@ -129,12 +127,6 @@ class nsDocShellLoadState final {
void SetSHEntry(nsISHEntry* aSHEntry);
const mozilla::dom::SessionHistoryInfo& GetSessionHistoryInfo() const;
uint64_t GetSessionHistoryID() const;
void SetSessionHistoryInfo(
const mozilla::dom::SessionHistoryInfoAndId& aIdAndInfo);
const nsString& Target() const;
void SetTarget(const nsAString& aTarget);
@@ -350,9 +342,6 @@ class nsDocShellLoadState final {
// Active Session History entry (if loading from SH)
nsCOMPtr<nsISHEntry> mSHEntry;
// Session history info for the load
mozilla::dom::SessionHistoryInfoAndId mSessionHistoryInfo;
// Target for load, like _content, _blank etc.
nsString mTarget;

View File

@@ -987,6 +987,12 @@ interface nsIDocShell : nsIDocShellTreeItem
Array<float> getColorMatrix();
/**
* Initialize session history for this docshell. The docshell must be the root
* docshell.
*/
void initSessionHistory();
%{C++
/**
* These methods call nsDocShell::GetHTMLEditorInternal() and

View File

@@ -6,6 +6,7 @@
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/SHEntryChild.h"
// session history
#include "nsSHEntryShared.h"
@@ -18,10 +19,14 @@ nsresult InitDocShellModule() {
mozilla::dom::BrowsingContext::Init();
nsresult rv = nsSHistory::Startup();
NS_ENSURE_SUCCESS(rv, rv);
mozilla::dom::SHEntryChildShared::Init();
return NS_OK;
}
void UnloadDocShellModule() { nsSHistory::Shutdown(); }
void UnloadDocShellModule() {
nsSHistory::Shutdown();
nsSHEntryShared::Shutdown();
}
} // namespace mozilla

View File

@@ -8,6 +8,8 @@
#include "mozilla/dom/ChildSHistoryBinding.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentFrameMessageManager.h"
#include "mozilla/dom/SHEntryChild.h"
#include "mozilla/dom/SHistoryChild.h"
#include "mozilla/StaticPrefs_fission.h"
#include "nsComponentManagerUtils.h"
#include "nsSHEntry.h"
@@ -18,29 +20,24 @@
namespace mozilla {
namespace dom {
ChildSHistory::ChildSHistory(BrowsingContext* aBrowsingContext)
: mBrowsingContext(aBrowsingContext) {}
void ChildSHistory::SetIsInProcess(bool aIsInProcess) {
if (!aIsInProcess) {
mHistory = nullptr;
return;
static already_AddRefed<nsISHistory> CreateSHistory(nsDocShell* aDocShell) {
if (XRE_IsContentProcess() && StaticPrefs::fission_sessionHistoryInParent()) {
return do_AddRef(static_cast<SHistoryChild*>(
ContentChild::GetSingleton()->SendPSHistoryConstructor(
aDocShell->GetBrowsingContext())));
}
if (mHistory) {
return;
}
mHistory = new nsSHistory(mBrowsingContext);
nsCOMPtr<nsISHistory> history =
new nsSHistory(aDocShell->GetBrowsingContext(), aDocShell->HistoryID());
return history.forget();
}
int32_t ChildSHistory::Count() {
if (StaticPrefs::fission_sessionHistoryInParent()) {
return mLength;
}
return mHistory->GetCount();
}
ChildSHistory::ChildSHistory(nsDocShell* aDocShell)
: mDocShell(aDocShell), mHistory(CreateSHistory(aDocShell)) {}
ChildSHistory::~ChildSHistory() {}
int32_t ChildSHistory::Count() { return mHistory->GetCount(); }
int32_t ChildSHistory::Index() {
int32_t index;
@@ -68,19 +65,7 @@ void ChildSHistory::Go(int32_t aOffset, ErrorResult& aRv) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (StaticPrefs::fission_sessionHistoryInParent()) {
nsCOMPtr<nsISHistory> shistory = mHistory;
ContentChild::GetSingleton()->SendHistoryGo(
mBrowsingContext, index.value(),
[shistory](int32_t&& aRequestedIndex) {
// FIXME Should probably only do this for non-fission.
shistory->InternalSetRequestedIndex(aRequestedIndex);
},
[](mozilla::ipc::
ResponseRejectReason) { /* FIXME Is ignoring this fine? */ });
} else {
aRv = mHistory->GotoIndex(index.value());
}
aRv = mHistory->GotoIndex(index.value());
}
void ChildSHistory::AsyncGo(int32_t aOffset) {
@@ -102,10 +87,7 @@ void ChildSHistory::EvictLocalContentViewers() {
mHistory->EvictAllContentViewers();
}
nsISHistory* ChildSHistory::LegacySHistory() {
MOZ_RELEASE_ASSERT(mHistory);
return mHistory;
}
nsISHistory* ChildSHistory::LegacySHistory() { return mHistory; }
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChildSHistory)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -115,7 +97,7 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(ChildSHistory)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ChildSHistory)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ChildSHistory, mBrowsingContext, mHistory)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ChildSHistory, mDocShell, mHistory)
JSObject* ChildSHistory::WrapObject(JSContext* cx,
JS::Handle<JSObject*> aGivenProto) {
@@ -123,7 +105,26 @@ JSObject* ChildSHistory::WrapObject(JSContext* cx,
}
nsISupports* ChildSHistory::GetParentObject() const {
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
// We want to get the BrowserChildMessageManager, which is the
// messageManager on mDocShell.
RefPtr<ContentFrameMessageManager> mm;
if (mDocShell) {
mm = mDocShell->GetMessageManager();
}
// else we must be unlinked... can that happen here?
return ToSupports(mm);
}
already_AddRefed<nsISHEntry> CreateSHEntryForDocShell(nsISHistory* aSHistory) {
uint64_t sharedID = SHEntryChildShared::CreateSharedID();
if (XRE_IsContentProcess() && StaticPrefs::fission_sessionHistoryInParent()) {
return do_AddRef(static_cast<SHEntryChild*>(
ContentChild::GetSingleton()->SendPSHEntryConstructor(
static_cast<SHistoryChild*>(aSHistory), sharedID)));
}
nsCOMPtr<nsISHEntry> entry = new nsLegacySHEntry(aSHistory, sharedID);
return entry.forget();
}
} // namespace dom

View File

@@ -25,14 +25,16 @@
#include "nsThreadUtils.h"
#include "mozilla/LinkedList.h"
class nsSHistory;
class nsDocShell;
class nsISHEntry;
class nsISHistory;
class nsIWebNavigation;
class nsIGlobalObject;
namespace mozilla {
namespace dom {
class BrowsingContext;
class ChildSHistory : public nsISupports, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -41,13 +43,7 @@ class ChildSHistory : public nsISupports, public nsWrapperCache {
JSObject* WrapObject(JSContext* cx,
JS::Handle<JSObject*> aGivenProto) override;
explicit ChildSHistory(BrowsingContext* aBrowsingContext);
// Create or destroy the session history implementation in the child process.
// This can be removed once session history is stored exclusively in the
// parent process.
void SetIsInProcess(bool aIsInProcess);
bool IsInProcess() { return !!mHistory; }
explicit ChildSHistory(nsDocShell* aDocShell);
int32_t Count();
int32_t Index();
@@ -75,10 +71,8 @@ class ChildSHistory : public nsISupports, public nsWrapperCache {
nsISHistory* LegacySHistory();
void SetLength(uint32_t aLength) { mLength = aLength; }
private:
virtual ~ChildSHistory() = default;
virtual ~ChildSHistory();
class PendingAsyncHistoryNavigation
: public Runnable,
@@ -102,12 +96,13 @@ class ChildSHistory : public nsISupports, public nsWrapperCache {
int32_t mOffset;
};
RefPtr<BrowsingContext> mBrowsingContext;
RefPtr<nsDocShell> mDocShell;
nsCOMPtr<nsISHistory> mHistory;
mozilla::LinkedList<PendingAsyncHistoryNavigation> mPendingNavigations;
uint32_t mLength = 0;
};
already_AddRefed<nsISHEntry> CreateSHEntryForDocShell(nsISHistory* aSHistory);
} // namespace dom
} // namespace mozilla

View File

@@ -0,0 +1,101 @@
/* -*- 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/. */
#include "mozilla/dom/MaybeNewPSHEntry.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PContentParent.h"
#include "mozilla/dom/PSHistoryParent.h"
#include "mozilla/dom/SHEntryChild.h"
#include "mozilla/dom/SHEntryParent.h"
#include "mozilla/dom/SHistoryChild.h"
namespace mozilla {
namespace ipc {
template <>
struct IPDLParamTraits<dom::NewPSHEntry> {
static void Write(IPC::Message* aMsg, IProtocol* aActor,
dom::NewPSHEntry&& aEntry) {
MOZ_RELEASE_ASSERT(aActor->GetSide() == ParentSide, "wrong side!");
WriteIPDLParam(aMsg, aActor, std::move(aEntry.mEndpoint));
WriteIPDLParam(aMsg, aActor, aEntry.mSHistoryParent);
WriteIPDLParam(aMsg, aActor, aEntry.mSharedID);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, dom::NewPSHEntry* aEntry) {
MOZ_RELEASE_ASSERT(aActor->GetSide() == ChildSide, "wrong side!");
return ReadIPDLParam(aMsg, aIter, aActor, &aEntry->mEndpoint) &&
ReadIPDLParam(aMsg, aIter, aActor, &aEntry->mSHistoryChild) &&
ReadIPDLParam(aMsg, aIter, aActor, &aEntry->mSharedID);
}
};
/* static */
void IPDLParamTraits<dom::CrossProcessSHEntry*>::Write(
IPC::Message* aMsg, IProtocol* aActor, dom::CrossProcessSHEntry* aEntry) {
MOZ_DIAGNOSTIC_ASSERT(aActor->ToplevelProtocol()->GetProtocolId() ==
PContentMsgStart);
if (aActor->GetSide() == ChildSide) {
WriteIPDLParam(aMsg, aActor,
static_cast<dom::PSHEntryChild*>(
static_cast<dom::SHEntryChild*>(aEntry)));
return;
}
dom::MaybeNewPSHEntryParent entry(static_cast<dom::PSHEntryParent*>(nullptr));
if (aEntry) {
entry = static_cast<dom::LegacySHEntry*>(aEntry)->GetOrCreateActor(
static_cast<dom::PContentParent*>(aActor->ToplevelProtocol()));
}
WriteIPDLParam(aMsg, aActor, std::move(entry));
}
/* static */
bool IPDLParamTraits<dom::CrossProcessSHEntry*>::Read(
const IPC::Message* aMsg, PickleIterator* aIter,
mozilla::ipc::IProtocol* aActor, RefPtr<dom::CrossProcessSHEntry>* aEntry) {
if (aActor->GetSide() == ParentSide) {
dom::PSHEntryParent* actor;
if (!ReadIPDLParam(aMsg, aIter, aActor, &actor)) {
aActor->FatalError("Error deserializing MaybeNewPSHEntry");
return false;
}
*aEntry =
actor ? static_cast<dom::SHEntryParent*>(actor)->GetSHEntry() : nullptr;
return true;
}
dom::MaybeNewPSHEntryChild actor(static_cast<dom::PSHEntryChild*>(nullptr));
if (!ReadIPDLParam(aMsg, aIter, aActor, &actor)) {
aActor->FatalError("Error deserializing MaybeNewPSHEntry");
return false;
}
return actor.match(
[&](dom::PSHEntryChild*& entry) {
*aEntry = static_cast<dom::SHEntryChild*>(entry);
return true;
},
[&](dom::NewPSHEntry& newEntry) {
RefPtr<dom::SHEntryChild> entry = new dom::SHEntryChild(
static_cast<dom::SHistoryChild*>(newEntry.mSHistoryChild),
newEntry.mSharedID);
dom::ContentChild::GetSingleton()->BindPSHEntryEndpoint(
std::move(newEntry.mEndpoint), do_AddRef(entry).take());
*aEntry = std::move(entry);
return true;
});
}
} // namespace ipc
} // namespace mozilla

View File

@@ -0,0 +1,62 @@
/* -*- 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_MaybeNewPSHEntry_h
#define mozilla_dom_MaybeNewPSHEntry_h
#include "ipc/IPCMessageUtils.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Variant.h"
#include "mozilla/ipc/IPDLParamTraits.h"
#include "mozilla/ipc/ProtocolUtils.h"
namespace mozilla {
namespace dom {
class LegacySHEntry;
class PSHistoryChild;
class PSHistoryParent;
class PSHEntryChild;
class PSHEntryParent;
class PSHistoryChild;
class PSHistoryParent;
class SHEntryChild;
struct NewPSHEntry final {
mozilla::ipc::ManagedEndpoint<PSHEntryChild> mEndpoint;
PSHistoryParent* mSHistoryParent;
PSHistoryChild* mSHistoryChild;
uint64_t mSharedID;
};
typedef Variant<PSHEntryParent*, NewPSHEntry> MaybeNewPSHEntryParent;
typedef Variant<PSHEntryChild*, NewPSHEntry> MaybeNewPSHEntryChild;
// Any IPDL protocol trying to pass this (as argument or return value) needs to
// be managed by PContent.
class CrossProcessSHEntry {
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
SHEntryChild* ToSHEntryChild();
};
} // namespace dom
namespace ipc {
template <>
struct IPDLParamTraits<dom::CrossProcessSHEntry*> {
static void Write(IPC::Message* aMsg, IProtocol* aActor,
dom::CrossProcessSHEntry* aEntry);
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, RefPtr<dom::CrossProcessSHEntry>* aEntry);
};
} // namespace ipc
} // namespace mozilla
#endif /* mozilla_dom_MaybeNewPSHEntry_h */

View File

@@ -0,0 +1,123 @@
/* 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/. */
include protocol PContent;
include protocol PSHistory;
include DOMTypes;
include PresState;
using refcounted class mozilla::dom::CrossProcessSHEntry from "mozilla/dom/MaybeNewPSHEntry.h";
using refcounted class nsDocShellLoadState from "mozilla/dom/DocShellMessageUtils.h";
using struct nsID from "nsID.h";
using nsIntRect from "nsRect.h";
namespace mozilla {
namespace dom {
sync protocol PSHEntry {
// IPDLParamTraits<dom::CrossProcessSHEntry*>::Write relies on PContent being
// the manager.
manager PContent;
parent:
sync GetURI() returns (nsIURI uri);
async SetURI(nsIURI uri);
sync GetOriginalURI() returns (nsIURI originalUri);
async SetOriginalURI(nsIURI originalUri);
sync GetResultPrincipalURI() returns (nsIURI resultPrincipalUri);
async SetResultPrincipalURI(nsIURI resultPrincipalUri);
sync GetLoadReplace() returns (bool loadReplace);
async SetLoadReplace(bool loadReplace);
sync GetTitle() returns (nsString title);
async SetTitle(nsString title);
sync GetIsSubFrame() returns (bool isSubFrame);
async SetIsSubFrame(bool isSubFrame);
sync GetReferrerInfo() returns (nsIReferrerInfo referrerInfo);
async SetReferrerInfo(nsIReferrerInfo referrerInfo);
sync GetSticky() returns (bool sticky);
async SetSticky(bool sticky);
sync GetPostData() returns (nsIInputStream postData);
async SetPostData(nsIInputStream postData);
sync GetParent() returns (CrossProcessSHEntry parentEntry);
async SetParent(nullable PSHEntry parentEntry);
sync GetLoadType() returns (uint32_t loadType);
async SetLoadType(uint32_t loadType);
sync GetID() returns (uint32_t id);
async SetID(uint32_t id);
sync GetCacheKey() returns (uint32_t cacheKey);
async SetCacheKey(uint32_t cacheKey);
sync GetExpirationStatus() returns (bool expirationStatus);
async SetExpirationStatus(bool expirationStatus);
sync GetContentType() returns (nsCString contentType);
async SetContentType(nsCString contentType);
sync GetURIWasModified() returns (bool uriWasModified);
async SetURIWasModified(bool uriWasModified);
sync GetTriggeringPrincipal() returns (nsIPrincipal triggeringPrincipal);
async SetTriggeringPrincipal(nsIPrincipal triggeringPrincipal);
sync GetPrincipalToInherit() returns (nsIPrincipal principalToInherit);
async SetPrincipalToInherit(nsIPrincipal principalToInherit);
sync GetStoragePrincipalToInherit()
returns (nsIPrincipal storagePrincipalToInherit);
async SetStoragePrincipalToInherit(nsIPrincipal storagePrincipalToInherit);
sync GetCsp() returns (nsIContentSecurityPolicy csp);
async SetCsp(nsIContentSecurityPolicy csp);
sync GetStateData() returns (ClonedMessageData stateData);
async SetStateData(ClonedMessageData stateData);
sync GetDocshellID() returns (nsID docshellId);
async SetDocshellID(nsID docshellId);
sync GetIsSrcdocEntry() returns (bool isSrcdocEntry);
sync GetSrcdocData() returns (nsString srcdocData);
async SetSrcdocData(nsString srcdocData);
sync GetBaseURI() returns (nsIURI baseUri);
async SetBaseURI(nsIURI baseUri);
sync GetScrollRestorationIsManual() returns (bool scrollRestorationIsManual);
async SetScrollRestorationIsManual(bool scrollRestorationIsManual);
sync GetLoadedInThisProcess() returns (bool loadedInThisProcess);
sync GetLastTouched() returns (uint32_t lastTouched);
async SetLastTouched(uint32_t lastTouched);
sync GetChildCount() returns (int32_t childCount);
sync GetPersist() returns (bool persist);
async SetPersist(bool persist);
async SetScrollPosition(int32_t x, int32_t y);
sync GetScrollPosition() returns (int32_t x, int32_t y);
sync GetViewerBounds() returns (nsIntRect bounds);
async SetViewerBounds(nsIntRect bounds);
async Create(nsIURI URI, nsString title, nsIInputStream inputStream,
uint32_t cacheKey, nsCString contentType,
nsIPrincipal triggeringPrincipal, nsIPrincipal principalToInherit,
nsIPrincipal storagePrincipalToInherit,
nsIContentSecurityPolicy csp, nsID docshellID,
bool dynamicCreation, nsIURI originalUri, nsIURI resultPrincipalURI,
bool loadReplace, nsIReferrerInfo referrerInfo,
nsString srcdoc, bool srcdocEntry, nsIURI baseURI,
bool saveLayoutState, bool expired);
sync HasDetachedEditor() returns (bool hasDetachedEditor);
sync IsDynamicallyAdded() returns (bool isDynamicallyAdded);
sync HasDynamicallyAddedChild() returns (bool hasDynamicallyAddedChild);
sync AdoptBFCacheEntry(PSHEntry entry) returns (nsresult result);
async AbandonBFCacheEntry(uint64_t aNewSharedID);
sync SharesDocumentWith(PSHEntry entry) returns (bool sharesDocumentWith,
nsresult result);
async SetLoadTypeAsHistory();
sync AddChild(nullable PSHEntry childEntry, int32_t offset, bool useRemoteSubframes) returns (nsresult result);
sync RemoveChild(PSHEntry childEntry) returns (nsresult result);
sync GetChildAt(int32_t index) returns (CrossProcessSHEntry childEntry);
sync GetChildSHEntryIfHasNoDynamicallyAddedChild(int32_t childOffset) returns (CrossProcessSHEntry childEntry);
sync ReplaceChild(PSHEntry newChildEntry) returns (nsresult result);
async ClearEntry(uint64_t aNewSharedID);
sync CreateLoadInfo() returns (nsDocShellLoadState loadState);
sync Clone() returns (CrossProcessSHEntry result);
sync SyncTreesForSubframeNavigation(nullable PSHEntry entry, MaybeDiscardedBrowsingContext BC,
MaybeDiscardedBrowsingContext ignoreBC)
returns (SwapEntriesDocshellData[] entriesToUpdate);
async UpdateLayoutHistoryState(bool scrollPositionOnly,
nsCString[] keys, PresState[] states);
sync __delete__();
};
} // namespace dom
} // namespace mozilla

View File

@@ -0,0 +1,88 @@
/* 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/. */
include protocol PContent;
include protocol PSHEntry;
include DOMTypes;
using mozilla::dom::MaybeDiscardedBrowsingContext from "mozilla/dom/BrowsingContext.h";
using refcounted class mozilla::dom::CrossProcessSHEntry from "mozilla/dom/MaybeNewPSHEntry.h";
using refcounted class nsDocShellLoadState from "mozilla/dom/DocShellMessageUtils.h";
using struct nsID from "nsID.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace dom {
struct LoadSHEntryData
{
CrossProcessSHEntry shEntry;
MaybeDiscardedBrowsingContext browsingContext;
nsDocShellLoadState loadState;
};
union LoadSHEntryResult {
nsresult;
LoadSHEntryData[];
};
sync protocol PSHistory {
// IPDLParamTraits<dom::CrossProcessSHEntry*>::Write relies on PContent being
// the manager.
manager PContent;
parent:
sync GetCount() returns (int32_t count);
sync GetIndex() returns (int32_t index);
sync SetIndex(int32_t index) returns (nsresult result);
sync GetRequestedIndex() returns (int32_t index);
async InternalSetRequestedIndex(int32_t index);
sync GetEntryAtIndex(int32_t index) returns (nsresult result, CrossProcessSHEntry entry);
sync PurgeHistory(int32_t numEntries) returns (nsresult result);
sync ReloadCurrentEntry() returns (LoadSHEntryResult load);
sync GotoIndex(int32_t index) returns (LoadSHEntryResult load);
sync GetIndexOfEntry(PSHEntry entry) returns (int32_t index);
sync AddEntry(PSHEntry entry, bool persist) returns (nsresult result, int32_t entriesPurged);
async UpdateIndex();
sync ReplaceEntry(int32_t index, PSHEntry entry) returns (nsresult result);
sync NotifyOnHistoryReload() returns (bool ok);
async EvictOutOfRangeContentViewers(int32_t index);
async EvictAllContentViewers();
async RemoveDynEntries(int32_t index, PSHEntry entry);
sync RemoveEntries(nsID[] ids, int32_t index) returns (bool didRemove);
async RemoveFrameEntries(PSHEntry entry);
sync Reload(uint32_t reloadFlags) returns (LoadSHEntryResult load);
sync GetAllEntries() returns (CrossProcessSHEntry[] entries);
sync FindEntryForBFCache(uint64_t sharedID, bool includeCurrentEntry)
returns (CrossProcessSHEntry entries, int32_t startIndex);
async Evict(PSHEntry[] entry);
async EnsureCorrectEntryAtCurrIndex(PSHEntry entry);
async EvictContentViewersOrReplaceEntry(nullable PSHEntry newSHEntry, bool replace);
async NotifyListenersContentViewerEvicted(uint32_t numEvicted);
// See below for some explanation
sync AddToRootSessionHistory(bool cloneChildren, nullable PSHEntry OSHE, MaybeDiscardedBrowsingContext BC, PSHEntry entry,
uint32_t loadType, bool shouldPersist) returns (int32_t? previousEntryIndex, int32_t? loadedEntryIndex,
SwapEntriesDocshellData[] entriesToUpdate, int32_t entriesPurged, nsresult result);
// In CloneAndReplaceChild and SetChildHistoryEntry methods (which get called within this
// and above function) there are calls to SwapHistoryEntries to update entries in the docshell.
// We don't have access to the docshell in the parent
// process so we have to either wait to update the docshell or update it via an IPC call.
// We pass in the ChildID of the process who invoked the IPC to make decisions
// about whether we should update entries in the docshell via an IPC call -
// if the caller is a process different from where the docshell lives.
// Else, we return entries that we need to update in entriesToUpdate array
// and update the docshell with such entries in the child process.
sync AddChildSHEntryHelper(PSHEntry cloneRef, PSHEntry newEntry, MaybeDiscardedBrowsingContext BC,
bool cloneChildren) returns (SwapEntriesDocshellData[] entriesToUpdate,
int32_t entriesPurged, CrossProcessSHEntry entry, nsresult result);
async __delete__();
child:
async ReloadCurrentEntryFromChild();
};
} // namespace dom
} // namespace mozilla

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
/* -*- 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_SHEntryChild_h
#define mozilla_dom_SHEntryChild_h
#include "mozilla/dom/PSHEntryChild.h"
#include "mozilla/dom/MaybeNewPSHEntry.h"
#include "nsContentUtils.h"
#include "nsExpirationTracker.h"
#include "nsIBFCacheEntry.h"
#include "nsISHEntry.h"
#include "nsRect.h"
#include "nsSHEntryShared.h"
#include "nsStubMutationObserver.h"
class nsDocShellEditorData;
class nsIContentViewer;
class nsILayoutHistoryState;
class nsIMutableArray;
namespace mozilla {
namespace dom {
class SHistoryChild;
/**
* Implementation of the shared state for session history entries in the child
* process.
*/
class SHEntryChildShared final : public nsIBFCacheEntry,
public nsStubMutationObserver,
public SHEntrySharedChildState {
public:
static void Init();
static SHEntryChildShared* GetOrCreate(SHistoryChild* aSHistory,
uint64_t aSharedID);
static void Remove(uint64_t aSharedID);
static uint64_t CreateSharedID() {
return nsContentUtils::GenerateProcessSpecificId(++sNextSharedID);
}
static void EvictContentViewers(
const nsTArray<uint64_t>& aToEvictSharedStateIDs);
void NotifyListenersContentViewerEvicted(uint32_t aNumEvicted = 1);
NS_DECL_ISUPPORTS
NS_DECL_NSIBFCACHEENTRY
// The nsIMutationObserver bits we actually care about.
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
nsExpirationState* GetExpirationState() { return &mExpirationState; }
uint64_t GetID() { return mID; }
private:
static uint64_t sNextSharedID;
SHEntryChildShared(SHistoryChild* aSHistory, uint64_t aID);
~SHEntryChildShared();
friend class SHEntryChild;
already_AddRefed<SHEntryChildShared> Duplicate();
void RemoveFromExpirationTracker();
void SyncPresentationState();
void DropPresentationState();
nsresult SetContentViewer(nsIContentViewer* aViewer);
uint64_t mID;
RefPtr<SHistoryChild> mSHistory;
};
/**
* Session history entry actor for the child process.
*/
class SHEntryChild final : public PSHEntryChild,
public nsISHEntry,
public CrossProcessSHEntry {
friend class PSHEntryChild;
using PSHEntryChild::CrossProcessSHEntry;
public:
explicit SHEntryChild(const SHEntryChild* aClone)
: mShared(aClone->mShared.get()), mIPCActorDeleted(false) {}
SHEntryChild(SHistoryChild* aSHistory, uint64_t aSharedID)
: mShared(SHEntryChildShared::GetOrCreate(aSHistory, aSharedID)),
mIPCActorDeleted(false) {}
NS_DECL_ISUPPORTS
NS_DECL_NSISHENTRY
void EvictContentViewer();
protected:
void ActorDestroy(ActorDestroyReason aWhy) override {
mIPCActorDeleted = true;
}
private:
~SHEntryChild() = default;
RefPtr<SHEntryChildShared> mShared;
bool mIPCActorDeleted;
};
inline SHEntryChild* CrossProcessSHEntry::ToSHEntryChild() {
MOZ_ASSERT(XRE_IsContentProcess(), "Wrong side!");
return static_cast<SHEntryChild*>(this);
}
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SHEntryChild_h */

View File

@@ -0,0 +1,620 @@
/* -*- 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/. */
#include "SHEntryParent.h"
#include "SHistoryParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/MaybeNewPSHEntry.h"
#include "nsILayoutHistoryState.h"
#include "nsStructuredCloneContainer.h"
namespace mozilla {
namespace dom {
SHEntrySharedParent::SHEntrySharedParent(PContentParent* aContentParent,
LegacySHistory* aSHistory,
uint64_t aSharedID)
: SHEntrySharedParentState(aSHistory, aSharedID),
mContentParent(aContentParent) {}
void SHEntrySharedParent::Destroy() {
if (mContentParent &&
!static_cast<ContentParent*>(mContentParent.get())->IsDestroyed()) {
Unused << mContentParent->SendDestroySHEntrySharedState(mID);
}
SHEntrySharedParentState::Destroy();
}
LegacySHEntry::LegacySHEntry(PContentParent* aContentParent,
LegacySHistory* aSHistory, uint64_t aSharedID)
: nsSHEntry(new SHEntrySharedParent(aContentParent, aSHistory, aSharedID)),
mActor(nullptr) {}
NS_IMPL_ISUPPORTS_INHERITED0(LegacySHEntry, nsSHEntry)
SHEntryParent* LegacySHEntry::CreateActor() {
MOZ_ASSERT(!mActor);
mActor = new SHEntryParent(this);
return mActor;
}
MaybeNewPSHEntryParent LegacySHEntry::GetOrCreateActor(
PContentParent* aContentParent) {
if (mActor) {
return AsVariant(static_cast<PSHEntryParent*>(mActor));
}
nsCOMPtr<nsISHistory> shistory = do_QueryReferent(mShared->mSHistory);
return AsVariant(
NewPSHEntry{aContentParent->OpenPSHEntryEndpoint(CreateActor()),
static_cast<LegacySHistory*>(shistory.get())->GetActor(),
nullptr, mShared->mID});
}
void LegacySHEntry::AbandonBFCacheEntry(uint64_t aNewSharedID) {
mShared =
static_cast<SHEntrySharedParent*>(mShared.get())->Duplicate(aNewSharedID);
}
NS_IMETHODIMP
LegacySHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
*aBFCacheID = mShared->GetID();
return NS_OK;
}
NS_IMETHODIMP
LegacySHEntry::Clone(nsISHEntry** aResult) {
nsCOMPtr<nsISHEntry> entry = new LegacySHEntry(*this);
entry.forget(aResult);
return NS_OK;
}
void SHEntryParent::ActorDestroy(ActorDestroyReason aWhy) {
mEntry->mActor = nullptr;
}
bool SHEntryParent::RecvGetURI(RefPtr<nsIURI>* aURI) {
*aURI = mEntry->GetURI();
return true;
}
bool SHEntryParent::RecvSetURI(nsIURI* aURI) {
DebugOnly<nsresult> rv = mEntry->SetURI(aURI);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetOriginalURI(RefPtr<nsIURI>* aOriginalURI) {
*aOriginalURI = mEntry->GetOriginalURI();
return true;
}
bool SHEntryParent::RecvSetOriginalURI(nsIURI* aOriginalURI) {
DebugOnly<nsresult> rv = mEntry->SetOriginalURI(aOriginalURI);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetResultPrincipalURI(
RefPtr<nsIURI>* aResultPrincipalURI) {
*aResultPrincipalURI = mEntry->GetResultPrincipalURI();
return true;
}
bool SHEntryParent::RecvSetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
DebugOnly<nsresult> rv = mEntry->SetResultPrincipalURI(aResultPrincipalURI);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetLoadReplace(bool* aLoadReplace) {
*aLoadReplace = mEntry->GetLoadReplace();
return true;
}
bool SHEntryParent::RecvSetLoadReplace(const bool& aLoadReplace) {
DebugOnly<nsresult> rv = mEntry->SetLoadReplace(aLoadReplace);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetTitle(nsString* aTitle) {
DebugOnly<nsresult> rv = mEntry->GetTitle(*aTitle);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetTitle(const nsString& aTitle) {
DebugOnly<nsresult> rv = mEntry->SetTitle(aTitle);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetIsSubFrame(bool* aIsSubFrame) {
*aIsSubFrame = mEntry->GetIsSubFrame();
return true;
}
bool SHEntryParent::RecvSetIsSubFrame(const bool& aIsSubFrame) {
DebugOnly<nsresult> rv = mEntry->SetIsSubFrame(aIsSubFrame);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetReferrerInfo(
RefPtr<nsIReferrerInfo>* aReferrerInfo) {
*aReferrerInfo = mEntry->GetReferrerInfo();
return true;
}
bool SHEntryParent::RecvSetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
DebugOnly<nsresult> rv = mEntry->SetReferrerInfo(aReferrerInfo);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetSticky(bool* aSticky) {
*aSticky = mEntry->GetSticky();
return true;
}
bool SHEntryParent::RecvSetSticky(const bool& aSticky) {
DebugOnly<nsresult> rv = mEntry->SetSticky(aSticky);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetPostData(RefPtr<nsIInputStream>* aPostData) {
*aPostData = mEntry->GetPostData();
return true;
}
bool SHEntryParent::RecvSetPostData(nsIInputStream* aPostData) {
DebugOnly<nsresult> rv = mEntry->SetPostData(aPostData);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetParent(RefPtr<CrossProcessSHEntry>* aParentEntry) {
nsCOMPtr<nsISHEntry> parent = mEntry->GetParent();
*aParentEntry = parent.forget().downcast<LegacySHEntry>();
return true;
}
bool SHEntryParent::RecvSetParent(PSHEntryParent* aParentEntry) {
DebugOnly<nsresult> rv = mEntry->SetParent(
aParentEntry ? static_cast<SHEntryParent*>(aParentEntry)->mEntry.get()
: nullptr);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetLoadType(uint32_t* aLoadType) {
*aLoadType = mEntry->GetLoadType();
return true;
}
bool SHEntryParent::RecvSetLoadType(const uint32_t& aLoadType) {
DebugOnly<nsresult> rv = mEntry->SetLoadType(aLoadType);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetID(uint32_t* aID) {
*aID = mEntry->GetID();
return true;
}
bool SHEntryParent::RecvSetID(const uint32_t& aID) {
DebugOnly<nsresult> rv = mEntry->SetID(aID);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetCacheKey(uint32_t* aCacheKey) {
*aCacheKey = mEntry->GetCacheKey();
return true;
}
bool SHEntryParent::RecvSetCacheKey(const uint32_t& aCacheKey) {
DebugOnly<nsresult> rv = mEntry->SetCacheKey(aCacheKey);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetExpirationStatus(bool* aExpirationStatus) {
*aExpirationStatus = mEntry->GetExpirationStatus();
return true;
}
bool SHEntryParent::RecvSetExpirationStatus(const bool& aExpirationStatus) {
DebugOnly<nsresult> rv = mEntry->SetExpirationStatus(aExpirationStatus);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetContentType(nsCString* aContentType) {
DebugOnly<nsresult> rv = mEntry->GetContentType(*aContentType);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetContentType(const nsCString& aContentType) {
DebugOnly<nsresult> rv = mEntry->SetContentType(aContentType);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetURIWasModified(bool* aURIWasModified) {
*aURIWasModified = mEntry->GetURIWasModified();
return true;
}
bool SHEntryParent::RecvSetURIWasModified(const bool& aURIWasModified) {
DebugOnly<nsresult> rv = mEntry->SetURIWasModified(aURIWasModified);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetTriggeringPrincipal(
RefPtr<nsIPrincipal>* aTriggeringPrincipal) {
*aTriggeringPrincipal = mEntry->GetTriggeringPrincipal();
return true;
}
bool SHEntryParent::RecvSetTriggeringPrincipal(
nsIPrincipal* aTriggeringPrincipal) {
DebugOnly<nsresult> rv = mEntry->SetTriggeringPrincipal(aTriggeringPrincipal);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetPrincipalToInherit(
RefPtr<nsIPrincipal>* aPrincipalToInherit) {
*aPrincipalToInherit = mEntry->GetPrincipalToInherit();
return true;
}
bool SHEntryParent::RecvSetPrincipalToInherit(
nsIPrincipal* aPrincipalToInherit) {
DebugOnly<nsresult> rv = mEntry->SetPrincipalToInherit(aPrincipalToInherit);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetStoragePrincipalToInherit(
RefPtr<nsIPrincipal>* aStoragePrincipalToInherit) {
*aStoragePrincipalToInherit = mEntry->GetStoragePrincipalToInherit();
return true;
}
bool SHEntryParent::RecvSetStoragePrincipalToInherit(
nsIPrincipal* aStoragePrincipalToInherit) {
DebugOnly<nsresult> rv =
mEntry->SetStoragePrincipalToInherit(aStoragePrincipalToInherit);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetCsp(RefPtr<nsIContentSecurityPolicy>* aCsp) {
*aCsp = mEntry->GetCsp();
return true;
}
bool SHEntryParent::RecvSetCsp(nsIContentSecurityPolicy* aCsp) {
DebugOnly<nsresult> rv = mEntry->SetCsp(aCsp);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetStateData(ClonedMessageData* aData) {
nsCOMPtr<nsIStructuredCloneContainer> container = mEntry->GetStateData();
if (container) {
static_cast<nsStructuredCloneContainer*>(container.get())
->BuildClonedMessageDataForParent(
static_cast<ContentParent*>(ToplevelProtocol()), *aData);
}
return true;
}
bool SHEntryParent::RecvSetStateData(ClonedMessageData&& aData) {
// FIXME Need more data! Should we signal null separately from the
// ClonedMessageData?
if (aData.data().data.Size() == 0) {
mEntry->SetStateData(nullptr);
} else {
RefPtr<nsStructuredCloneContainer> container =
new nsStructuredCloneContainer();
container->StealFromClonedMessageDataForParent(aData);
mEntry->SetStateData(container);
}
return true;
}
bool SHEntryParent::RecvGetDocshellID(nsID* aDocshellID) {
DebugOnly<nsresult> rv = mEntry->GetDocshellID(*aDocshellID);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetDocshellID(const nsID& aDocshellID) {
DebugOnly<nsresult> rv = mEntry->SetDocshellID(aDocshellID);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetIsSrcdocEntry(bool* aIsSrcdocEntry) {
*aIsSrcdocEntry = mEntry->GetIsSrcdocEntry();
return true;
}
bool SHEntryParent::RecvGetSrcdocData(nsString* aSrcdocData) {
DebugOnly<nsresult> rv = mEntry->GetSrcdocData(*aSrcdocData);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetSrcdocData(const nsString& aSrcdocData) {
DebugOnly<nsresult> rv = mEntry->SetSrcdocData(aSrcdocData);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetBaseURI(RefPtr<nsIURI>* aBaseURI) {
*aBaseURI = mEntry->GetBaseURI();
return true;
}
bool SHEntryParent::RecvSetBaseURI(nsIURI* aBaseURI) {
DebugOnly<nsresult> rv = mEntry->SetBaseURI(aBaseURI);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetScrollRestorationIsManual(
bool* aScrollRestorationIsManual) {
DebugOnly<nsresult> rv =
mEntry->GetScrollRestorationIsManual(aScrollRestorationIsManual);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetScrollRestorationIsManual(
const bool& aScrollRestorationIsManual) {
DebugOnly<nsresult> rv =
mEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetLoadedInThisProcess(bool* aLoadedInThisProcess) {
*aLoadedInThisProcess = mEntry->GetLoadedInThisProcess();
return true;
}
bool SHEntryParent::RecvGetLastTouched(uint32_t* aLastTouched) {
*aLastTouched = mEntry->GetLastTouched();
return true;
}
bool SHEntryParent::RecvSetLastTouched(const uint32_t& aLastTouched) {
DebugOnly<nsresult> rv = mEntry->SetLastTouched(aLastTouched);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetChildCount(int32_t* aChildCount) {
*aChildCount = mEntry->GetChildCount();
return true;
}
bool SHEntryParent::RecvGetPersist(bool* aPersist) {
*aPersist = mEntry->GetPersist();
return true;
}
bool SHEntryParent::RecvSetPersist(const bool& aPersist) {
DebugOnly<nsresult> rv = mEntry->SetPersist(aPersist);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetScrollPosition(int32_t* aX, int32_t* aY) {
DebugOnly<nsresult> rv = mEntry->GetScrollPosition(aX, aY);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvSetScrollPosition(const int32_t& aX,
const int32_t& aY) {
DebugOnly<nsresult> rv = mEntry->SetScrollPosition(aX, aY);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvGetViewerBounds(nsIntRect* aBounds) {
mEntry->GetViewerBounds(*aBounds);
return true;
}
bool SHEntryParent::RecvSetViewerBounds(const nsIntRect& aBounds) {
mEntry->SetViewerBounds(aBounds);
return true;
}
bool SHEntryParent::RecvCreate(
nsIURI* aURI, const nsString& aTitle, nsIInputStream* aInputStream,
const uint32_t& aCacheKey, const nsCString& aContentType,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aStoragePrincipalToInherit, nsIContentSecurityPolicy* aCsp,
const nsID& aDocshellID, const bool& aDynamicCreation, nsIURI* aOriginalURI,
nsIURI* aResultPrincipalURI, const bool& aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& srcdoc,
const bool& srcdocEntry, nsIURI* aBaseURI, const bool& aSaveLayoutState,
const bool& aExpired) {
DebugOnly<nsresult> rv = mEntry->Create(
aURI, aTitle, aInputStream, aCacheKey, aContentType, aTriggeringPrincipal,
aPrincipalToInherit, aStoragePrincipalToInherit, aCsp, aDocshellID,
aDynamicCreation, aOriginalURI, aResultPrincipalURI, aLoadReplace,
aReferrerInfo, srcdoc, srcdocEntry, aBaseURI, aSaveLayoutState, aExpired);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvHasDetachedEditor(bool* aHasDetachedEditor) {
*aHasDetachedEditor = mEntry->HasDetachedEditor();
return true;
}
bool SHEntryParent::RecvIsDynamicallyAdded(bool* aIsDynamicallyAdded) {
*aIsDynamicallyAdded = mEntry->IsDynamicallyAdded();
return true;
}
bool SHEntryParent::RecvHasDynamicallyAddedChild(
bool* aHasDynamicallyAddedChild) {
DebugOnly<nsresult> rv =
mEntry->HasDynamicallyAddedChild(aHasDynamicallyAddedChild);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvDocshellID(nsID* aDocshellID) {
mEntry->GetDocshellID(*aDocshellID);
return true;
}
bool SHEntryParent::RecvAdoptBFCacheEntry(PSHEntryParent* aEntry,
nsresult* aResult) {
*aResult =
mEntry->AdoptBFCacheEntry(static_cast<SHEntryParent*>(aEntry)->mEntry);
return true;
}
bool SHEntryParent::RecvAbandonBFCacheEntry(const uint64_t& aNewSharedID) {
mEntry->AbandonBFCacheEntry(aNewSharedID);
return true;
}
bool SHEntryParent::RecvSharesDocumentWith(PSHEntryParent* aEntry,
bool* aSharesDocumentWith,
nsresult* aResult) {
*aResult = mEntry->SharesDocumentWith(
static_cast<SHEntryParent*>(aEntry)->mEntry, aSharesDocumentWith);
return true;
}
bool SHEntryParent::RecvSetLoadTypeAsHistory() {
DebugOnly<nsresult> rv = mEntry->SetLoadTypeAsHistory();
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
return true;
}
bool SHEntryParent::RecvAddChild(PSHEntryParent* aChild, const int32_t& aOffset,
const bool& aUseRemoteSubframes,
nsresult* aResult) {
*aResult = mEntry->AddChild(
aChild ? static_cast<SHEntryParent*>(aChild)->mEntry.get() : nullptr,
aOffset, aUseRemoteSubframes);
return true;
}
bool SHEntryParent::RecvRemoveChild(PSHEntryParent* aChild, nsresult* aResult) {
*aResult = mEntry->RemoveChild(static_cast<SHEntryParent*>(aChild)->mEntry);
return true;
}
bool SHEntryParent::RecvGetChildAt(const int32_t& aIndex,
RefPtr<CrossProcessSHEntry>* aChild) {
nsCOMPtr<nsISHEntry> child;
DebugOnly<nsresult> rv = mEntry->GetChildAt(aIndex, getter_AddRefs(child));
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
*aChild = child.forget().downcast<LegacySHEntry>();
return true;
}
bool SHEntryParent::RecvGetChildSHEntryIfHasNoDynamicallyAddedChild(
const int32_t& aChildOffset, RefPtr<CrossProcessSHEntry>* aChild) {
nsCOMPtr<nsISHEntry> child;
mEntry->GetChildSHEntryIfHasNoDynamicallyAddedChild(aChildOffset,
getter_AddRefs(child));
*aChild = child.forget().downcast<LegacySHEntry>();
return true;
}
bool SHEntryParent::RecvReplaceChild(PSHEntryParent* aNewChild,
nsresult* aResult) {
*aResult =
mEntry->ReplaceChild(static_cast<SHEntryParent*>(aNewChild)->mEntry);
return true;
}
bool SHEntryParent::RecvClearEntry(const uint64_t& aNewSharedID) {
mEntry->ClearEntry();
mEntry->AbandonBFCacheEntry(aNewSharedID);
return true;
}
bool SHEntryParent::RecvCreateLoadInfo(
RefPtr<nsDocShellLoadState>* aLoadState) {
mEntry->CreateLoadInfo(getter_AddRefs(*aLoadState));
return true;
}
bool SHEntryParent::RecvUpdateLayoutHistoryState(
const bool& aScrollPositionOnly, nsTArray<nsCString>&& aKeys,
nsTArray<PresState>&& aStates) {
nsCOMPtr<nsILayoutHistoryState> layoutHistoryState;
// InitLayoutHistoryState creates a new object only if there isn't one
// already.
mEntry->InitLayoutHistoryState(getter_AddRefs(layoutHistoryState));
layoutHistoryState->Reset();
if (aKeys.Length() != aStates.Length()) {
NS_WARNING("Bogus data sent from the child process?");
return true;
}
layoutHistoryState->SetScrollPositionOnly(aScrollPositionOnly);
for (uint32_t i = 0; i < aKeys.Length(); ++i) {
PresState& state = aStates[i];
UniquePtr<PresState> newState = MakeUnique<PresState>(state);
layoutHistoryState->AddState(aKeys[i], std::move(newState));
}
return true;
}
bool SHEntryParent::RecvClone(RefPtr<CrossProcessSHEntry>* aResult) {
nsCOMPtr<nsISHEntry> result;
DebugOnly<nsresult> rv =
static_cast<LegacySHEntry*>(mEntry)->Clone(getter_AddRefs(result));
MOZ_ASSERT(NS_SUCCEEDED(rv), "Didn't expect this to fail.");
*aResult = result.forget().downcast<LegacySHEntry>();
return true;
}
bool SHEntryParent::RecvSyncTreesForSubframeNavigation(
PSHEntryParent* aSHEntry, const MaybeDiscarded<BrowsingContext>& aBC,
const MaybeDiscarded<BrowsingContext>& aIgnoreBC,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate) {
nsTArray<EntriesAndBrowsingContextData> entriesToSendOverIPC;
// aBC or aIgnoreBC can be discarded but we can update them anyway if they are
// not null
mEntry->SyncTreesForSubframeNavigation(
static_cast<ContentParent*>(Manager())->ChildID(),
aSHEntry ? static_cast<SHEntryParent*>(aSHEntry)->mEntry.get() : nullptr,
aBC.GetMaybeDiscarded(), aIgnoreBC.GetMaybeDiscarded(),
&entriesToSendOverIPC);
SHistoryParent::CreateActorsForSwapEntries(entriesToSendOverIPC,
aEntriesToUpdate, Manager());
return true;
}
} // namespace dom
} // namespace mozilla

View File

@@ -0,0 +1,225 @@
/* -*- 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_SHistoryEntry_h
#define mozilla_dom_SHistoryEntry_h
#include "mozilla/dom/PSHEntryParent.h"
#include "mozilla/dom/MaybeNewPSHEntry.h"
#include "mozilla/WeakPtr.h"
#include "nsSHEntry.h"
#include "nsSHEntryShared.h"
namespace mozilla {
namespace dom {
class LegacySHistory;
class PContentParent;
class SHEntryParent;
/**
* Implementation of the shared state for session history entries in the parent
* process.
*/
class SHEntrySharedParent : public SHEntrySharedParentState {
public:
SHEntrySharedParent(PContentParent* aContentParent, LegacySHistory* aSHistory,
uint64_t aSharedID);
already_AddRefed<SHEntrySharedParent> Duplicate(uint64_t aNewSharedID) {
RefPtr<SHEntrySharedParent> shared =
new SHEntrySharedParent(this, aNewSharedID);
shared->CopyFrom(this);
return shared.forget();
}
PContentParent* GetContentParent() { return mContentParent.get(); }
protected:
SHEntrySharedParent(SHEntrySharedParent* aDuplicate, uint64_t aSharedID)
: SHEntrySharedParentState(aDuplicate, aSharedID),
mContentParent(aDuplicate->mContentParent) {}
void Destroy() override;
private:
mozilla::WeakPtr<PContentParent> mContentParent;
};
/**
* Session history entry implementation based on the legacy implementation that
* used to live in the child process. Ideally this wouldn't implement nsISHEntry
* (it should only ever be accessed by SHEntryParent and LegacySHistory).
* The actor is (re)created as needed, whenever we need to return an entry to
* the child process. The lifetime is determined by the child side.
*/
class LegacySHEntry final : public nsSHEntry, public CrossProcessSHEntry {
public:
LegacySHEntry(PContentParent* aContentParent, LegacySHistory* aSHistory,
uint64_t aSharedID);
explicit LegacySHEntry(const LegacySHEntry& aEntry)
: nsSHEntry(aEntry), mActor(nullptr) {}
NS_DECL_ISUPPORTS_INHERITED
MaybeNewPSHEntryParent GetOrCreateActor(PContentParent* aContentParent);
using nsSHEntry::AbandonBFCacheEntry;
void AbandonBFCacheEntry(uint64_t aNewSharedID);
NS_IMETHODIMP GetBfcacheID(uint64_t* aBFCacheID) override;
uint64_t GetSharedStateID() const { return mShared->GetID(); }
dom::SHEntrySharedParentState* GetSharedState() const {
return mShared.get();
}
NS_IMETHOD Clone(nsISHEntry** aResult) override;
private:
friend class SHEntryParent;
friend class SHistoryParent;
~LegacySHEntry() = default;
SHEntryParent* CreateActor();
SHEntryParent* mActor;
};
/**
* Session history entry actor for the parent process. Forwards to the legacy
* implementation that used to live in the child process (see LegacySHEntry).
*/
class SHEntryParent final : public PSHEntryParent {
friend class PSHEntryParent;
friend class SHistoryParent;
friend class ContentParent;
public:
explicit SHEntryParent(LegacySHEntry* aEntry)
: PSHEntryParent(), mEntry(aEntry) {}
LegacySHEntry* GetSHEntry() { return mEntry; }
protected:
void ActorDestroy(ActorDestroyReason aWhy) override;
private:
bool RecvGetURI(RefPtr<nsIURI>* aURI);
bool RecvSetURI(nsIURI* aURI);
bool RecvGetOriginalURI(RefPtr<nsIURI>* aOriginalURI);
bool RecvSetOriginalURI(nsIURI* aOriginalURI);
bool RecvGetResultPrincipalURI(RefPtr<nsIURI>* aResultPrincipalURI);
bool RecvSetResultPrincipalURI(nsIURI* aResultPrincipalURI);
bool RecvGetLoadReplace(bool* aLoadReplace);
bool RecvSetLoadReplace(const bool& aLoadReplace);
bool RecvGetTitle(nsString* aTitle);
bool RecvSetTitle(const nsString& aTitle);
bool RecvGetIsSubFrame(bool* aIsSubFrame);
bool RecvSetIsSubFrame(const bool& aIsSubFrame);
bool RecvGetReferrerInfo(RefPtr<nsIReferrerInfo>* aReferrerInfo);
bool RecvSetReferrerInfo(nsIReferrerInfo* aReferrerInfo);
bool RecvGetSticky(bool* aSticky);
bool RecvSetSticky(const bool& aSticky);
bool RecvGetPostData(RefPtr<nsIInputStream>* aPostData);
bool RecvSetPostData(nsIInputStream* aPostData);
bool RecvGetParent(RefPtr<CrossProcessSHEntry>* aParentEntry);
bool RecvSetParent(PSHEntryParent* aParentEntry);
bool RecvGetLoadType(uint32_t* aLoadType);
bool RecvSetLoadType(const uint32_t& aLoadType);
bool RecvGetID(uint32_t* aID);
bool RecvSetID(const uint32_t& aID);
bool RecvGetCacheKey(uint32_t* aCacheKey);
bool RecvSetCacheKey(const uint32_t& aCacheKey);
bool RecvGetExpirationStatus(bool* aExpirationStatus);
bool RecvSetExpirationStatus(const bool& aExpirationStatus);
bool RecvGetContentType(nsCString* aContentType);
bool RecvSetContentType(const nsCString& aContentType);
bool RecvGetURIWasModified(bool* aURIWasModified);
bool RecvSetURIWasModified(const bool& aURIWasModified);
bool RecvGetTriggeringPrincipal(RefPtr<nsIPrincipal>* aTriggeringPrincipal);
bool RecvSetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal);
bool RecvGetPrincipalToInherit(RefPtr<nsIPrincipal>* aPrincipalToInherit);
bool RecvSetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit);
bool RecvGetStoragePrincipalToInherit(
RefPtr<nsIPrincipal>* aStoragePrincipalToInherit);
bool RecvSetStoragePrincipalToInherit(
nsIPrincipal* aStoragePrincipalToInherit);
bool RecvGetCsp(RefPtr<nsIContentSecurityPolicy>* aCsp);
bool RecvSetCsp(nsIContentSecurityPolicy* aCsp);
bool RecvGetStateData(ClonedMessageData* aData);
bool RecvSetStateData(ClonedMessageData&& aData);
bool RecvGetDocshellID(nsID* aDocshellID);
bool RecvSetDocshellID(const nsID& aDocshellID);
bool RecvGetIsSrcdocEntry(bool* aIsSrcdocEntry);
bool RecvGetSrcdocData(nsString* aSrcdocData);
bool RecvSetSrcdocData(const nsString& aSrcdocData);
bool RecvGetBaseURI(RefPtr<nsIURI>* aBaseURI);
bool RecvSetBaseURI(nsIURI* aBaseURI);
bool RecvGetScrollRestorationIsManual(bool* aScrollRestorationIsManual);
bool RecvSetScrollRestorationIsManual(const bool& aScrollRestorationIsManual);
bool RecvGetLoadedInThisProcess(bool* aLoadedInThisProcess);
bool RecvGetLastTouched(uint32_t* aLastTouched);
bool RecvSetLastTouched(const uint32_t& aLastTouched);
bool RecvGetChildCount(int32_t* aChildCount);
bool RecvGetPersist(bool* aPersist);
bool RecvSetPersist(const bool& aPersist);
bool RecvGetScrollPosition(int32_t* aX, int32_t* aY);
bool RecvSetScrollPosition(const int32_t& aX, const int32_t& aY);
bool RecvGetViewerBounds(nsIntRect* aBounds);
bool RecvSetViewerBounds(const nsIntRect& aBounds);
bool RecvCreate(nsIURI* aURI, const nsString& aTitle,
nsIInputStream* aInputStream, const uint32_t& aCacheKey,
const nsCString& aContentType,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aStoragePrincipalToInherit,
nsIContentSecurityPolicy* aCsp, const nsID& aDocshellID,
const bool& aDynamicCreation, nsIURI* aOriginalURI,
nsIURI* aResultPrincipalURI, const bool& aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& srcdoc,
const bool& srcdocEntry, nsIURI* aBaseURI,
const bool& aSaveLayoutState, const bool& aExpired);
bool RecvClone(PSHEntryParent** aCloneEntry);
bool RecvHasDetachedEditor(bool* aHasDetachedEditor);
bool RecvIsDynamicallyAdded(bool* aIsDynamicallyAdded);
bool RecvHasDynamicallyAddedChild(bool* aHasDynamicallyAddedChild);
bool RecvDocshellID(nsID* aDocshellID);
bool RecvAdoptBFCacheEntry(PSHEntryParent* aEntry, nsresult* aResult);
bool RecvAbandonBFCacheEntry(const uint64_t& aNewSharedID);
bool RecvSharesDocumentWith(PSHEntryParent* aEntry, bool* aSharesDocumentWith,
nsresult* aResult);
bool RecvSetLoadTypeAsHistory();
bool RecvAddChild(PSHEntryParent* aChild, const int32_t& aOffset,
const bool& aUseRemoteSubframes, nsresult* aResult);
bool RecvRemoveChild(PSHEntryParent* aChild, nsresult* aResult);
bool RecvGetChildAt(const int32_t& aIndex,
RefPtr<CrossProcessSHEntry>* aChild);
bool RecvGetChildSHEntryIfHasNoDynamicallyAddedChild(
const int32_t& aChildOffset, RefPtr<CrossProcessSHEntry>* aChild);
bool RecvReplaceChild(PSHEntryParent* aNewChild, nsresult* aResult);
bool RecvClearEntry(const uint64_t& aNewSharedID);
bool RecvCreateLoadInfo(RefPtr<nsDocShellLoadState>* aLoadState);
bool RecvClone(RefPtr<CrossProcessSHEntry>* aResult);
bool RecvSyncTreesForSubframeNavigation(
PSHEntryParent* aSHEntry, const MaybeDiscarded<BrowsingContext>& aBC,
const MaybeDiscarded<BrowsingContext>& aIgnoreBC,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate);
bool RecvUpdateLayoutHistoryState(const bool& aScrollPositionOnly,
nsTArray<nsCString>&& aKeys,
nsTArray<PresState>&& aStates);
RefPtr<LegacySHEntry> mEntry;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SHEntryParent_h */

View File

@@ -0,0 +1,470 @@
/* -*- 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/. */
#include "SHistoryChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PSHistoryChild.h"
#include "nsDocShell.h"
#include "nsISHistoryListener.h"
#include "SHEntryChild.h"
namespace mozilla {
namespace dom {
class SwapEntriesDocshellData;
}
} // namespace mozilla
#define CONTENT_VIEWER_TIMEOUT_SECONDS \
"browser.sessionhistory.contentViewerTimeout"
// Default this to time out unused content viewers after 30 minutes
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30 * 60)
namespace mozilla {
namespace dom {
void SHistoryChild::HistoryTracker::NotifyExpired(SHEntryChildShared* aObj) {
RemoveObject(aObj);
mSHistory->EvictExpiredContentViewerForEntry(aObj);
}
SHistoryChild::SHistoryChild(BrowsingContext* aRootBC)
: mRootDocShell(static_cast<nsDocShell*>(aRootBC->GetDocShell())),
mIPCActorDeleted(false) {
// Bind mHistoryTracker's event target to the tabGroup for aRootBC.
// Maybe move this to ChildSHistory?
nsCOMPtr<nsPIDOMWindowOuter> win = aRootBC->GetDOMWindow();
if (win) {
// Seamonkey moves shistory between <xul:browser>s when restoring a tab.
// Let's try not to break our friend too badly...
if (mHistoryTracker) {
NS_WARNING(
"Change the root docshell of a shistory is unsafe and "
"potentially problematic.");
mHistoryTracker->AgeAllGenerations();
}
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(win);
mHistoryTracker = mozilla::MakeUnique<SHistoryChild::HistoryTracker>(
this,
mozilla::Preferences::GetUint(CONTENT_VIEWER_TIMEOUT_SECONDS,
CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT),
global->EventTargetFor(mozilla::TaskCategory::Other));
}
}
NS_IMPL_ADDREF(SHistoryChild)
NS_IMETHODIMP_(MozExternalRefCountType) SHistoryChild::Release() {
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
NS_ASSERT_OWNINGTHREAD(SHEntryChild);
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, count, "SHistoryChild");
if (count == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
}
if (count == 1 && !mIPCActorDeleted) {
Unused << Send__delete__(this);
}
return count;
}
NS_IMPL_QUERY_INTERFACE(SHistoryChild, nsISHistory, nsISupportsWeakReference)
NS_IMETHODIMP
SHistoryChild::GetCount(int32_t* aCount) {
return SendGetCount(aCount) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::GetIndex(int32_t* aIndex) {
return SendGetIndex(aIndex) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::SetIndex(int32_t aIndex) {
nsresult rv;
return SendSetIndex(aIndex, &rv) ? rv : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::GetRequestedIndex(int32_t* aRequestedIndex) {
return SendGetRequestedIndex(aRequestedIndex) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP_(void)
SHistoryChild::InternalSetRequestedIndex(int32_t aRequestedIndex) {
SendInternalSetRequestedIndex(aRequestedIndex);
}
NS_IMETHODIMP
SHistoryChild::GetEntryAtIndex(int32_t aIndex, nsISHEntry** aResult) {
nsresult rv;
RefPtr<CrossProcessSHEntry> entry;
if (!SendGetEntryAtIndex(aIndex, &rv, &entry)) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
*aResult = entry ? do_AddRef(entry->ToSHEntryChild()).take() : nullptr;
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::PurgeHistory(int32_t aNumEntries) {
nsresult rv;
if (!SendPurgeHistory(aNumEntries, &rv)) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
if (mRootDocShell) {
mRootDocShell->HistoryPurged(aNumEntries);
}
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::AddSHistoryListener(nsISHistoryListener* aListener) {
NS_ENSURE_ARG_POINTER(aListener);
// Check if the listener supports Weak Reference. This is a must.
// This listener functionality is used by embedders and we want to
// have the right ownership with who ever listens to SHistory
nsWeakPtr listener = do_GetWeakReference(aListener);
if (!listener) {
return NS_ERROR_FAILURE;
}
mListeners.AppendElementUnlessExists(listener);
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::RemoveSHistoryListener(nsISHistoryListener* aListener) {
// Make sure the listener that wants to be removed is the
// one we have in store.
nsWeakPtr listener = do_GetWeakReference(aListener);
mListeners.RemoveElement(listener);
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::ReloadCurrentEntry() {
LoadSHEntryResult loadResult;
if (!SendReloadCurrentEntry(&loadResult)) {
return NS_ERROR_FAILURE;
}
if (loadResult.type() == LoadSHEntryResult::Tnsresult) {
return loadResult;
}
return LoadURI(loadResult);
}
NS_IMETHODIMP
SHistoryChild::GotoIndex(int32_t aIndex) {
LoadSHEntryResult loadResult;
if (!SendGotoIndex(aIndex, &loadResult)) {
return NS_ERROR_FAILURE;
}
if (loadResult.type() == LoadSHEntryResult::Tnsresult) {
return loadResult;
}
return LoadURI(loadResult);
}
NS_IMETHODIMP_(int32_t)
SHistoryChild::GetIndexOfEntry(nsISHEntry* aEntry) {
int32_t index;
if (!SendGetIndexOfEntry(static_cast<SHEntryChild*>(aEntry), &index)) {
return 0;
}
return index;
}
NS_IMETHODIMP
SHistoryChild::AddEntry(nsISHEntry* aEntry, bool aPersist) {
NS_ENSURE_ARG(aEntry);
nsresult rv;
int32_t entriesPurged;
if (!SendAddEntry(static_cast<SHEntryChild*>(aEntry), aPersist, &rv,
&entriesPurged)) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
if (mRootDocShell) {
aEntry->SetDocshellID(mRootDocShell->HistoryID());
if (entriesPurged > 0) {
mRootDocShell->HistoryPurged(entriesPurged);
}
}
return NS_OK;
}
NS_IMETHODIMP_(void)
SHistoryChild::ClearRootBrowsingContext() { mRootDocShell = nullptr; }
NS_IMETHODIMP
SHistoryChild::UpdateIndex(void) {
return SendUpdateIndex() ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::ReplaceEntry(int32_t aIndex, nsISHEntry* aReplaceEntry) {
nsresult rv;
if (!SendReplaceEntry(aIndex, static_cast<SHEntryChild*>(aReplaceEntry),
&rv)) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::NotifyOnHistoryReload(bool* _retval) {
return SendNotifyOnHistoryReload(_retval) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::EvictOutOfRangeContentViewers(int32_t aIndex) {
// FIXME Need to get out of range entries and entries that are safe (to
// compare content viewers so we don't evict live content viewers).
return SendEvictOutOfRangeContentViewers(aIndex) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SHistoryChild::EvictExpiredContentViewerForEntry(nsIBFCacheEntry* aBFEntry) {
SHEntryChildShared* shared = static_cast<SHEntryChildShared*>(aBFEntry);
RefPtr<CrossProcessSHEntry> entry;
int32_t index;
if (!SendFindEntryForBFCache(shared->GetID(), false, &entry, &index)) {
return NS_ERROR_FAILURE;
}
RefPtr<SHEntryChild> shEntry;
if (entry && (shEntry = entry->ToSHEntryChild())) {
shEntry->EvictContentViewer();
SendEvict(nsTArray<PSHEntryChild*>({shEntry.get()}));
}
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::EvictAllContentViewers(void) {
nsTArray<RefPtr<CrossProcessSHEntry>> entries;
if (!SendGetAllEntries(&entries)) {
return NS_ERROR_FAILURE;
}
// Keep a strong reference to all the entries, we're going to send the array
// back to the parent!
nsTArray<RefPtr<SHEntryChild>> shEntries(entries.Length());
for (RefPtr<CrossProcessSHEntry>& entry : entries) {
RefPtr<SHEntryChild> shEntry = entry->ToSHEntryChild();
shEntry->EvictContentViewer();
shEntries.AppendElement(shEntry.forget());
}
nsTArray<PSHEntryChild*> pshEntries;
pshEntries.AppendElements(shEntries);
SendEvict(pshEntries);
return NS_OK;
}
NS_IMETHODIMP_(void)
SHistoryChild::EvictContentViewersOrReplaceEntry(nsISHEntry* aNewSHEntry,
bool aReplace) {
SendEvictContentViewersOrReplaceEntry(static_cast<SHEntryChild*>(aNewSHEntry),
aReplace);
}
NS_IMETHODIMP_(void)
SHistoryChild::AddToExpirationTracker(nsIBFCacheEntry* aBFEntry) {
RefPtr<SHEntryChildShared> entry = static_cast<SHEntryChildShared*>(aBFEntry);
if (mHistoryTracker && entry) {
mHistoryTracker->AddObject(entry);
}
}
NS_IMETHODIMP_(void)
SHistoryChild::RemoveFromExpirationTracker(nsIBFCacheEntry* aBFEntry) {
RefPtr<SHEntryChildShared> entry = static_cast<SHEntryChildShared*>(aBFEntry);
MOZ_ASSERT(mHistoryTracker && !mHistoryTracker->IsEmpty());
if (mHistoryTracker && entry) {
mHistoryTracker->RemoveObject(entry);
}
}
NS_IMETHODIMP_(void)
SHistoryChild::RemoveDynEntries(int32_t aIndex, nsISHEntry* aEntry) {
SendRemoveDynEntries(aIndex, static_cast<SHEntryChild*>(aEntry));
}
NS_IMETHODIMP_(void)
SHistoryChild::EnsureCorrectEntryAtCurrIndex(nsISHEntry* aEntry) {
SendEnsureCorrectEntryAtCurrIndex(static_cast<SHEntryChild*>(aEntry));
}
NS_IMETHODIMP_(void)
SHistoryChild::RemoveDynEntriesForBFCacheEntry(nsIBFCacheEntry* aBFEntry) {
RefPtr<CrossProcessSHEntry> entry;
int32_t index;
if (!SendFindEntryForBFCache(
static_cast<SHEntryChildShared*>(aBFEntry)->GetID(), true, &entry,
&index)) {
return;
}
RefPtr<SHEntryChild> shEntry;
if (entry && (shEntry = entry->ToSHEntryChild())) {
RemoveDynEntries(index, shEntry);
}
}
NS_IMETHODIMP_(void)
SHistoryChild::RemoveEntries(nsTArray<nsID>& aIDs, int32_t aStartIndex) {
bool didRemove = false;
if (SendRemoveEntries(aIDs, aStartIndex, &didRemove) && didRemove &&
mRootDocShell) {
mRootDocShell->DispatchLocationChangeEvent();
}
}
NS_IMETHODIMP_(void)
SHistoryChild::RemoveFrameEntries(nsISHEntry* aEntry) {
SendRemoveFrameEntries(static_cast<SHEntryChild*>(aEntry));
}
NS_IMETHODIMP
SHistoryChild::Reload(uint32_t aReloadFlags) {
LoadSHEntryResult loadResult;
if (!SendReload(aReloadFlags, &loadResult)) {
return NS_ERROR_FAILURE;
}
if (loadResult.type() == LoadSHEntryResult::Tnsresult) {
return loadResult;
}
return LoadURI(loadResult);
}
NS_IMETHODIMP
SHistoryChild::CreateEntry(nsISHEntry** aEntry) {
uint64_t sharedID = SHEntryChildShared::CreateSharedID();
RefPtr<SHEntryChild> entry = static_cast<SHEntryChild*>(
Manager()->SendPSHEntryConstructor(this, sharedID));
if (!entry) {
return NS_ERROR_FAILURE;
}
entry.forget(aEntry);
return NS_OK;
}
nsresult SHistoryChild::LoadURI(nsTArray<LoadSHEntryData>& aLoadData) {
for (LoadSHEntryData& l : aLoadData) {
if (l.browsingContext().IsNullOrDiscarded()) {
continue;
}
nsCOMPtr<nsIDocShell> docShell = l.browsingContext().get()->GetDocShell();
if (!docShell) {
continue;
}
RefPtr<SHEntryChild> entry;
if (l.shEntry()) {
entry = l.shEntry()->ToSHEntryChild();
}
// FIXME Should this be sent through IPC?
l.loadState()->SetSHEntry(entry);
docShell->LoadURI(l.loadState(), false);
}
return NS_OK;
}
NS_IMETHODIMP
SHistoryChild::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
BrowsingContext* aBC, nsISHEntry* aEntry,
uint32_t aLoadType, bool aShouldPersist,
Maybe<int32_t>* aPreviousEntryIndex,
Maybe<int32_t>* aLoadedEntryIndex) {
nsresult rv;
int32_t entriesPurged;
nsTArray<SwapEntriesDocshellData> entriesToUpdate;
if (!SendAddToRootSessionHistory(
aCloneChildren, static_cast<SHEntryChild*>(aOSHE), aBC,
static_cast<SHEntryChild*>(aEntry), aLoadType, aShouldPersist,
aPreviousEntryIndex, aLoadedEntryIndex, &entriesToUpdate,
&entriesPurged, &rv)) {
return NS_ERROR_FAILURE;
}
for (auto& data : entriesToUpdate) {
MOZ_ASSERT(!data.context().IsNull(), "Browsing context cannot be null");
nsDocShell* docshell = static_cast<nsDocShell*>(
data.context().GetMaybeDiscarded()->GetDocShell());
if (docshell) {
docshell->SwapHistoryEntries(data.oldEntry()->ToSHEntryChild(),
data.newEntry()->ToSHEntryChild());
}
}
if (NS_SUCCEEDED(rv) && mRootDocShell && entriesPurged > 0) {
mRootDocShell->HistoryPurged(entriesPurged);
}
return rv;
}
NS_IMETHODIMP
SHistoryChild::AddChildSHEntryHelper(nsISHEntry* aCloneRef,
nsISHEntry* aNewEntry,
BrowsingContext* aBC,
bool aCloneChildren) {
nsresult rv;
RefPtr<CrossProcessSHEntry> child;
int32_t entriesPurged;
nsTArray<SwapEntriesDocshellData> entriesToUpdate;
if (!SendAddChildSHEntryHelper(static_cast<SHEntryChild*>(aCloneRef),
static_cast<SHEntryChild*>(aNewEntry), aBC,
aCloneChildren, &entriesToUpdate,
&entriesPurged, &child, &rv)) {
return NS_ERROR_FAILURE;
}
for (auto& data : entriesToUpdate) {
MOZ_ASSERT(!data.context().IsNull(), "Browsing context cannot be null");
nsDocShell* docshell = static_cast<nsDocShell*>(
data.context().GetMaybeDiscarded()->GetDocShell());
if (docshell) {
docshell->SwapHistoryEntries(data.oldEntry()->ToSHEntryChild(),
data.newEntry()->ToSHEntryChild());
}
}
if (!child) {
return rv;
}
if (NS_SUCCEEDED(rv) && mRootDocShell && entriesPurged > 0) {
mRootDocShell->HistoryPurged(entriesPurged);
}
return rv;
}
} // namespace dom
} // namespace mozilla

View File

@@ -0,0 +1,88 @@
/* -*- 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_SHistoryChild_h
#define mozilla_dom_SHistoryChild_h
#include "mozilla/dom/PSHistoryChild.h"
#include "nsExpirationTracker.h"
#include "nsISHistory.h"
#include "nsWeakReference.h"
class nsIDocShell;
namespace mozilla {
namespace dom {
class LoadSHEntryData;
class SHEntryChildShared;
/**
* Session history actor for the child process.
*/
class SHistoryChild final : public PSHistoryChild,
public nsISHistory,
public nsSupportsWeakReference {
friend class PSHistoryChild;
public:
explicit SHistoryChild(BrowsingContext* aBrowsingContext);
NS_DECL_ISUPPORTS
NS_DECL_NSISHISTORY
protected:
void ActorDestroy(ActorDestroyReason aWhy) override {
mIPCActorDeleted = true;
}
private:
bool RecvReloadCurrentEntryFromChild() {
ReloadCurrentEntry();
return true;
}
// The timer based history tracker is used to evict bfcache on expiration.
class HistoryTracker final
: public nsExpirationTracker<SHEntryChildShared, 3> {
public:
explicit HistoryTracker(SHistoryChild* aSHistory, uint32_t aTimeout,
nsIEventTarget* aEventTarget)
: nsExpirationTracker(1000 * aTimeout / 2, "HistoryTracker",
aEventTarget),
mSHistory(aSHistory) {
MOZ_ASSERT(aSHistory);
mSHistory = aSHistory;
}
protected:
void NotifyExpired(SHEntryChildShared* aObj) override;
private:
// HistoryTracker is owned by SHistoryChild; it always outlives
// HistoryTracker so it's safe to use raw pointer here.
SHistoryChild* mSHistory;
};
~SHistoryChild() = default;
nsresult LoadURI(nsTArray<LoadSHEntryData>& aLoadData);
// Track all bfcache entries and evict on expiration.
mozilla::UniquePtr<HistoryTracker> mHistoryTracker;
// Session History listeners
nsAutoTObserverArray<nsWeakPtr, 2> mListeners;
WeakPtr<nsDocShell> mRootDocShell;
bool mIPCActorDeleted;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SHistoryChild_h */

View File

@@ -0,0 +1,436 @@
/* -*- 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/. */
#include "SHistoryParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/SHEntryParent.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentProcessManager.h"
#include "mozilla/dom/PContentParent.h"
#include "mozilla/Logging.h"
#include "nsTHashtable.h"
#include "SHEntryChild.h"
extern mozilla::LazyLogModule gSHistoryLog;
namespace mozilla {
namespace dom {
LegacySHistory::LegacySHistory(SHistoryParent* aSHistoryParent,
CanonicalBrowsingContext* aRootBC,
const nsID& aDocShellID)
: nsSHistory(aRootBC, aDocShellID), mSHistoryParent(aSHistoryParent) {
mIsRemote = true;
aRootBC->SetSessionHistory(this);
}
static void FillInLoadResult(
nsresult aRv, const nsTArray<nsSHistory::LoadEntryResult>& aLoadResults,
LoadSHEntryResult* aResult) {
if (NS_SUCCEEDED(aRv)) {
nsTArray<LoadSHEntryData> data;
data.SetCapacity(aLoadResults.Length());
for (const nsSHistory::LoadEntryResult& l : aLoadResults) {
data.AppendElement(
LoadSHEntryData(static_cast<LegacySHEntry*>(l.mLoadState->SHEntry()),
l.mBrowsingContext, l.mLoadState));
}
*aResult = data;
} else {
*aResult = aRv;
}
}
SHistoryParent::SHistoryParent(CanonicalBrowsingContext* aContext)
: mHistory(new LegacySHistory(this, aContext, nsID())) {}
SHistoryParent::~SHistoryParent() { mHistory->mSHistoryParent = nullptr; }
SHEntryParent* SHistoryParent::CreateEntry(PContentParent* aContentParent,
PSHistoryParent* aSHistoryParent,
uint64_t aSharedID) {
RefPtr<LegacySHEntry> entry = new LegacySHEntry(
aContentParent, static_cast<SHistoryParent*>(aSHistoryParent)->mHistory,
aSharedID);
return entry->CreateActor();
}
void SHistoryParent::ActorDestroy(ActorDestroyReason aWhy) {}
bool SHistoryParent::RecvGetCount(int32_t* aCount) {
return NS_SUCCEEDED(mHistory->GetCount(aCount));
}
bool SHistoryParent::RecvGetIndex(int32_t* aIndex) {
return NS_SUCCEEDED(mHistory->GetIndex(aIndex));
}
bool SHistoryParent::RecvSetIndex(int32_t aIndex, nsresult* aResult) {
*aResult = mHistory->SetIndex(aIndex);
return true;
}
bool SHistoryParent::RecvGetRequestedIndex(int32_t* aIndex) {
return NS_SUCCEEDED(mHistory->GetRequestedIndex(aIndex));
}
bool SHistoryParent::RecvInternalSetRequestedIndex(int32_t aIndex) {
mHistory->InternalSetRequestedIndex(aIndex);
return true;
}
bool SHistoryParent::RecvGetEntryAtIndex(int32_t aIndex, nsresult* aResult,
RefPtr<CrossProcessSHEntry>* aEntry) {
nsCOMPtr<nsISHEntry> entry;
*aResult = mHistory->GetEntryAtIndex(aIndex, getter_AddRefs(entry));
*aEntry = entry.forget().downcast<LegacySHEntry>();
return true;
}
bool SHistoryParent::RecvPurgeHistory(int32_t aNumEntries, nsresult* aResult) {
*aResult = mHistory->PurgeHistory(aNumEntries);
return true;
}
bool SHistoryParent::RecvReloadCurrentEntry(LoadSHEntryResult* aLoadResult) {
nsTArray<nsSHistory::LoadEntryResult> loadResults;
nsresult rv = mHistory->ReloadCurrentEntry(loadResults);
if (NS_SUCCEEDED(rv)) {
FillInLoadResult(rv, loadResults, aLoadResult);
} else {
*aLoadResult = rv;
}
return true;
}
bool SHistoryParent::RecvGotoIndex(int32_t aIndex,
LoadSHEntryResult* aLoadResult) {
nsTArray<nsSHistory::LoadEntryResult> loadResults;
nsresult rv = mHistory->GotoIndex(aIndex, loadResults);
FillInLoadResult(rv, loadResults, aLoadResult);
return true;
}
bool SHistoryParent::RecvGetIndexOfEntry(PSHEntryParent* aEntry,
int32_t* aIndex) {
MOZ_ASSERT(Manager() == aEntry->Manager());
*aIndex =
mHistory->GetIndexOfEntry(static_cast<SHEntryParent*>(aEntry)->mEntry);
return true;
}
bool SHistoryParent::RecvAddEntry(PSHEntryParent* aEntry, bool aPersist,
nsresult* aResult, int32_t* aEntriesPurged) {
MOZ_ASSERT(Manager() == aEntry->Manager());
*aResult = mHistory->AddEntry(static_cast<SHEntryParent*>(aEntry)->mEntry,
aPersist, aEntriesPurged);
return true;
}
bool SHistoryParent::RecvUpdateIndex() {
return NS_SUCCEEDED(mHistory->UpdateIndex());
}
bool SHistoryParent::RecvReplaceEntry(int32_t aIndex, PSHEntryParent* aEntry,
nsresult* aResult) {
MOZ_ASSERT(Manager() == aEntry->Manager());
*aResult = mHistory->ReplaceEntry(
aIndex, static_cast<SHEntryParent*>(aEntry)->mEntry);
return true;
}
bool SHistoryParent::RecvNotifyOnHistoryReload(bool* aOk) {
return NS_SUCCEEDED(mHistory->NotifyOnHistoryReload(aOk));
}
bool SHistoryParent::RecvEvictOutOfRangeContentViewers(int32_t aIndex) {
return NS_SUCCEEDED(mHistory->EvictOutOfRangeContentViewers(aIndex));
}
bool SHistoryParent::RecvEvictAllContentViewers() {
return NS_SUCCEEDED(mHistory->EvictAllContentViewers());
}
bool SHistoryParent::RecvEvictContentViewersOrReplaceEntry(
PSHEntryParent* aNewSHEntry, bool aReplace) {
MOZ_ASSERT(Manager() == aNewSHEntry->Manager());
mHistory->EvictContentViewersOrReplaceEntry(
aNewSHEntry ? static_cast<SHEntryParent*>(aNewSHEntry)->mEntry.get()
: nullptr,
aReplace);
return true;
}
bool SHistoryParent::RecvRemoveDynEntries(int32_t aIndex,
PSHEntryParent* aEntry) {
MOZ_ASSERT(Manager() == aEntry->Manager());
mHistory->RemoveDynEntries(aIndex,
static_cast<SHEntryParent*>(aEntry)->mEntry);
return true;
}
bool SHistoryParent::RecvEnsureCorrectEntryAtCurrIndex(PSHEntryParent* aEntry) {
mHistory->EnsureCorrectEntryAtCurrIndex(
static_cast<SHEntryParent*>(aEntry)->mEntry);
return true;
}
bool SHistoryParent::RecvRemoveEntries(nsTArray<nsID>&& aIds, int32_t aIndex,
bool* aDidRemove) {
mHistory->RemoveEntries(aIds, aIndex, aDidRemove);
return true;
}
bool SHistoryParent::RecvRemoveFrameEntries(PSHEntryParent* aEntry) {
mHistory->RemoveFrameEntries(
static_cast<SHEntryParent*>(aEntry)->GetSHEntry());
return true;
}
bool SHistoryParent::RecvReload(const uint32_t& aReloadFlags,
LoadSHEntryResult* aLoadResult) {
nsTArray<nsSHistory::LoadEntryResult> loadResults;
nsresult rv = mHistory->Reload(aReloadFlags, loadResults);
if (NS_SUCCEEDED(rv) && loadResults.IsEmpty()) {
*aLoadResult = NS_OK;
} else {
FillInLoadResult(rv, loadResults, aLoadResult);
}
return true;
}
bool SHistoryParent::RecvGetAllEntries(
nsTArray<RefPtr<CrossProcessSHEntry>>* aEntries) {
nsTArray<nsCOMPtr<nsISHEntry>>& entries = mHistory->Entries();
uint32_t length = entries.Length();
aEntries->AppendElements(length);
for (uint32_t i = 0; i < length; ++i) {
aEntries->ElementAt(i) = static_cast<LegacySHEntry*>(entries[i].get());
}
return true;
}
bool SHistoryParent::RecvFindEntryForBFCache(
const uint64_t& aSharedID, const bool& aIncludeCurrentEntry,
RefPtr<CrossProcessSHEntry>* aEntry, int32_t* aIndex) {
int32_t currentIndex;
mHistory->GetIndex(&currentIndex);
int32_t startSafeIndex, endSafeIndex;
mHistory->WindowIndices(currentIndex, &startSafeIndex, &endSafeIndex);
for (int32_t i = startSafeIndex; i <= endSafeIndex; ++i) {
nsCOMPtr<nsISHEntry> entry;
nsresult rv = mHistory->GetEntryAtIndex(i, getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, false);
RefPtr<LegacySHEntry> shEntry = entry.forget().downcast<LegacySHEntry>();
if (shEntry->GetSharedStateID() == aSharedID) {
if (!aIncludeCurrentEntry && i == currentIndex) {
*aEntry = nullptr;
*aIndex = -1;
} else {
*aEntry = std::move(shEntry);
*aIndex = i;
}
return true;
}
}
*aEntry = nullptr;
*aIndex = -1;
return true;
}
bool SHistoryParent::RecvEvict(nsTArray<PSHEntryParent*>&& aEntries) {
for (PSHEntryParent* entry : aEntries) {
int32_t index =
mHistory->GetIndexOfEntry(static_cast<SHEntryParent*>(entry)->mEntry);
if (index != -1) {
mHistory->RemoveDynEntries(index,
static_cast<SHEntryParent*>(entry)->mEntry);
}
}
return true;
}
bool SHistoryParent::RecvNotifyListenersContentViewerEvicted(
uint32_t aNumEvicted) {
mHistory->NotifyListenersContentViewerEvicted(aNumEvicted);
return true;
}
void LegacySHistory::EvictOutOfRangeWindowContentViewers(int32_t aIndex) {
if (aIndex < 0) {
return;
}
NS_ENSURE_TRUE_VOID(aIndex < Length());
// Calculate the range that's safe from eviction.
int32_t startSafeIndex, endSafeIndex;
WindowIndices(aIndex, &startSafeIndex, &endSafeIndex);
// See nsSHistory::EvictOutOfRangeWindowContentViewers for more comments.
MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug,
("EvictOutOfRangeWindowContentViewers(index=%d), "
"Length()=%d. Safe range [%d, %d]",
aIndex, Length(), startSafeIndex, endSafeIndex));
// Collect content viewers within safe range so we don't accidentally evict
// one of them if it appears outside this range.
nsTHashtable<nsUint64HashKey> safeSharedStateIDs;
for (int32_t i = startSafeIndex; i <= endSafeIndex; i++) {
RefPtr<LegacySHEntry> entry =
static_cast<LegacySHEntry*>(mEntries[i].get());
MOZ_ASSERT(entry);
safeSharedStateIDs.PutEntry(entry->GetSharedStateID());
}
// Iterate over entries that are not within safe range and save the IDs
// of shared state and content parents into a hashtable.
// Format of the hashtable: content parent -> list of shared state IDs
nsDataHashtable<nsPtrHashKey<PContentParent>, nsTHashtable<nsUint64HashKey>>
toEvict;
for (int32_t i = 0; i < Length(); i++) {
if (i >= startSafeIndex && i <= endSafeIndex) {
continue;
}
RefPtr<LegacySHEntry> entry =
static_cast<LegacySHEntry*>(mEntries[i].get());
dom::SHEntrySharedParentState* sharedParentState = entry->GetSharedState();
uint64_t id = entry->GetSharedStateID();
PContentParent* parent =
static_cast<SHEntrySharedParent*>(sharedParentState)
->GetContentParent();
MOZ_ASSERT(parent);
if (!safeSharedStateIDs.Contains(id)) {
nsTHashtable<nsUint64HashKey>& ids = toEvict.GetOrInsert(parent);
ids.PutEntry(id);
}
}
if (toEvict.Count() == 0) {
return;
}
// Remove dynamically created children from entries that will be evicted
// later. We are iterating over the mEntries (instead of toEvict) to gain
// access to each nsSHEntry because toEvict only contains content parents and
// IDs of SHEntrySharedParentState
// (It's important that the condition checks Length(), rather than a cached
// copy of Length(), because the length might change between iterations due to
// RemoveDynEntries call.)
for (int32_t i = 0; i < Length(); i++) {
RefPtr<LegacySHEntry> entry =
static_cast<LegacySHEntry*>(mEntries[i].get());
MOZ_ASSERT(entry);
uint64_t id = entry->GetSharedStateID();
if (!safeSharedStateIDs.Contains(id)) {
// When dropping bfcache, we have to remove associated dynamic entries as
// well.
int32_t index = GetIndexOfEntry(entry);
if (index != -1) {
RemoveDynEntries(index, entry);
}
}
}
// Iterate over the 'toEvict' hashtable to get the IDs of content viewers to
// evict for each parent
for (auto iter = toEvict.ConstIter(); !iter.Done(); iter.Next()) {
auto parent = iter.Key();
const nsTHashtable<nsUint64HashKey>& ids = iter.Data();
// Convert ids into an array because we don't have support for passing
// nsTHashtable over IPC
AutoTArray<uint64_t, 4> evictArray;
for (auto iter = ids.ConstIter(); !iter.Done(); iter.Next()) {
evictArray.AppendElement(iter.Get()->GetKey());
}
Unused << parent->SendEvictContentViewers(evictArray);
}
}
NS_IMETHODIMP
LegacySHistory::CreateEntry(nsISHEntry** aEntry) {
NS_ENSURE_TRUE(mRootBC, NS_ERROR_FAILURE);
NS_ADDREF(*aEntry = new LegacySHEntry(
static_cast<CanonicalBrowsingContext*>(mRootBC)
->GetContentParent(),
this, SHEntryChildShared::CreateSharedID()));
return NS_OK;
}
NS_IMETHODIMP
LegacySHistory::ReloadCurrentEntry() {
return mSHistoryParent->SendReloadCurrentEntryFromChild() ? NS_OK
: NS_ERROR_FAILURE;
}
bool SHistoryParent::RecvAddToRootSessionHistory(
bool aCloneChildren, PSHEntryParent* aOSHE,
const MaybeDiscarded<BrowsingContext>& aBC, PSHEntryParent* aEntry,
uint32_t aLoadType, bool aShouldPersist,
Maybe<int32_t>* aPreviousEntryIndex, Maybe<int32_t>* aLoadedEntryIndex,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
int32_t* aEntriesPurged, nsresult* aResult) {
MOZ_ASSERT(!aBC.IsNull(), "Browsing context cannot be null");
nsTArray<EntriesAndBrowsingContextData> entriesToSendOverIDL;
*aResult = mHistory->AddToRootSessionHistory(
aCloneChildren,
aOSHE ? static_cast<SHEntryParent*>(aOSHE)->mEntry.get() : nullptr,
aBC.GetMaybeDiscarded(),
static_cast<SHEntryParent*>(aEntry)->mEntry.get(), aLoadType,
aShouldPersist, static_cast<ContentParent*>(Manager())->ChildID(),
aPreviousEntryIndex, aLoadedEntryIndex, &entriesToSendOverIDL,
aEntriesPurged);
SHistoryParent::CreateActorsForSwapEntries(entriesToSendOverIDL,
aEntriesToUpdate, Manager());
return true;
}
bool SHistoryParent::RecvAddChildSHEntryHelper(
PSHEntryParent* aCloneRef, PSHEntryParent* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aBC, bool aCloneChildren,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
int32_t* aEntriesPurged, RefPtr<CrossProcessSHEntry>* aChild,
nsresult* aResult) {
MOZ_ASSERT(!aBC.IsNull(), "Browsing context cannot be null");
nsCOMPtr<nsISHEntry> child;
nsTArray<EntriesAndBrowsingContextData> entriesToSendOverIPC;
*aResult = mHistory->AddChildSHEntryHelper(
static_cast<SHEntryParent*>(aCloneRef)->mEntry.get(),
aNewEntry ? static_cast<SHEntryParent*>(aNewEntry)->mEntry.get()
: nullptr,
aBC.GetMaybeDiscarded(), aCloneChildren,
static_cast<ContentParent*>(Manager())->ChildID(), &entriesToSendOverIPC,
aEntriesPurged, getter_AddRefs(child));
SHistoryParent::CreateActorsForSwapEntries(entriesToSendOverIPC,
aEntriesToUpdate, Manager());
*aChild = child.forget().downcast<LegacySHEntry>();
return true;
}
void SHistoryParent::CreateActorsForSwapEntries(
const nsTArray<EntriesAndBrowsingContextData>& aEntriesToSendOverIPC,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
PContentParent* aContentParent) {
for (auto& data : aEntriesToSendOverIPC) {
SwapEntriesDocshellData* toUpdate = aEntriesToUpdate->AppendElement();
// Old entry
toUpdate->oldEntry() = static_cast<LegacySHEntry*>(data.oldEntry.get());
// New entry
toUpdate->newEntry() = static_cast<LegacySHEntry*>(data.newEntry.get());
toUpdate->context() = data.context;
}
}
} // namespace dom
} // namespace mozilla

View File

@@ -0,0 +1,130 @@
/* -*- 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_SHistoryParent_h
#define mozilla_dom_SHistoryParent_h
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/PSHistoryParent.h"
#include "mozilla/RefPtr.h"
#include "nsSHistory.h"
namespace mozilla {
namespace dom {
class PSHEntryOrSharedID;
class SHistoryParent;
class SHEntryParent;
/**
* Session history implementation based on the legacy implementation that used
* to live in the child process. Ideally this wouldn't implement nsISHistory
* (it should only ever be accessed by SHistoryParent).
*/
class LegacySHistory final : public nsSHistory {
private:
friend class SHistoryParent;
virtual ~LegacySHistory() = default;
void EvictOutOfRangeWindowContentViewers(int32_t aIndex) override;
SHistoryParent* mSHistoryParent;
public:
LegacySHistory(SHistoryParent* aSHistoryParent,
CanonicalBrowsingContext* aRootBC, const nsID& aDocShellID);
NS_IMETHOD CreateEntry(nsISHEntry** aEntry) override;
using nsSHistory::ReloadCurrentEntry;
NS_IMETHOD ReloadCurrentEntry() override;
SHistoryParent* GetActor() { return mSHistoryParent; }
};
/**
* Session history actor for the parent process. Forwards to the legacy
* implementation that used to live in the child process (see LegacySHistory).
*/
class SHistoryParent final : public PSHistoryParent {
friend class LegacySHistory;
friend class PSHistoryParent;
friend class SHEntryParent;
public:
explicit SHistoryParent(CanonicalBrowsingContext* aContext);
virtual ~SHistoryParent();
static SHEntryParent* CreateEntry(PContentParent* aContentParent,
PSHistoryParent* aSHistoryParent,
uint64_t aSharedID);
// We have a list of entries we would like to return from
// the IPC call and we need to create actors for all of them
static void CreateActorsForSwapEntries(
const nsTArray<EntriesAndBrowsingContextData>& aEntriesToSendOverIPC,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
PContentParent* aContentParent);
protected:
void ActorDestroy(ActorDestroyReason aWhy) override;
private:
bool RecvGetCount(int32_t* aCount);
bool RecvGetIndex(int32_t* aIndex);
bool RecvSetIndex(int32_t aIndex, nsresult* aResult);
bool RecvGetRequestedIndex(int32_t* aIndex);
bool RecvInternalSetRequestedIndex(int32_t aIndex);
bool RecvGetEntryAtIndex(int32_t aIndex, nsresult* aResult,
RefPtr<CrossProcessSHEntry>* aEntry);
bool RecvPurgeHistory(int32_t aNumEntries, nsresult* aResult);
bool RecvReloadCurrentEntry(LoadSHEntryResult* aLoadResult);
bool RecvGotoIndex(int32_t aIndex, LoadSHEntryResult* aLoadResult);
bool RecvGetIndexOfEntry(PSHEntryParent* aEntry, int32_t* aIndex);
bool RecvAddEntry(PSHEntryParent* aEntry, bool aPersist, nsresult* aResult,
int32_t* aEntriesPurged);
bool RecvUpdateIndex();
bool RecvReplaceEntry(int32_t aIndex, PSHEntryParent* aEntry,
nsresult* aResult);
bool RecvNotifyOnHistoryReload(bool* aOk);
bool RecvEvictOutOfRangeContentViewers(int32_t aIndex);
bool RecvEvictAllContentViewers();
bool RecvRemoveDynEntries(int32_t aIndex, PSHEntryParent* aEntry);
bool RecvRemoveEntries(nsTArray<nsID>&& ids, int32_t aIndex,
bool* aDidRemove);
bool RecvRemoveFrameEntries(PSHEntryParent* aEntry);
bool RecvReload(const uint32_t& aReloadFlags, LoadSHEntryResult* aLoadResult);
bool RecvGetAllEntries(nsTArray<RefPtr<CrossProcessSHEntry>>* aEntries);
bool RecvFindEntryForBFCache(const uint64_t& aSharedID,
const bool& aIncludeCurrentEntry,
RefPtr<CrossProcessSHEntry>* aEntry,
int32_t* aIndex);
bool RecvEvict(nsTArray<PSHEntryParent*>&& aEntries);
bool RecvEnsureCorrectEntryAtCurrIndex(PSHEntryParent* aEntry);
bool RecvEvictContentViewersOrReplaceEntry(PSHEntryParent* aNewSHEntry,
bool aReplace);
bool RecvNotifyListenersContentViewerEvicted(uint32_t aNumEvicted);
bool RecvAddToRootSessionHistory(
bool aCloneChildren, PSHEntryParent* aOSHE,
const MaybeDiscarded<BrowsingContext>& aBC, PSHEntryParent* aEntry,
uint32_t aLoadType, bool aShouldPersist,
Maybe<int32_t>* aPreviousEntryIndex, Maybe<int32_t>* aLoadedEntryIndex,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
int32_t* aEntriesPurged, nsresult* aResult);
bool RecvAddChildSHEntryHelper(
PSHEntryParent* aCloneRef, PSHEntryParent* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aBC, bool aCloneChildren,
nsTArray<SwapEntriesDocshellData>* aEntriesToUpdate,
int32_t* aEntriesPurged, RefPtr<CrossProcessSHEntry>* aChild,
nsresult* aResult);
RefPtr<CanonicalBrowsingContext> mContext;
RefPtr<LegacySHistory> mHistory;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SHistoryParent_h */

View File

@@ -1,827 +0,0 @@
/* -*- 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/. */
#include "SessionHistoryEntry.h"
#include "nsDocShellLoadState.h"
#include "nsILayoutHistoryState.h"
#include "nsSHEntryShared.h"
#include "nsStructuredCloneContainer.h"
namespace mozilla {
namespace dom {
SessionHistoryInfo::SessionHistoryInfo(nsDocShellLoadState* aLoadState,
nsIChannel* aChannel)
: mURI(aLoadState->URI()),
mOriginalURI(aLoadState->OriginalURI()),
mResultPrincipalURI(aLoadState->ResultPrincipalURI()),
mReferrerInfo(aLoadState->GetReferrerInfo()),
mPostData(aLoadState->PostDataStream()),
mLoadType(aLoadState->LoadType()),
mScrollPositionX(0),
mScrollPositionY(0),
mSrcdocData(aLoadState->SrcdocData()),
mBaseURI(aLoadState->BaseURI()),
mLoadReplace(aLoadState->LoadReplace()),
mURIWasModified(false),
/* FIXME Should this be aLoadState->IsSrcdocLoad()? */
mIsSrcdocEntry(!aLoadState->SrcdocData().IsEmpty()),
mScrollRestorationIsManual(false) {
bool isNoStore = false;
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
Unused << httpChannel->IsNoStoreResponse(&isNoStore);
mPersist = !isNoStore;
}
}
static uint32_t gEntryID;
SessionHistoryEntry::SessionHistoryEntry(nsISHistory* aSessionHistory,
nsDocShellLoadState* aLoadState,
nsIChannel* aChannel)
: mInfo(new SessionHistoryInfo(aLoadState, aChannel)),
mSharedInfo(new SHEntrySharedParentState(aSessionHistory)),
mID(++gEntryID) {
mSharedInfo->mTriggeringPrincipal = aLoadState->TriggeringPrincipal();
mSharedInfo->mPrincipalToInherit = aLoadState->PrincipalToInherit();
mSharedInfo->mStoragePrincipalToInherit =
aLoadState->StoragePrincipalToInherit();
mSharedInfo->mCsp = aLoadState->Csp();
// FIXME Set remaining shared fields!
}
NS_IMPL_ISUPPORTS(SessionHistoryEntry, nsISHEntry)
NS_IMETHODIMP
SessionHistoryEntry::GetURI(nsIURI** aURI) {
nsCOMPtr<nsIURI> uri = mInfo->mURI;
uri.forget(aURI);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetURI(nsIURI* aURI) {
mInfo->mURI = aURI;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetOriginalURI(nsIURI** aOriginalURI) {
nsCOMPtr<nsIURI> originalURI = mInfo->mOriginalURI;
originalURI.forget(aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetOriginalURI(nsIURI* aOriginalURI) {
mInfo->mOriginalURI = aOriginalURI;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetResultPrincipalURI(nsIURI** aResultPrincipalURI) {
nsCOMPtr<nsIURI> resultPrincipalURI = mInfo->mResultPrincipalURI;
resultPrincipalURI.forget(aResultPrincipalURI);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
mInfo->mResultPrincipalURI = aResultPrincipalURI;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetLoadReplace(bool* aLoadReplace) {
*aLoadReplace = mInfo->mLoadReplace;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetLoadReplace(bool aLoadReplace) {
mInfo->mLoadReplace = aLoadReplace;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetTitle(nsAString& aTitle) {
aTitle = mInfo->mTitle;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetTitle(const nsAString& aTitle) {
mInfo->mTitle = aTitle;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetIsSubFrame(bool* aIsSubFrame) {
*aIsSubFrame = mSharedInfo->mIsFrameNavigation;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetIsSubFrame(bool aIsSubFrame) {
mSharedInfo->mIsFrameNavigation = aIsSubFrame;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
nsCOMPtr<nsIReferrerInfo> referrerInfo = mInfo->mReferrerInfo;
referrerInfo.forget(aReferrerInfo);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
mInfo->mReferrerInfo = aReferrerInfo;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetContentViewer(nsIContentViewer** aContentViewer) {
NS_WARNING("This lives in the child process");
*aContentViewer = nullptr;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetContentViewer(nsIContentViewer* aContentViewer) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::GetSticky(bool* aSticky) {
*aSticky = mSharedInfo->mSticky;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetSticky(bool aSticky) {
mSharedInfo->mSticky = aSticky;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetWindowState(nsISupports** aWindowState) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::SetWindowState(nsISupports* aWindowState) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::GetRefreshURIList(nsIMutableArray** aRefreshURIList) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::SetRefreshURIList(nsIMutableArray* aRefreshURIList) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::GetPostData(nsIInputStream** aPostData) {
nsCOMPtr<nsIInputStream> postData = mInfo->mPostData;
postData.forget(aPostData);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetPostData(nsIInputStream* aPostData) {
mInfo->mPostData = aPostData;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetLayoutHistoryState(
nsILayoutHistoryState** aLayoutHistoryState) {
nsCOMPtr<nsILayoutHistoryState> layoutHistoryState =
mSharedInfo->mLayoutHistoryState;
layoutHistoryState.forget(aLayoutHistoryState);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetLayoutHistoryState(
nsILayoutHistoryState* aLayoutHistoryState) {
mSharedInfo->mLayoutHistoryState = aLayoutHistoryState;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetParent(nsISHEntry** aParent) {
nsCOMPtr<nsISHEntry> parent = mParent;
parent.forget(aParent);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetParent(nsISHEntry* aParent) {
mParent = aParent;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetLoadType(uint32_t* aLoadType) {
*aLoadType = mInfo->mLoadType;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetLoadType(uint32_t aLoadType) {
mInfo->mLoadType = aLoadType;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetID(uint32_t* aID) {
*aID = mID;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetID(uint32_t aID) {
mID = aID;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetCacheKey(uint32_t* aCacheKey) {
*aCacheKey = mSharedInfo->mCacheKey;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetCacheKey(uint32_t aCacheKey) {
mSharedInfo->mCacheKey = aCacheKey;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetSaveLayoutStateFlag(bool* aSaveLayoutStateFlag) {
*aSaveLayoutStateFlag = mSharedInfo->mSaveLayoutState;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
mSharedInfo->mSaveLayoutState = aSaveLayoutStateFlag;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetExpirationStatus(bool* aExpirationStatus) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::SetExpirationStatus(bool aExpirationStatus) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::GetContentType(nsACString& aContentType) {
aContentType = mSharedInfo->mContentType;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetContentType(const nsACString& aContentType) {
mSharedInfo->mContentType = aContentType;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetURIWasModified(bool* aURIWasModified) {
*aURIWasModified = mInfo->mURIWasModified;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetURIWasModified(bool aURIWasModified) {
mInfo->mURIWasModified = aURIWasModified;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetTriggeringPrincipal(
nsIPrincipal** aTriggeringPrincipal) {
nsCOMPtr<nsIPrincipal> triggeringPrincipal =
mSharedInfo->mTriggeringPrincipal;
triggeringPrincipal.forget(aTriggeringPrincipal);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetTriggeringPrincipal(
nsIPrincipal* aTriggeringPrincipal) {
mSharedInfo->mTriggeringPrincipal = aTriggeringPrincipal;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit) {
nsCOMPtr<nsIPrincipal> principalToInherit = mSharedInfo->mPrincipalToInherit;
principalToInherit.forget(aPrincipalToInherit);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit) {
mSharedInfo->mPrincipalToInherit = aPrincipalToInherit;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetStoragePrincipalToInherit(
nsIPrincipal** aStoragePrincipalToInherit) {
nsCOMPtr<nsIPrincipal> storagePrincipalToInherit =
mSharedInfo->mStoragePrincipalToInherit;
storagePrincipalToInherit.forget(aStoragePrincipalToInherit);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetStoragePrincipalToInherit(
nsIPrincipal* aStoragePrincipalToInherit) {
mSharedInfo->mStoragePrincipalToInherit = aStoragePrincipalToInherit;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetCsp(nsIContentSecurityPolicy** aCsp) {
nsCOMPtr<nsIContentSecurityPolicy> csp = mSharedInfo->mCsp;
csp.forget(aCsp);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
mSharedInfo->mCsp = aCsp;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetStateData(nsIStructuredCloneContainer** aStateData) {
RefPtr<nsStructuredCloneContainer> stateData = mInfo->mStateData;
stateData.forget(aStateData);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetStateData(nsIStructuredCloneContainer* aStateData) {
mInfo->mStateData = static_cast<nsStructuredCloneContainer*>(aStateData);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetDocshellID(nsID& aDocshellID) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::SetDocshellID(const nsID& aDocshellID) {
NS_WARNING("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry) {
*aIsSrcdocEntry = mInfo->mIsSrcdocEntry;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetSrcdocData(nsAString& aSrcdocData) {
aSrcdocData = mInfo->mSrcdocData;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetSrcdocData(const nsAString& aSrcdocData) {
mInfo->mSrcdocData = aSrcdocData;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetBaseURI(nsIURI** aBaseURI) {
nsCOMPtr<nsIURI> baseURI = mInfo->mBaseURI;
baseURI.forget(aBaseURI);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetBaseURI(nsIURI* aBaseURI) {
mInfo->mBaseURI = aBaseURI;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetScrollRestorationIsManual(
bool* aScrollRestorationIsManual) {
*aScrollRestorationIsManual = mInfo->mScrollRestorationIsManual;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetScrollRestorationIsManual(
bool aScrollRestorationIsManual) {
mInfo->mScrollRestorationIsManual = aScrollRestorationIsManual;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetLoadedInThisProcess(bool* aLoadedInThisProcess) {
// FIXME
//*aLoadedInThisProcess = mInfo->mLoadedInThisProcess;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetShistory(nsISHistory** aShistory) {
nsCOMPtr<nsISHistory> sHistory = do_QueryReferent(mSharedInfo->mSHistory);
sHistory.forget(aShistory);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetLastTouched(uint32_t* aLastTouched) {
*aLastTouched = mSharedInfo->mLastTouched;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetLastTouched(uint32_t aLastTouched) {
mSharedInfo->mLastTouched = aLastTouched;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetChildCount(int32_t* aChildCount) {
*aChildCount = mChildren.Length();
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetPersist(bool* aPersist) {
*aPersist = mInfo->mPersist;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetPersist(bool aPersist) {
mInfo->mPersist = aPersist;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetScrollPosition(int32_t* aX, int32_t* aY) {
*aX = mInfo->mScrollPositionX;
*aY = mInfo->mScrollPositionY;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetScrollPosition(int32_t aX, int32_t aY) {
mInfo->mScrollPositionX = aX;
mInfo->mScrollPositionY = aY;
return NS_OK;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::GetViewerBounds(nsIntRect& bounds) {
bounds = mSharedInfo->mViewerBounds;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::SetViewerBounds(const nsIntRect& bounds) {
mSharedInfo->mViewerBounds = bounds;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::AddChildShell(nsIDocShellTreeItem* shell) {
MOZ_CRASH("This lives in the child process");
}
NS_IMETHODIMP
SessionHistoryEntry::ChildShellAt(int32_t index,
nsIDocShellTreeItem** _retval) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::ClearChildShells() {
MOZ_CRASH("This lives in the child process");
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::SyncPresentationState() {
MOZ_CRASH("This lives in the child process");
}
NS_IMETHODIMP
SessionHistoryEntry::InitLayoutHistoryState(
nsILayoutHistoryState** aLayoutHistoryState) {
if (!mSharedInfo->mLayoutHistoryState) {
nsCOMPtr<nsILayoutHistoryState> historyState;
historyState = NS_NewLayoutHistoryState();
SetLayoutHistoryState(historyState);
}
return GetLayoutHistoryState(aLayoutHistoryState);
}
NS_IMETHODIMP
SessionHistoryEntry::Create(
nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
uint32_t aCacheKey, const nsACString& aContentType,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aStoragePrincipalToInherit, nsIContentSecurityPolicy* aCsp,
const nsID& aDocshellID, bool aDynamicCreation, nsIURI* aOriginalURI,
nsIURI* aResultPrincipalURI, bool aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& aSrcdoc, bool aSrcdocEntry,
nsIURI* aBaseURI, bool aSaveLayoutState, bool aExpired) {
MOZ_CRASH("Might need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
SessionHistoryEntry::Clone(nsISHEntry** _retval) {
MOZ_CRASH("Might need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP_(nsDocShellEditorData*)
SessionHistoryEntry::ForgetEditorData() {
MOZ_CRASH("This lives in the child process");
return nullptr;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::SetEditorData(nsDocShellEditorData* aData) {
MOZ_CRASH("This lives in the child process");
}
NS_IMETHODIMP_(bool)
SessionHistoryEntry::HasDetachedEditor() {
MOZ_CRASH("This lives in the child process");
return false;
}
NS_IMETHODIMP_(bool)
SessionHistoryEntry::IsDynamicallyAdded() {
return mSharedInfo->mDynamicallyCreated;
}
NS_IMETHODIMP
SessionHistoryEntry::HasDynamicallyAddedChild(bool* aHasDynamicallyAddedChild) {
for (const auto& child : mChildren) {
if (child->IsDynamicallyAdded()) {
*aHasDynamicallyAddedChild = true;
return NS_OK;
}
}
*aHasDynamicallyAddedChild = false;
return NS_OK;
}
NS_IMETHODIMP_(bool)
SessionHistoryEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry) {
MOZ_CRASH("This lives in the child process");
return false;
}
NS_IMETHODIMP
SessionHistoryEntry::AdoptBFCacheEntry(nsISHEntry* aEntry) {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::AbandonBFCacheEntry() {
MOZ_CRASH("This lives in the child process");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SessionHistoryEntry::SharesDocumentWith(nsISHEntry* aEntry,
bool* aSharesDocumentWith) {
MOZ_CRASH("Might need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
SessionHistoryEntry::SetLoadTypeAsHistory() {
mInfo->mLoadType = LOAD_HISTORY;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::AddChild(nsISHEntry* aChild, int32_t aOffset,
bool aUseRemoteSubframes) {
MOZ_CRASH("Need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
SessionHistoryEntry::RemoveChild(nsISHEntry* aChild) {
MOZ_CRASH("Need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
SessionHistoryEntry::GetChildAt(int32_t aIndex, nsISHEntry** aChild) {
nsCOMPtr<nsISHEntry> child = mChildren.SafeElementAt(aIndex);
child.forget(aChild);
return NS_OK;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::GetChildSHEntryIfHasNoDynamicallyAddedChild(
int32_t aChildOffset, nsISHEntry** aChild) {
MOZ_CRASH("Need to implement this");
}
NS_IMETHODIMP
SessionHistoryEntry::ReplaceChild(nsISHEntry* aNewChild) {
MOZ_CRASH("Need to implement this");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::ClearEntry() {
int32_t childCount = GetChildCount();
// Remove all children of this entry
for (int32_t i = childCount; i > 0; --i) {
nsCOMPtr<nsISHEntry> child;
GetChildAt(i - 1, getter_AddRefs(child));
RemoveChild(child);
}
}
NS_IMETHODIMP
SessionHistoryEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
nsCOMPtr<nsIURI> uri = GetURI();
RefPtr<nsDocShellLoadState> loadState(new nsDocShellLoadState(mInfo->mURI));
loadState->SetOriginalURI(mInfo->mOriginalURI);
loadState->SetMaybeResultPrincipalURI(Some(mInfo->mResultPrincipalURI));
loadState->SetLoadReplace(mInfo->mLoadReplace);
loadState->SetPostDataStream(mInfo->mPostData);
loadState->SetReferrerInfo(mInfo->mReferrerInfo);
loadState->SetTypeHint(mSharedInfo->mContentType);
loadState->SetTriggeringPrincipal(mSharedInfo->mTriggeringPrincipal);
loadState->SetPrincipalToInherit(mSharedInfo->mPrincipalToInherit);
loadState->SetStoragePrincipalToInherit(
mSharedInfo->mStoragePrincipalToInherit);
loadState->SetCsp(mSharedInfo->mCsp);
// Do not inherit principal from document (security-critical!);
uint32_t flags = nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_NONE;
// Passing nullptr as aSourceDocShell gives the same behaviour as before
// aSourceDocShell was introduced. According to spec we should be passing
// the source browsing context that was used when the history entry was
// first created. bug 947716 has been created to address this issue.
nsAutoString srcdoc;
nsCOMPtr<nsIURI> baseURI;
if (mInfo->mIsSrcdocEntry) {
srcdoc = mInfo->mSrcdocData;
baseURI = mInfo->mBaseURI;
flags |= nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
} else {
srcdoc = VoidString();
}
loadState->SetSrcdocData(srcdoc);
loadState->SetBaseURI(baseURI);
loadState->SetLoadFlags(flags);
loadState->SetFirstParty(true);
loadState->SetSHEntry(this);
loadState.forget(aLoadState);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::GetBfcacheID(uint64_t* aBfcacheID) {
*aBfcacheID = mSharedInfo->mID;
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SynchronizeLayoutHistoryState() {
// No-op on purpose. See nsISHEntry.idl
return NS_OK;
}
NS_IMETHODIMP_(void)
SessionHistoryEntry::SyncTreesForSubframeNavigation(
nsISHEntry* aEntry, mozilla::dom::BrowsingContext* aTopBC,
mozilla::dom::BrowsingContext* aIgnoreBC) {
MOZ_CRASH("Need to implement this");
}
} // namespace dom
namespace ipc {
void IPDLParamTraits<dom::SessionHistoryInfoAndId>::Write(
IPC::Message* aMsg, IProtocol* aActor,
const dom::SessionHistoryInfoAndId& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mId);
const dom::SessionHistoryInfo* info = aParam.mInfo.get();
dom::ClonedMessageData stateData;
if (info->mStateData) {
JSStructuredCloneData& data = info->mStateData->Data();
auto iter = data.Start();
bool success;
stateData.data().data = data.Borrow(iter, data.Size(), &success);
if (NS_WARN_IF(!success)) {
return;
}
MOZ_ASSERT(info->mStateData->PortIdentifiers().IsEmpty() &&
info->mStateData->BlobImpls().IsEmpty() &&
info->mStateData->InputStreams().IsEmpty());
}
WriteIPDLParam(aMsg, aActor, info->mURI);
WriteIPDLParam(aMsg, aActor, info->mOriginalURI);
WriteIPDLParam(aMsg, aActor, info->mResultPrincipalURI);
WriteIPDLParam(aMsg, aActor, info->mReferrerInfo);
WriteIPDLParam(aMsg, aActor, info->mTitle);
WriteIPDLParam(aMsg, aActor, info->mPostData);
WriteIPDLParam(aMsg, aActor, info->mLoadType);
WriteIPDLParam(aMsg, aActor, info->mScrollPositionX);
WriteIPDLParam(aMsg, aActor, info->mScrollPositionY);
WriteIPDLParam(aMsg, aActor, stateData);
WriteIPDLParam(aMsg, aActor, info->mSrcdocData);
WriteIPDLParam(aMsg, aActor, info->mBaseURI);
WriteIPDLParam(aMsg, aActor, info->mLoadReplace);
WriteIPDLParam(aMsg, aActor, info->mURIWasModified);
WriteIPDLParam(aMsg, aActor, info->mIsSrcdocEntry);
WriteIPDLParam(aMsg, aActor, info->mScrollRestorationIsManual);
WriteIPDLParam(aMsg, aActor, info->mPersist);
}
bool IPDLParamTraits<dom::SessionHistoryInfoAndId>::Read(
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
dom::SessionHistoryInfoAndId* aResult) {
uint64_t id;
UniquePtr<dom::SessionHistoryInfo> info =
MakeUnique<dom::SessionHistoryInfo>();
dom::ClonedMessageData stateData;
if (!ReadIPDLParam(aMsg, aIter, aActor, &id) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mURI) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mOriginalURI) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mResultPrincipalURI) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mReferrerInfo) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mTitle) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mPostData) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mLoadType) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mScrollPositionX) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mScrollPositionY) ||
!ReadIPDLParam(aMsg, aIter, aActor, &stateData) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mSrcdocData) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mBaseURI) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mLoadReplace) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mURIWasModified) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mIsSrcdocEntry) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mScrollRestorationIsManual) ||
!ReadIPDLParam(aMsg, aIter, aActor, &info->mPersist)) {
aActor->FatalError("Error reading fields for SessionHistoryInfo");
return false;
}
info->mStateData = new nsStructuredCloneContainer();
if (aActor->GetSide() == ChildSide) {
UnpackClonedMessageDataForChild(stateData, *info->mStateData);
} else {
UnpackClonedMessageDataForParent(stateData, *info->mStateData);
}
aResult->mId = id;
aResult->mInfo = std::move(info);
return true;
}
} // namespace ipc
} // namespace mozilla

View File

@@ -1,125 +0,0 @@
/* -*- 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 "nsISHEntry.h"
#include "nsStructuredCloneContainer.h"
class nsDocShellLoadState;
class nsIChannel;
class nsIInputStream;
class nsIReferrerInfo;
class nsISHistory;
class nsIURI;
namespace mozilla {
namespace dom {
struct SessionHistoryInfoAndId;
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(nsDocShellLoadState* aLoadState, nsIChannel* aChannel);
bool operator==(const SessionHistoryInfo& aInfo) const {
return false; // FIXME
}
nsIURI* GetURI() const { return mURI; }
private:
friend class SessionHistoryEntry;
friend struct mozilla::ipc::IPDLParamTraits<SessionHistoryInfoAndId>;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mResultPrincipalURI;
nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
nsString mTitle;
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 = false;
};
// XXX Not sure that the id shouldn't just live in SessionHistoryInfo.
struct SessionHistoryInfoAndId {
SessionHistoryInfoAndId() = default;
SessionHistoryInfoAndId(uint64_t aId,
UniquePtr<mozilla::dom::SessionHistoryInfo> aInfo)
: mId(aId), mInfo(std::move(aInfo)) {}
SessionHistoryInfoAndId(SessionHistoryInfoAndId&& aInfoAndId) = default;
SessionHistoryInfoAndId& operator=(
const SessionHistoryInfoAndId& aInfoAndId) {
mId = aInfoAndId.mId;
mInfo = MakeUnique<SessionHistoryInfo>(*aInfoAndId.mInfo);
return *this;
}
bool operator==(const SessionHistoryInfoAndId& aInfoAndId) const {
return mId == aInfoAndId.mId && !mInfo == !aInfoAndId.mInfo &&
*mInfo == *aInfoAndId.mInfo;
}
uint64_t mId = 0;
UniquePtr<mozilla::dom::SessionHistoryInfo> mInfo;
};
// 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.
class SessionHistoryEntry : public nsISHEntry {
public:
SessionHistoryEntry(nsISHistory* aSessionHistory,
nsDocShellLoadState* aLoadState, nsIChannel* aChannel);
NS_DECL_ISUPPORTS
NS_DECL_NSISHENTRY
const SessionHistoryInfo& GetInfo() const { return *mInfo; }
private:
virtual ~SessionHistoryEntry() = default;
UniquePtr<SessionHistoryInfo> mInfo;
RefPtr<SHEntrySharedParentState> mSharedInfo;
nsISHEntry* mParent = nullptr;
uint32_t mID;
nsTArray<RefPtr<SessionHistoryEntry>> mChildren;
};
} // namespace dom
// Allow sending SessionHistoryInfo objects over IPC.
namespace ipc {
template <>
struct IPDLParamTraits<dom::SessionHistoryInfoAndId> {
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const dom::SessionHistoryInfoAndId& aParam);
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, dom::SessionHistoryInfoAndId* aResult);
};
} // namespace ipc
} // namespace mozilla
#endif /* mozilla_dom_SessionHistoryEntry_h */

View File

@@ -13,6 +13,11 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'shistory'
IPDL_SOURCES += [
'PSHEntry.ipdl',
'PSHistory.ipdl',
]
EXPORTS += [
'nsSHEntry.h',
'nsSHEntryShared.h',
@@ -21,15 +26,23 @@ EXPORTS += [
EXPORTS.mozilla.dom += [
'ChildSHistory.h',
'SessionHistoryEntry.h',
'MaybeNewPSHEntry.h',
'SHEntryChild.h',
'SHEntryParent.h',
'SHistoryChild.h',
'SHistoryParent.h',
]
UNIFIED_SOURCES += [
'ChildSHistory.cpp',
'MaybeNewPSHEntry.cpp',
'nsSHEntry.cpp',
'nsSHEntryShared.cpp',
'nsSHistory.cpp',
'SessionHistoryEntry.cpp',
'SHEntryChild.cpp',
'SHEntryParent.cpp',
'SHistoryChild.cpp',
'SHistoryParent.cpp',
]
LOCAL_INCLUDES += [

View File

@@ -150,6 +150,13 @@ interface nsISHistory: nsISupports
*/
void addEntry(in nsISHEntry aEntry, in boolean aPersist);
/**
* Clear the reference to the toplevel browsing context object that this
* SHistory object belongs to.
*/
[noscript, notxpcom]
void ClearRootBrowsingContext();
/**
* Update the index maintained by sessionHistory
*/

View File

@@ -10,7 +10,6 @@
#include "nsDocShell.h"
#include "nsDocShellEditorData.h"
#include "nsDocShellLoadState.h"
#include "nsDocShellLoadTypes.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentViewer.h"
@@ -22,6 +21,7 @@
#include "nsIURI.h"
#include "nsSHEntryShared.h"
#include "nsSHistory.h"
#include "SHEntryChild.h"
#include "mozilla/Logging.h"
#include "nsIReferrerInfo.h"
@@ -32,8 +32,8 @@ namespace dom = mozilla::dom;
static uint32_t gEntryID = 0;
nsSHEntry::nsSHEntry(nsISHistory* aSHistory)
: mShared(new nsSHEntryShared(aSHistory)),
nsSHEntry::nsSHEntry(dom::SHEntrySharedParentState* aState)
: mShared(aState),
mLoadType(0),
mID(gEntryID++),
mScrollPositionX(0),
@@ -173,6 +173,22 @@ nsSHEntry::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetContentViewer(nsIContentViewer* aViewer) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetContentViewer(nsIContentViewer** aResult) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSticky(bool aSticky) {
mShared->mSticky = aSticky;
@@ -298,6 +314,22 @@ nsSHEntry::SetCacheKey(uint32_t aCacheKey) {
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSaveLayoutStateFlag(bool aFlag) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetExpirationStatus(bool* aFlag) {
*aFlag = mShared->mExpired;
@@ -370,11 +402,14 @@ nsSHEntry::Create(
mResultPrincipalURI = aResultPrincipalURI;
mLoadReplace = aLoadReplace;
mReferrerInfo = aReferrerInfo;
return NS_OK;
}
mShared->mLayoutHistoryState = nullptr;
mShared->mSaveLayoutState = aSaveLayoutState;
NS_IMETHODIMP
nsSHEntry::Clone(nsISHEntry** aResult) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
@@ -396,6 +431,22 @@ nsSHEntry::SetParent(nsISHEntry* aParent) {
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetWindowState(nsISupports* aState) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetWindowState(nsISupports** aState) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::SetViewerBounds(const nsIntRect& aBounds) {
mShared->mViewerBounds = aBounds;
@@ -457,9 +508,17 @@ nsSHEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
return NS_OK;
}
bool nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return false;
}
NS_IMETHODIMP
nsSHEntry::AdoptBFCacheEntry(nsISHEntry* aEntry) {
nsSHEntryShared* shared = static_cast<nsSHEntry*>(aEntry)->mShared;
dom::SHEntrySharedParentState* shared =
static_cast<nsSHEntry*>(aEntry)->mShared;
NS_ENSURE_STATE(shared);
mShared = shared;
@@ -474,6 +533,14 @@ nsSHEntry::SharesDocumentWith(nsISHEntry* aEntry, bool* aOut) {
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::AbandonBFCacheEntry() {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry) {
*aIsSrcdocEntry = mIsSrcdocEntry;
@@ -741,7 +808,71 @@ NS_IMETHODIMP_(void) nsSHEntry::ClearEntry() {
GetChildAt(i, getter_AddRefs(child));
RemoveChild(child);
}
AbandonBFCacheEntry();
}
NS_IMETHODIMP_(void)
nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
}
NS_IMETHODIMP
nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::ClearChildShells() {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
}
NS_IMETHODIMP
nsSHEntry::GetRefreshURIList(nsIMutableArray** aList) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetRefreshURIList(nsIMutableArray* aList) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::SyncPresentationState() {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
}
nsDocShellEditorData* nsSHEntry::ForgetEditorData() {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return nullptr;
}
void nsSHEntry::SetEditorData(nsDocShellEditorData* aData) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
}
bool nsSHEntry::HasDetachedEditor() {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return false;
}
NS_IMETHODIMP
@@ -884,10 +1015,22 @@ nsSHEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::SyncTreesForSubframeNavigation(
nsISHEntry* aEntry, mozilla::dom::BrowsingContext* aTopBC,
mozilla::dom::BrowsingContext* aIgnoreBC) {
NS_IMETHODIMP
nsSHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
return NS_OK;
}
void nsSHEntry::SyncTreesForSubframeNavigation(
uint64_t aOtherPid, nsISHEntry* aEntry,
mozilla::dom::BrowsingContext* aTopBC,
mozilla::dom::BrowsingContext* aIgnoreBC,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate) {
MOZ_ASSERT(aEntriesToUpdate || aOtherPid == 0,
"our entries to update is null");
// We need to sync up the browsing context and session history trees for
// subframe navigation. If the load was in a subframe, we forward up to
// the top browsing context, which will then recursively sync up all browsing
@@ -904,12 +1047,24 @@ nsSHEntry::SyncTreesForSubframeNavigation(
nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(this);
if (oldRootEntry) {
nsSHistory::SwapEntriesData data = {aIgnoreBC, newRootEntry, nullptr};
nsSHistory::SwapEntriesData data = {aIgnoreBC, newRootEntry, nullptr,
aOtherPid, aEntriesToUpdate};
nsSHistory::SetChildHistoryEntry(oldRootEntry, aTopBC, 0, &data);
}
}
}
NS_IMETHODIMP_(void)
nsSHEntry::SyncTreesForSubframeNavigation(
nsISHEntry* aEntry, mozilla::dom::BrowsingContext* aTopBC,
mozilla::dom::BrowsingContext* aIgnoreBC) {
SyncTreesForSubframeNavigation(
0 /* unused, this will be set in SHEntryParent::RecvSyncTrees */,
aEntry, aTopBC, aIgnoreBC,
nullptr /* this will be given in SHEntryCHild::SyncTrees if we
are going over IPC, else, it is not needed */);
}
void nsSHEntry::EvictContentViewer() {
nsCOMPtr<nsIContentViewer> viewer = GetContentViewer();
if (viewer) {
@@ -928,33 +1083,58 @@ nsSHEntry::SynchronizeLayoutHistoryState() {
return NS_OK;
}
nsLegacySHEntry::nsLegacySHEntry(nsISHistory* aHistory, uint64_t aID)
: nsSHEntry(new nsSHEntryShared(aHistory, aID)) {}
NS_IMETHODIMP
nsSHEntry::SetContentViewer(nsIContentViewer* aViewer) {
nsLegacySHEntry::SetContentViewer(nsIContentViewer* aViewer) {
return GetState()->SetContentViewer(aViewer);
}
NS_IMETHODIMP
nsSHEntry::GetContentViewer(nsIContentViewer** aResult) {
nsLegacySHEntry::GetContentViewer(nsIContentViewer** aResult) {
*aResult = GetState()->mContentViewer;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::Clone(nsISHEntry** aResult) {
nsCOMPtr<nsISHEntry> entry = new nsSHEntry(*this);
nsLegacySHEntry::Create(
nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
uint32_t aCacheKey, const nsACString& aContentType,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aStoragePrincipalToInherit, nsIContentSecurityPolicy* aCsp,
const nsID& aDocShellID, bool aDynamicCreation, nsIURI* aOriginalURI,
nsIURI* aResultPrincipalURI, bool aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& aSrcdocData,
bool aSrcdocEntry, nsIURI* aBaseURI, bool aSaveLayoutState, bool aExpired) {
mShared->mLayoutHistoryState = nullptr;
mShared->mSaveLayoutState = aSaveLayoutState;
return nsSHEntry::Create(aURI, aTitle, aInputStream, aCacheKey, aContentType,
aTriggeringPrincipal, aPrincipalToInherit,
aStoragePrincipalToInherit, aCsp, aDocShellID,
aDynamicCreation, aOriginalURI, aResultPrincipalURI,
aLoadReplace, aReferrerInfo, aSrcdocData,
aSrcdocEntry, aBaseURI, aSaveLayoutState, aExpired);
}
NS_IMETHODIMP
nsLegacySHEntry::Clone(nsISHEntry** aResult) {
nsCOMPtr<nsISHEntry> entry = new nsLegacySHEntry(*this);
entry.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag) {
nsLegacySHEntry::GetSaveLayoutStateFlag(bool* aFlag) {
*aFlag = mShared->mSaveLayoutState;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSaveLayoutStateFlag(bool aFlag) {
nsLegacySHEntry::SetSaveLayoutStateFlag(bool aFlag) {
mShared->mSaveLayoutState = aFlag;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
@@ -964,53 +1144,55 @@ nsSHEntry::SetSaveLayoutStateFlag(bool aFlag) {
}
NS_IMETHODIMP
nsSHEntry::SetWindowState(nsISupports* aState) {
nsLegacySHEntry::SetWindowState(nsISupports* aState) {
GetState()->mWindowState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetWindowState(nsISupports** aState) {
nsLegacySHEntry::GetWindowState(nsISupports** aState) {
NS_IF_ADDREF(*aState = GetState()->mWindowState);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetRefreshURIList(nsIMutableArray** aList) {
nsLegacySHEntry::GetRefreshURIList(nsIMutableArray** aList) {
NS_IF_ADDREF(*aList = GetState()->mRefreshURIList);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetRefreshURIList(nsIMutableArray* aList) {
nsLegacySHEntry::SetRefreshURIList(nsIMutableArray* aList) {
GetState()->mRefreshURIList = aList;
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell) {
nsLegacySHEntry::AddChildShell(nsIDocShellTreeItem* aShell) {
MOZ_ASSERT(aShell, "Null child shell added to history entry");
GetState()->mChildShells.AppendObject(aShell);
}
NS_IMETHODIMP
nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell) {
nsLegacySHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell) {
NS_IF_ADDREF(*aShell = GetState()->mChildShells.SafeObjectAt(aIndex));
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHEntry::ClearChildShells() { GetState()->mChildShells.Clear(); }
nsLegacySHEntry::ClearChildShells() { GetState()->mChildShells.Clear(); }
NS_IMETHODIMP_(void)
nsSHEntry::SyncPresentationState() { GetState()->SyncPresentationState(); }
nsLegacySHEntry::SyncPresentationState() {
GetState()->SyncPresentationState();
}
nsDocShellEditorData* nsSHEntry::ForgetEditorData() {
nsDocShellEditorData* nsLegacySHEntry::ForgetEditorData() {
// XXX jlebar Check how this is used.
return GetState()->mEditorData.release();
}
void nsSHEntry::SetEditorData(nsDocShellEditorData* aData) {
void nsLegacySHEntry::SetEditorData(nsDocShellEditorData* aData) {
NS_ASSERTION(!(aData && GetState()->mEditorData),
"We're going to overwrite an owning ref!");
if (GetState()->mEditorData != aData) {
@@ -1018,22 +1200,33 @@ void nsSHEntry::SetEditorData(nsDocShellEditorData* aData) {
}
}
bool nsSHEntry::HasDetachedEditor() {
bool nsLegacySHEntry::HasDetachedEditor() {
return GetState()->mEditorData != nullptr;
}
bool nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry) {
bool nsLegacySHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry) {
return static_cast<nsIBFCacheEntry*>(GetState()) == aEntry;
}
NS_IMETHODIMP
nsSHEntry::AbandonBFCacheEntry() {
mShared = GetState()->Duplicate();
nsLegacySHEntry::AbandonBFCacheEntry() {
mShared =
GetState()->Duplicate(mozilla::dom::SHEntryChildShared::CreateSharedID());
return NS_OK;
}
NS_IMETHODIMP_(void)
nsLegacySHEntry::ClearEntry() {
nsSHEntry::ClearEntry();
AbandonBFCacheEntry();
}
NS_IMETHODIMP
nsSHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
nsLegacySHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
*aBFCacheID = mShared->GetID();
return NS_OK;
}
nsSHEntryShared* nsLegacySHEntry::GetState() {
return static_cast<nsSHEntryShared*>(mShared.get());
}

View File

@@ -14,15 +14,33 @@
#include "mozilla/Attributes.h"
namespace mozilla {
namespace dom {
class SHEntrySharedChildState;
class SHEntrySharedParentState;
} // namespace dom
} // namespace mozilla
class nsSHEntryShared;
class nsIInputStream;
class nsIURI;
class nsIReferrerInfo;
// Structure for passing around entries via XPCOM from methods such as
// nsSHistory::CloneAndReplaceChild, nsSHistory::SetChildHistoryEntry and
// nsSHEntry::SyncTreesForSubframeNavigation, that need to swap entries in
// docshell, to corresponding Recv methods so that we don't have to create
// actors until we are about to return from the parent process
struct EntriesAndBrowsingContextData {
nsCOMPtr<nsISHEntry> oldEntry;
nsCOMPtr<nsISHEntry> newEntry;
mozilla::dom::BrowsingContext* context;
};
class nsSHEntry : public nsISHEntry {
public:
explicit nsSHEntry(nsISHistory* aSHistory);
NS_DECL_ISUPPORTS
NS_DECL_NSISHENTRY
@@ -30,16 +48,20 @@ class nsSHEntry : public nsISHEntry {
static nsresult Startup();
static void Shutdown();
void SyncTreesForSubframeNavigation(
uint64_t aOtherPid, nsISHEntry* aEntry,
mozilla::dom::BrowsingContext* aTopBC,
mozilla::dom::BrowsingContext* aIgnoreBC,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate);
protected:
explicit nsSHEntry(mozilla::dom::SHEntrySharedParentState* aState);
explicit nsSHEntry(const nsSHEntry& aOther);
virtual ~nsSHEntry();
nsSHEntryShared* GetState() { return mShared; }
// We share the state in here with other SHEntries which correspond to the
// same document.
RefPtr<nsSHEntryShared> mShared;
RefPtr<mozilla::dom::SHEntrySharedParentState> mShared;
// See nsSHEntry.idl for comments on these members.
nsCOMPtr<nsIURI> mURI;
@@ -65,4 +87,53 @@ class nsSHEntry : public nsISHEntry {
bool mPersist;
};
/**
* Session history entry class used for implementing session history for
* docshells in the parent process (a different solution would be to use the
* IPC actors for that too, with both parent and child actor created in the
* parent process).
*/
class nsLegacySHEntry final : public nsSHEntry {
public:
explicit nsLegacySHEntry(nsISHistory* aHistory, uint64_t aID);
explicit nsLegacySHEntry(const nsLegacySHEntry& aOther) : nsSHEntry(aOther) {}
NS_IMETHOD GetContentViewer(nsIContentViewer** aResult) override;
NS_IMETHOD SetContentViewer(nsIContentViewer* aViewer) override;
NS_IMETHOD GetWindowState(nsISupports** aState) override;
NS_IMETHOD SetWindowState(nsISupports* aState) override;
using nsISHEntry::GetRefreshURIList;
NS_IMETHOD GetRefreshURIList(nsIMutableArray** aRefreshURIList) override;
NS_IMETHOD SetRefreshURIList(nsIMutableArray* aRefreshURIList) override;
using nsISHEntry::GetSaveLayoutStateFlag;
NS_IMETHOD GetSaveLayoutStateFlag(bool* aSaveLayoutStateFlag) override;
NS_IMETHOD SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) override;
NS_IMETHOD_(void) AddChildShell(nsIDocShellTreeItem* aShell) override;
NS_IMETHOD ChildShellAt(int32_t aIndex,
nsIDocShellTreeItem** aShell) override;
NS_IMETHOD_(void) ClearChildShells() override;
NS_IMETHOD_(void) SyncPresentationState() override;
NS_IMETHOD Create(
nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
uint32_t aCacheKey, const nsACString& aContentType,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aStoragePrincipalToInherit, nsIContentSecurityPolicy* aCsp,
const nsID& aDocshellID, bool aDynamicCreation, nsIURI* aOriginalURI,
nsIURI* aResultPrincipalURI, bool aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& aSrcdocData,
bool aSrcdocEntry, nsIURI* aBaseURI, bool aSaveLayoutState,
bool aExpired) override;
NS_IMETHOD Clone(nsISHEntry** aResult) override;
NS_IMETHOD_(nsDocShellEditorData*) ForgetEditorData(void) override;
NS_IMETHOD_(void) SetEditorData(nsDocShellEditorData* aData) override;
NS_IMETHOD_(bool) HasDetachedEditor() override;
NS_IMETHOD_(bool) HasBFCacheEntry(nsIBFCacheEntry* aEntry) override;
NS_IMETHOD AbandonBFCacheEntry() override;
NS_IMETHOD_(void) ClearEntry() override;
NS_IMETHOD GetBfcacheID(uint64_t* aBFCacheID) override;
private:
nsSHEntryShared* GetState();
};
#endif /* nsSHEntry_h */

View File

@@ -21,23 +21,21 @@
namespace dom = mozilla::dom;
namespace {
uint64_t gSHEntrySharedID = 0;
} // namespace
namespace mozilla {
namespace dom {
SHEntrySharedParentState::SHEntrySharedParentState(nsISHistory* aSHistory)
: SHEntrySharedParentState(
nsWeakPtr(do_GetWeakReference(aSHistory)).get()) {}
SHEntrySharedParentState::SHEntrySharedParentState(nsISHistory* aSHistory,
uint64_t aID)
: SHEntrySharedParentState(nsWeakPtr(do_GetWeakReference(aSHistory)).get(),
aID) {}
SHEntrySharedParentState::SHEntrySharedParentState(nsIWeakReference* aSHistory)
SHEntrySharedParentState::SHEntrySharedParentState(nsIWeakReference* aSHistory,
uint64_t aID)
: mDocShellID({0}),
mViewerBounds(0, 0, 0, 0),
mCacheKey(0),
mLastTouched(0),
mID(++gSHEntrySharedID),
mID(aID),
mSHistory(aSHistory),
mIsFrameNavigation(false),
mSticky(true),
@@ -69,8 +67,12 @@ void dom::SHEntrySharedParentState::NotifyListenersContentViewerEvicted() {
}
}
dom::SHEntrySharedChildState::SHEntrySharedChildState()
: mSaveLayoutState(true) {}
void SHEntrySharedChildState::CopyFrom(SHEntrySharedChildState* aEntry) {
mChildShells.AppendObjects(aEntry->mChildShells);
mSaveLayoutState = aEntry->mSaveLayoutState;
}
} // namespace dom
@@ -100,8 +102,9 @@ NS_IMPL_QUERY_INTERFACE(nsSHEntryShared, nsIBFCacheEntry, nsIMutationObserver)
NS_IMPL_ADDREF_INHERITED(nsSHEntryShared, dom::SHEntrySharedParentState)
NS_IMPL_RELEASE_INHERITED(nsSHEntryShared, dom::SHEntrySharedParentState)
already_AddRefed<nsSHEntryShared> nsSHEntryShared::Duplicate() {
RefPtr<nsSHEntryShared> newEntry = new nsSHEntryShared(this);
already_AddRefed<nsSHEntryShared> nsSHEntryShared::Duplicate(
uint64_t aNewSharedID) {
RefPtr<nsSHEntryShared> newEntry = new nsSHEntryShared(this, aNewSharedID);
newEntry->dom::SHEntrySharedParentState::CopyFrom(this);
newEntry->dom::SHEntrySharedChildState::CopyFrom(this);

View File

@@ -53,12 +53,11 @@ class SHEntrySharedParentState {
void NotifyListenersContentViewerEvicted();
explicit SHEntrySharedParentState(nsISHistory* aSHistory);
protected:
explicit SHEntrySharedParentState(SHEntrySharedParentState* aDuplicate)
: SHEntrySharedParentState(aDuplicate->mSHistory) {}
explicit SHEntrySharedParentState(nsIWeakReference* aSHistory);
SHEntrySharedParentState(nsISHistory* aSHistory, uint64_t aID);
SHEntrySharedParentState(SHEntrySharedParentState* aDuplicate, uint64_t aID)
: SHEntrySharedParentState(aDuplicate->mSHistory, aID) {}
SHEntrySharedParentState(nsIWeakReference* aSHistory, uint64_t aID);
virtual ~SHEntrySharedParentState();
NS_INLINE_DECL_VIRTUAL_REFCOUNTING_WITH_DESTROY(SHEntrySharedParentState,
Destroy())
@@ -105,6 +104,8 @@ class SHEntrySharedParentState {
*/
class SHEntrySharedChildState {
protected:
SHEntrySharedChildState();
void CopyFrom(SHEntrySharedChildState* aSource);
public:
@@ -116,11 +117,16 @@ class SHEntrySharedChildState {
// they're specific to a particular content viewer.
nsCOMPtr<nsIContentViewer> mContentViewer;
RefPtr<mozilla::dom::Document> mDocument;
// FIXME Move to parent?
nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
nsCOMPtr<nsISupports> mWindowState;
// FIXME Move to parent?
nsCOMPtr<nsIMutableArray> mRefreshURIList;
nsExpirationState mExpirationState;
UniquePtr<nsDocShellEditorData> mEditorData;
// FIXME Move to parent?
bool mSaveLayoutState;
};
} // namespace dom
@@ -143,7 +149,7 @@ class nsSHEntryShared final : public nsIBFCacheEntry,
using SHEntrySharedParentState::SHEntrySharedParentState;
already_AddRefed<nsSHEntryShared> Duplicate();
already_AddRefed<nsSHEntryShared> Duplicate(uint64_t aNewSharedID);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIBFCACHEENTRY
@@ -160,7 +166,7 @@ class nsSHEntryShared final : public nsIBFCacheEntry,
private:
~nsSHEntryShared();
friend class nsSHEntry;
friend class nsLegacySHEntry;
void RemoveFromExpirationTracker();
void SyncPresentationState();

View File

@@ -29,13 +29,15 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/MaybeNewPSHEntry.h"
#include "mozilla/dom/SHEntryChild.h"
#include "mozilla/dom/SHEntryParent.h"
#include "mozilla/LinkedList.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "nsIWebNavigation.h"
#include "nsDocShellLoadTypes.h"
#include "base/process.h"
@@ -202,12 +204,12 @@ void nsSHistory::EvictContentViewerForEntry(nsISHEntry* aEntry) {
}
}
nsSHistory::nsSHistory(BrowsingContext* aRootBC)
nsSHistory::nsSHistory(BrowsingContext* aRootBC, const nsID& aRootDocShellID)
: mRootBC(aRootBC),
mIsRemote(false),
mIndex(-1),
mRequestedIndex(-1),
mRootDocShellID(aRootBC->GetHistoryID()) {
mRootDocShellID(aRootDocShellID) {
// Add this new SHistory object to the list
gSHistoryList.insertBack(this);
@@ -394,10 +396,20 @@ nsresult nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
for (BrowsingContext* child : aBC->Children()) {
// If the SH pref is on, or we are in the parent process, update
// canonical BC directly
nsDocShell* docshell = static_cast<nsDocShell*>(child->GetDocShell());
if (docshell && docshell->HasHistoryEntry(childEntry)) {
childBC = docshell->GetBrowsingContext();
break;
if (StaticPrefs::fission_sessionHistoryInParent() ||
XRE_IsParentProcess()) {
// Walk the children of the browsing context and see if one of them
// has childEntry as mOSHE or mLSHE
if (child->Canonical()->HasHistoryEntry(childEntry)) {
childBC = child;
break;
}
} else {
nsDocShell* docshell = static_cast<nsDocShell*>(child->GetDocShell());
if (docshell && docshell->HasHistoryEntry(childEntry)) {
childBC = docshell->GetBrowsingContext();
break;
}
}
}
}
@@ -412,27 +424,38 @@ nsresult nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
// callback data for WalkHistoryEntries
struct MOZ_STACK_CLASS CloneAndReplaceData {
CloneAndReplaceData(uint32_t aCloneID, nsISHEntry* aReplaceEntry,
bool aCloneChildren, nsISHEntry* aDestTreeParent)
bool aCloneChildren, nsISHEntry* aDestTreeParent,
uint64_t aOtherPid,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate)
: cloneID(aCloneID),
cloneChildren(aCloneChildren),
replaceEntry(aReplaceEntry),
destTreeParent(aDestTreeParent) {}
destTreeParent(aDestTreeParent),
otherPid(aOtherPid),
entriesToUpdate(aEntriesToUpdate) {}
uint32_t cloneID;
bool cloneChildren;
nsISHEntry* replaceEntry;
nsISHEntry* destTreeParent;
nsCOMPtr<nsISHEntry> resultEntry;
uint64_t otherPid;
// see comment for WalkHistoryEntriesFunc
nsTArray<EntriesAndBrowsingContextData>* entriesToUpdate;
};
nsresult nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
BrowsingContext* aOwnerBC,
int32_t aChildIndex, void* aData) {
MOZ_ASSERT(
XRE_IsParentProcess() || !StaticPrefs::fission_sessionHistoryInParent(),
"We should be in the parent process, or SH pref should be off");
nsCOMPtr<nsISHEntry> dest;
CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
uint32_t cloneID = data->cloneID;
nsISHEntry* replaceEntry = data->replaceEntry;
base::ProcessId otherPid = data->otherPid;
if (!aEntry) {
if (data->destTreeParent) {
@@ -457,14 +480,15 @@ nsresult nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
if (srcID != cloneID || data->cloneChildren) {
// Walk the children
CloneAndReplaceData childData(cloneID, replaceEntry, data->cloneChildren,
dest);
dest, otherPid, data->entriesToUpdate);
rv = nsSHistory::WalkHistoryEntries(aEntry, aOwnerBC, CloneAndReplaceChild,
&childData);
NS_ENSURE_SUCCESS(rv, rv);
}
if (srcID != cloneID && aOwnerBC) {
nsSHistory::HandleEntriesToSwapInDocShell(aOwnerBC, aEntry, dest);
nsSHistory::HandleEntriesToSwapInDocShell(aOwnerBC, aEntry, dest,
data->entriesToUpdate, otherPid);
}
if (data->destTreeParent) {
@@ -477,10 +501,13 @@ nsresult nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
// static
nsresult nsSHistory::CloneAndReplace(
nsISHEntry* aSrcEntry, BrowsingContext* aOwnerBC, uint32_t aCloneID,
nsISHEntry* aReplaceEntry, bool aCloneChildren, nsISHEntry** aDestEntry) {
nsISHEntry* aReplaceEntry, bool aCloneChildren, nsISHEntry** aDestEntry,
uint64_t aOtherPid,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate) {
NS_ENSURE_ARG_POINTER(aDestEntry);
NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr);
CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr,
aOtherPid, aEntriesToUpdate);
nsresult rv = CloneAndReplaceChild(aSrcEntry, aOwnerBC, 0, &data);
data.resultEntry.swap(*aDestEntry);
return rv;
@@ -490,19 +517,31 @@ NS_IMETHODIMP
nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
BrowsingContext* aBC, bool aCloneChildren) {
nsCOMPtr<nsISHEntry> child;
nsresult rv = AddChildSHEntryHelper(aCloneRef, aNewEntry, aBC, aCloneChildren,
getter_AddRefs(child));
int32_t entriesPurged;
nsresult rv = AddChildSHEntryHelper(
aCloneRef, aNewEntry, aBC, aCloneChildren,
0 /*unused, passed in by SHEntryParent::RecvAddChildSHEntryHelper
*/
,
nullptr /* array - this will be set in
SHistory::RecvAddChildSHEntryHelper if we are going over IPC,
else, it is not needed */
,
&entriesPurged /*used by SHEntryChild::AddToRootSessionHistory but
not here */
,
getter_AddRefs(child));
if (NS_SUCCEEDED(rv)) {
child->SetDocshellID(aBC->GetHistoryID());
}
return rv;
}
nsresult nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef,
nsISHEntry* aNewEntry,
BrowsingContext* aBC,
bool aCloneChildren,
nsISHEntry** aNextEntry) {
nsresult nsSHistory::AddChildSHEntryHelper(
nsISHEntry* aCloneRef, nsISHEntry* aNewEntry, BrowsingContext* aBC,
bool aCloneChildren, uint64_t aOtherPid,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
int32_t* aEntriesPurged, nsISHEntry** aNextEntry) {
/* You are currently in the rootDocShell.
* You will get here when a subframe has a new url
* to load and you have walked up the tree all the
@@ -522,9 +561,10 @@ nsresult nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef,
nsresult rv = NS_OK;
uint32_t cloneID = aCloneRef->GetID();
rv = nsSHistory::CloneAndReplace(currentHE, aBC, cloneID, aNewEntry,
aCloneChildren, aNextEntry);
aCloneChildren, aNextEntry, aOtherPid,
aEntriesToUpdate);
if (NS_SUCCEEDED(rv)) {
rv = AddEntry(*aNextEntry, true);
rv = AddEntry(*aNextEntry, true, aEntriesPurged);
}
return rv;
}
@@ -532,7 +572,15 @@ nsresult nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef,
nsresult nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry,
BrowsingContext* aBC,
int32_t aEntryIndex, void* aData) {
MOZ_ASSERT(
XRE_IsParentProcess() || !StaticPrefs::fission_sessionHistoryInParent(),
"We should be in the parent process, or 'SH in parent' pref should be "
"off");
SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
uint64_t otherPid = data->otherPid;
MOZ_ASSERT(data->entriesToUpdate || otherPid == 0,
"entriesToUpdate can't be null if we were called over IPC");
if (!aBC || aBC == data->ignoreBC) {
return NS_OK;
}
@@ -573,9 +621,11 @@ nsresult nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry,
destEntry = destTreeRoot;
}
nsSHistory::HandleEntriesToSwapInDocShell(aBC, aEntry, destEntry);
nsSHistory::HandleEntriesToSwapInDocShell(aBC, aEntry, destEntry,
data->entriesToUpdate, otherPid);
// Now handle the children of aEntry.
SwapEntriesData childData = {data->ignoreBC, destTreeRoot, destEntry};
SwapEntriesData childData = {data->ignoreBC, destTreeRoot, destEntry,
otherPid, data->entriesToUpdate};
return nsSHistory::WalkHistoryEntries(aEntry, aBC, SetChildHistoryEntry,
&childData);
}
@@ -583,15 +633,38 @@ nsresult nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry,
// static
void nsSHistory::HandleEntriesToSwapInDocShell(
mozilla::dom::BrowsingContext* aBC, nsISHEntry* aOldEntry,
nsISHEntry* aNewEntry) {
nsISHEntry* aNewEntry,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
uint64_t aOtherPid) {
bool shPref = StaticPrefs::fission_sessionHistoryInParent();
if (XRE_IsParentProcess()) {
aBC->Canonical()->SwapHistoryEntries(aOldEntry, aNewEntry);
}
if (aBC->IsInProcess() || !shPref) {
nsDocShell* docshell = static_cast<nsDocShell*>(aBC->GetDocShell());
if (docshell) {
docshell->SwapHistoryEntries(aOldEntry, aNewEntry);
}
} else if (aBC->Canonical()->IsOwnedByProcess(aOtherPid)) {
EntriesAndBrowsingContextData* toUpdate = aEntriesToUpdate->AppendElement();
toUpdate->oldEntry = aOldEntry;
toUpdate->newEntry = aNewEntry;
toUpdate->context = aBC;
} else {
// FIXME Bug 1633988: Need to update entries?
// XXX anny: this is currently not working! see bug 1581970
// This BC is owned by a process different from the caller,
// so we can send the entries right away to a different process
ContentParent* cp = aBC->Canonical()->GetContentParent();
auto convert = [](auto entry) {
return static_cast<CrossProcessSHEntry*>(
static_cast<LegacySHEntry*>(static_cast<nsSHEntry*>(entry)));
};
// We are performing a nested IPC call to a different process
Unused << cp->SendUpdateSHEntriesInDocShell(convert(aOldEntry),
convert(aNewEntry), aBC);
}
}
@@ -601,6 +674,29 @@ nsSHistory::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
uint32_t aLoadType, bool aShouldPersist,
Maybe<int32_t>* aPreviousEntryIndex,
Maybe<int32_t>* aLoadedEntryIndex) {
int32_t entriesPurged;
nsresult rv = AddToRootSessionHistory(
aCloneChildren, aOSHE, aBC, aEntry, aLoadType, aShouldPersist,
0 /* unused, passed in by SHEntryParent::RecvAddToRootSessionHistory */,
aPreviousEntryIndex, aLoadedEntryIndex,
nullptr /* array - this will be set in RecvAddToRootSessionHistory if we
are going over IPC, else, it is not needed */
,
&entriesPurged
/* used by SHEntryChild::AddToRootSessionHistory but not here */);
if (NS_SUCCEEDED(rv)) {
aEntry->SetDocshellID(aBC->GetHistoryID());
}
return rv;
}
nsresult nsSHistory::AddToRootSessionHistory(
bool aCloneChildren, nsISHEntry* aOSHE, BrowsingContext* aBC,
nsISHEntry* aEntry, uint32_t aLoadType, bool aShouldPersist,
uint64_t aOtherPid, Maybe<int32_t>* previousEntryIndex,
Maybe<int32_t>* aLoadedEntryIndex,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
int32_t* aEntriesPurged) {
nsresult rv = NS_OK;
// If we need to clone our children onto the new session
@@ -609,7 +705,8 @@ nsSHistory::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
uint32_t cloneID = aOSHE->GetID();
nsCOMPtr<nsISHEntry> newEntry;
nsSHistory::CloneAndReplace(aOSHE, aBC, cloneID, aEntry, true,
getter_AddRefs(newEntry));
getter_AddRefs(newEntry), aOtherPid,
aEntriesToUpdate);
NS_ASSERTION(aEntry == newEntry,
"The new session history should be in the new entry");
}
@@ -635,15 +732,12 @@ nsSHistory::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
}
if (addToSHistory) {
// Add to session history
*aPreviousEntryIndex = Some(mIndex);
rv = AddEntry(aEntry, aShouldPersist);
*previousEntryIndex = Some(mIndex);
rv = AddEntry(aEntry, aShouldPersist, aEntriesPurged);
*aLoadedEntryIndex = Some(mIndex);
MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
("Previous index: %d, Loaded index: %d",
aPreviousEntryIndex->value(), aLoadedEntryIndex->value()));
}
if (NS_SUCCEEDED(rv)) {
aEntry->SetDocshellID(aBC->GetHistoryID());
previousEntryIndex->value(), aLoadedEntryIndex->value()));
}
return rv;
}
@@ -653,7 +747,14 @@ nsSHistory::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
*/
NS_IMETHODIMP
nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist) {
int32_t dummy = 0;
return AddEntry(aSHEntry, aPersist, &dummy);
}
nsresult nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist,
int32_t* aEntriesPurged) {
NS_ENSURE_ARG(aSHEntry);
*aEntriesPurged = 0;
nsCOMPtr<nsISHistory> shistoryOfEntry = aSHEntry->GetShistory();
if (shistoryOfEntry != this) {
@@ -697,12 +798,16 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist) {
// Purge History list if it is too long
if (gHistoryMaxSize >= 0 && Length() > gHistoryMaxSize) {
PurgeHistory(Length() - gHistoryMaxSize);
*aEntriesPurged = Length() - gHistoryMaxSize;
PurgeHistory(*aEntriesPurged);
}
return NS_OK;
}
NS_IMETHODIMP_(void)
nsSHistory::ClearRootBrowsingContext() { mRootBC = nullptr; }
/* Get size of the history list */
NS_IMETHODIMP
nsSHistory::GetCount(int32_t* aResult) {
@@ -928,9 +1033,8 @@ nsSHistory::EvictAllContentViewers() {
return NS_OK;
}
/* static */
void nsSHistory::LoadURIs(nsTArray<LoadEntryResult>& aLoadResults) {
for (LoadEntryResult& loadEntry : aLoadResults) {
static void LoadURIs(nsTArray<nsSHistory::LoadEntryResult>& aLoadResults) {
for (nsSHistory::LoadEntryResult& loadEntry : aLoadResults) {
loadEntry.mBrowsingContext->LoadURI(loadEntry.mLoadState, false);
}
}
@@ -1692,7 +1796,8 @@ nsresult nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry,
NS_IMETHODIMP
nsSHistory::CreateEntry(nsISHEntry** aEntry) {
nsCOMPtr<nsISHEntry> entry = new nsSHEntry(this);
nsCOMPtr<nsISHEntry> entry =
new nsLegacySHEntry(this, SHEntryChildShared::CreateSharedID());
entry.forget(aEntry);
return NS_OK;
}

View File

@@ -64,9 +64,13 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
nsISHEntry* destTreeRoot; // constant; the root of the dest tree
nsISHEntry* destTreeParent; // constant; the node under destTreeRoot
// whose children will correspond to aEntry
uint64_t otherPid; // constant; pid of the process which indirectly called
// SetChildHistoryEntry
// see comment for WalkHistoryEntriesFunc
nsTArray<EntriesAndBrowsingContextData>* entriesToUpdate;
};
explicit nsSHistory(mozilla::dom::BrowsingContext* aRootBC);
nsSHistory(mozilla::dom::BrowsingContext* aRootBC, const nsID& aDocShellID);
NS_DECL_ISUPPORTS
NS_DECL_NSISHISTORY
@@ -104,10 +108,11 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
// have that pointer updated to point to the cloned history entry.
// If aCloneChildren is true then the children of the entry with id
// |aCloneID| will be cloned into |aReplaceEntry|.
static nsresult CloneAndReplace(nsISHEntry* aSrcEntry,
mozilla::dom::BrowsingContext* aOwnerBC,
uint32_t aCloneID, nsISHEntry* aReplaceEntry,
bool aCloneChildren, nsISHEntry** aDestEntry);
static nsresult CloneAndReplace(
nsISHEntry* aSrcEntry, mozilla::dom::BrowsingContext* aOwnerBC,
uint32_t aCloneID, nsISHEntry* aReplaceEntry, bool aCloneChildren,
nsISHEntry** aDestEntry, uint64_t aOtherPid,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate);
// Child-walking callback for CloneAndReplace
static nsresult CloneAndReplaceChild(nsISHEntry* aEntry,
@@ -127,12 +132,26 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
WalkHistoryEntriesFunc aCallback,
void* aData);
nsresult AddChildSHEntryHelper(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
mozilla::dom::BrowsingContext* aBC,
bool aCloneChildren, nsISHEntry** aNextEntry);
nsresult AddToRootSessionHistory(
bool aCloneChildren, nsISHEntry* aOSHE,
mozilla::dom::BrowsingContext* aBC, nsISHEntry* aEntry,
uint32_t aLoadType, bool aShouldPersist, uint64_t aOtherPid,
mozilla::Maybe<int32_t>* aPreviousEntryIndex,
mozilla::Maybe<int32_t>* aLoadedEntryIndex,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
int32_t* aEntriesPurged);
nsresult AddChildSHEntryHelper(
nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
mozilla::dom::BrowsingContext* aBC, bool aCloneChildren,
uint64_t aOtherPid,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
int32_t* aEntriesPurged, nsISHEntry** aNextEntry);
nsTArray<nsCOMPtr<nsISHEntry>>& Entries() { return mEntries; }
nsresult AddEntry(nsISHEntry* aSHEntry, bool aPersist,
int32_t* aEntriesPurged);
void RemoveEntries(nsTArray<nsID>& aIDs, int32_t aStartIndex,
bool* aDidRemove);
@@ -148,8 +167,6 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
RefPtr<nsDocShellLoadState> mLoadState;
};
static void LoadURIs(nsTArray<LoadEntryResult>& aLoadResults);
// If this doesn't return an error then either aLoadResult is set to nothing,
// in which case the caller should ignore the load, or it returns a valid
// LoadEntryResult in aLoadResult which the caller should use to do the load.
@@ -220,9 +237,11 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
// process. Otherwise, if the browsing context is in a different process, we
// do a nested IPC call to that process to update the docshell in that
// process.
static void HandleEntriesToSwapInDocShell(mozilla::dom::BrowsingContext* aBC,
nsISHEntry* aOldEntry,
nsISHEntry* aNewEntry);
static void HandleEntriesToSwapInDocShell(
mozilla::dom::BrowsingContext* aBC, nsISHEntry* aOldEntry,
nsISHEntry* aNewEntry,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
uint64_t aOtherPid);
protected:
// Length of mEntries.

View File

@@ -2132,7 +2132,8 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
if (mIsTopLevelContent && mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disablehistory)) {
// XXX(nika): Set this up more explicitly?
mPendingBrowsingContext->InitSessionHistory();
nsresult rv = docShell->InitSessionHistory();
NS_ENSURE_SUCCESS(rv, rv);
}
// Apply sandbox flags even if our owner is not an iframe, as this copies

View File

@@ -26,7 +26,6 @@
#include "mozilla/dom/RemoteDragStartData.h"
#include "mozilla/dom/RemoteWebProgress.h"
#include "mozilla/dom/RemoteWebProgressRequest.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/SessionStoreUtilsBinding.h"
#include "mozilla/dom/UserActivation.h"
@@ -74,7 +73,6 @@
#include "nsIXPConnect.h"
#include "nsIXULBrowserWindow.h"
#include "nsIAppWindow.h"
#include "nsSHistory.h"
#include "nsViewManager.h"
#include "nsVariant.h"
#include "nsIWidget.h"

View File

@@ -61,6 +61,8 @@
#include "mozilla/dom/RemoteWorkerService.h"
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/SHEntryChild.h"
#include "mozilla/dom/SHistoryChild.h"
#include "mozilla/dom/URLClassifierChild.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WorkerDebugger.h"
@@ -3232,6 +3234,42 @@ bool ContentChild::DeallocPSessionStorageObserverChild(
return true;
}
PSHEntryChild* ContentChild::AllocPSHEntryChild(PSHistoryChild* aSHistory,
uint64_t aSharedID) {
// We take a strong reference for the IPC layer. The Release implementation
// for SHEntryChild will ask the IPC layer to release it (through
// DeallocPSHEntryChild) if that is the only remaining reference.
RefPtr<SHEntryChild> child;
child = new SHEntryChild(static_cast<SHistoryChild*>(aSHistory), aSharedID);
return child.forget().take();
}
void ContentChild::DeallocPSHEntryChild(PSHEntryChild* aActor) {
// Release the strong reference we took in AllocPSHEntryChild for the IPC
// layer.
RefPtr<SHEntryChild> child(dont_AddRef(static_cast<SHEntryChild*>(aActor)));
}
PSHistoryChild* ContentChild::AllocPSHistoryChild(
const MaybeDiscarded<BrowsingContext>& aContext) {
// FIXME: How should SHistoryChild construction deal with a null or discarded
// BrowsingContext? This will likely kill the current child process.
if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
return nullptr;
}
// We take a strong reference for the IPC layer. The Release implementation
// for SHistoryChild will ask the IPC layer to release it (through
// DeallocPSHistoryChild) if that is the only remaining reference.
return do_AddRef(new SHistoryChild(aContext.get())).take();
}
void ContentChild::DeallocPSHistoryChild(PSHistoryChild* aActor) {
// Release the strong reference we took in AllocPSHistoryChild for the IPC
// layer.
RefPtr<SHistoryChild> child(dont_AddRef(static_cast<SHistoryChild*>(aActor)));
}
mozilla::ipc::IPCResult ContentChild::RecvActivate(PBrowserChild* aTab) {
BrowserChild* tab = static_cast<BrowserChild*>(aTab);
return tab->RecvActivate();
@@ -3450,10 +3488,6 @@ mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
loadState->SetLoadType(aArgs.loadStateLoadType());
}
if (aArgs.sessionHistoryInfo().isSome()) {
loadState->SetSessionHistoryInfo(aArgs.sessionHistoryInfo().ref());
}
RefPtr<ChildProcessChannelListener> processListener =
ChildProcessChannelListener::GetSingleton();
// The listener will call completeRedirectSetup or asyncOpen on the channel.
@@ -3488,6 +3522,18 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateMediaControlKeysEvent(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvDestroySHEntrySharedState(
const uint64_t& aID) {
SHEntryChildShared::Remove(aID);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvEvictContentViewers(
nsTArray<uint64_t>&& aToEvictSharedStateIDs) {
SHEntryChildShared::EvictContentViewers(std::move(aToEvictSharedStateIDs));
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvSessionStorageData(
const uint64_t aTopContextId, const nsACString& aOriginAttrs,
const nsACString& aOriginKey, const nsTArray<KeyValuePair>& aDefaultData,
@@ -3502,6 +3548,18 @@ mozilla::ipc::IPCResult ContentChild::RecvSessionStorageData(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvUpdateSHEntriesInDocShell(
CrossProcessSHEntry* aOldEntry, CrossProcessSHEntry* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aContext) {
MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
nsDocShell* docshell =
static_cast<nsDocShell*>(aContext.GetMaybeDiscarded()->GetDocShell());
if (docshell) {
docshell->SwapHistoryEntries(aOldEntry->ToSHEntryChild(),
aNewEntry->ToSHEntryChild());
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
const MaybeDiscarded<BrowsingContext>& aContext,
@@ -4128,14 +4186,6 @@ mozilla::ipc::IPCResult ContentChild::RecvDisplayLoadError(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvHistoryCommitLength(
const MaybeDiscarded<BrowsingContext>& aContext, uint32_t aLength) {
if (!aContext.IsNullOrDiscarded()) {
aContext.get()->GetChildSessionHistory()->SetLength(aLength);
}
return IPC_OK();
}
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
mozilla::ipc::IPCResult ContentChild::RecvInitSandboxTesting(
Endpoint<PSandboxTestingChild>&& aEndpoint) {

View File

@@ -600,6 +600,16 @@ class ContentChild final : public PContentChild,
bool DeallocPSessionStorageObserverChild(
PSessionStorageObserverChild* aActor);
PSHEntryChild* AllocPSHEntryChild(PSHistoryChild* aSHistory,
uint64_t aSharedID);
void DeallocPSHEntryChild(PSHEntryChild*);
PSHistoryChild* AllocPSHistoryChild(
const MaybeDiscarded<BrowsingContext>& aContext);
void DeallocPSHistoryChild(PSHistoryChild* aActor);
nsTArray<LookAndFeelInt>& LookAndFeelCache() { return mLookAndFeelCache; }
/**
@@ -648,11 +658,20 @@ class ContentChild final : public PContentChild,
return mBrowsingContextFieldEpoch;
}
mozilla::ipc::IPCResult RecvDestroySHEntrySharedState(const uint64_t& aID);
mozilla::ipc::IPCResult RecvEvictContentViewers(
nsTArray<uint64_t>&& aToEvictSharedStateIDs);
mozilla::ipc::IPCResult RecvSessionStorageData(
uint64_t aTopContextId, const nsACString& aOriginAttrs,
const nsACString& aOriginKey, const nsTArray<KeyValuePair>& aDefaultData,
const nsTArray<KeyValuePair>& aSessionData);
mozilla::ipc::IPCResult RecvUpdateSHEntriesInDocShell(
CrossProcessSHEntry* aOldEntry, CrossProcessSHEntry* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aContext);
mozilla::ipc::IPCResult RecvOnAllowAccessFor(
const MaybeDiscarded<BrowsingContext>& aContext,
const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
@@ -790,10 +809,7 @@ class ContentChild final : public PContentChild,
JSActor::Type GetSide() override { return JSActor::Type::Child; }
mozilla::ipc::IPCResult RecvHistoryCommitLength(
const MaybeDiscarded<BrowsingContext>& aContext, uint32_t aLength);
private:
private:
#ifdef NIGHTLY_BUILD
virtual PContentChild::Result OnMessageReceived(const Message& aMsg) override;
#else

View File

@@ -108,6 +108,8 @@
#include "mozilla/dom/PresentationParent.h"
#include "mozilla/dom/ProcessMessageManager.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/dom/SHEntryParent.h"
#include "mozilla/dom/SHistoryParent.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/dom/ServiceWorkerUtils.h"
@@ -5646,6 +5648,25 @@ bool ContentParent::DeallocPSessionStorageObserverParent(
return mozilla::dom::DeallocPSessionStorageObserverParent(aActor);
}
PSHEntryParent* ContentParent::AllocPSHEntryParent(PSHistoryParent* aSHistory,
uint64_t aSharedID) {
return SHistoryParent::CreateEntry(this, aSHistory, aSharedID);
}
void ContentParent::DeallocPSHEntryParent(PSHEntryParent* aEntry) {
delete static_cast<SHEntryParent*>(aEntry);
}
PSHistoryParent* ContentParent::AllocPSHistoryParent(
const MaybeDiscarded<BrowsingContext>& aContext) {
MOZ_ASSERT(!aContext.IsNull());
return new SHistoryParent(aContext.GetMaybeDiscarded()->Canonical());
}
void ContentParent::DeallocPSHistoryParent(PSHistoryParent* aActor) {
delete static_cast<SHistoryParent*>(aActor);
}
mozilla::ipc::IPCResult ContentParent::RecvMaybeReloadPlugins() {
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
pluginHost->ReloadPlugins();
@@ -5805,6 +5826,35 @@ mozilla::ipc::IPCResult ContentParent::RecvNotifyPictureInPictureModeChanged(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvUpdateSHEntriesInBC(
PSHEntryParent* aNewLSHE, PSHEntryParent* aNewOSHE,
const MaybeDiscarded<BrowsingContext>& aMaybeContext) {
if (aMaybeContext.IsNullOrDiscarded()) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to update a browsing context that does not "
"exist or has been discarded"));
return IPC_OK();
}
auto aContext = aMaybeContext.get()->Canonical();
MOZ_ASSERT(aContext);
if (!aContext->IsOwnedByProcess(ChildID())) {
// We are trying to update a child BrowsingContext in another child
// process. This is illegal since the owner of the BrowsingContext
// is the proccess with the in-process docshell, which is tracked
// by OwnerProcessId.
MOZ_DIAGNOSTIC_ASSERT(
false,
"Trying to update a child BrowsingContext in another child process");
return IPC_OK();
}
SHEntryParent* newLSHEparent = static_cast<SHEntryParent*>(aNewLSHE);
SHEntryParent* newOSHEparent = static_cast<SHEntryParent*>(aNewOSHE);
nsISHEntry* lshe = newLSHEparent ? newLSHEparent->mEntry.get() : nullptr;
nsISHEntry* oshe = newOSHEparent ? newOSHEparent->mEntry.get() : nullptr;
aContext->UpdateSHEntries(lshe, oshe);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvAbortOtherOrientationPendingPromises(
const MaybeDiscarded<BrowsingContext>& aContext) {
if (aContext.IsNullOrDiscarded()) {
@@ -6352,33 +6402,6 @@ mozilla::ipc::IPCResult ContentParent::RecvReportServiceWorkerShutdownProgress(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvHistoryCommit(
const MaybeDiscarded<BrowsingContext>& aContext,
uint64_t aSessionHistoryEntryID) {
if (!aContext.IsDiscarded()) {
aContext.get_canonical()->SessionHistoryCommit(aSessionHistoryEntryID);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvHistoryGo(
const MaybeDiscarded<BrowsingContext>& aContext, int32_t aOffset,
HistoryGoResolver&& aResolveRequestedIndex) {
if (!aContext.IsDiscarded()) {
nsSHistory* shistory =
static_cast<nsSHistory*>(aContext.get_canonical()->GetSessionHistory());
nsTArray<nsSHistory::LoadEntryResult> loadResults;
nsresult rv = shistory->GotoIndex(aOffset, loadResults);
if (NS_FAILED(rv)) {
return IPC_FAIL(this, "GotoIndex failed");
}
aResolveRequestedIndex(shistory->GetRequestedIndex());
shistory->LoadURIs(loadResults);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvCommitWindowContextTransaction(
const MaybeDiscarded<WindowContext>& aContext,
WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {

View File

@@ -584,6 +584,16 @@ class ContentParent final
bool DeallocPSessionStorageObserverParent(
PSessionStorageObserverParent* aActor);
PSHEntryParent* AllocPSHEntryParent(PSHistoryParent* aSHistory,
uint64_t aSharedID);
void DeallocPSHEntryParent(PSHEntryParent*);
PSHistoryParent* AllocPSHistoryParent(
const MaybeDiscarded<BrowsingContext>& aContext);
void DeallocPSHistoryParent(PSHistoryParent* aActor);
bool DeallocPURLClassifierLocalParent(PURLClassifierLocalParent* aActor);
bool DeallocPURLClassifierParent(PURLClassifierParent* aActor);
@@ -1274,6 +1284,10 @@ class ContentParent final
uint32_t aShutdownStateId,
ServiceWorkerShutdownState::Progress aProgress);
mozilla::ipc::IPCResult RecvUpdateSHEntriesInBC(
PSHEntryParent* aNewLSHE, PSHEntryParent* aNewOSHE,
const MaybeDiscarded<BrowsingContext>& aMaybeContext);
mozilla::ipc::IPCResult RecvRawMessage(const JSActorMessageMeta& aMeta,
const ClonedMessageData& aData,
const ClonedMessageData& aStack);
@@ -1281,14 +1295,6 @@ class ContentParent final
mozilla::ipc::IPCResult RecvAbortOtherOrientationPendingPromises(
const MaybeDiscarded<BrowsingContext>& aContext);
mozilla::ipc::IPCResult RecvHistoryCommit(
const MaybeDiscarded<BrowsingContext>& aContext,
uint64_t aSessionHistoryEntryID);
mozilla::ipc::IPCResult RecvHistoryGo(
const MaybeDiscarded<BrowsingContext>& aContext, int32_t aOffset,
HistoryGoResolver&& aResolveRequestedIndex);
// Notify the ContentChild to enable the input event prioritization when
// initializing.
void MaybeEnableRemoteInputEventQueue();

View File

@@ -13,6 +13,7 @@ include IPCBlob;
include IPCStream;
include protocol PIPCBlobInputStream;
include ProtocolTypes;
include protocol PSHEntry;
using struct mozilla::void_t
from "ipc/IPCMessageUtils.h";
@@ -40,7 +41,9 @@ using refcounted class nsIInputStream from "mozilla/ipc/IPCStreamUtils.h";
using refcounted class nsIReferrerInfo from "mozilla/dom/ReferrerInfoUtils.h";
using refcounted class nsIVariant from "mozilla/dom/PropertyBagUtils.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using refcounted class nsISHEntry from "nsISHEntry.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
using refcounted class mozilla::dom::CrossProcessSHEntry from "mozilla/dom/MaybeNewPSHEntry.h";
using mozilla::dom::WindowContextInitializer from "mozilla/dom/WindowContext.h";
namespace mozilla {
@@ -275,6 +278,10 @@ struct DocShellLoadStateInit
nsIInputStream HeadersStream;
nsString SrcdocData; // useless without sourcedocshell
// This might be missing if serialization of session history entries is
// not supported. This is the case when 'fission.sessionHistoryInParent'
// pref is off.
CrossProcessSHEntry SHEntry;
// Fields missing due to lack of need or serialization
// nsCOMPtr<nsIDocShell> mSourceDocShell;
@@ -379,5 +386,11 @@ struct OwnerShowInfo {
nsSizeMode sizeMode;
};
struct SwapEntriesDocshellData {
CrossProcessSHEntry oldEntry;
CrossProcessSHEntry newEntry;
MaybeDiscardedBrowsingContext context;
};
} // namespace dom
} // namespace mozilla

View File

@@ -46,6 +46,8 @@ include protocol PRemoteDecoderManager;
include protocol PProfiler;
include protocol PScriptCache;
include protocol PSessionStorageObserver;
include protocol PSHEntry;
include protocol PSHistory;
include protocol PBenchmarkStorage;
include DOMTypes;
include JavaScriptTypes;
@@ -120,6 +122,7 @@ using mozilla::dom::MaybeMediaMetadataBase from "mozilla/dom/MediaSessionIPCUtil
using mozilla::dom::MediaSessionPlaybackState from "mozilla/dom/MediaSessionBinding.h";
using refcounted class nsDocShellLoadState from "nsDocShellLoadState.h";
using mozilla::dom::ServiceWorkerShutdownState::Progress from "mozilla/dom/ServiceWorkerShutdownState.h";
using refcounted class mozilla::dom::CrossProcessSHEntry from "mozilla/dom/MaybeNewPSHEntry.h";
using mozilla::ContentBlockingNotifier::StorageAccessGrantedReason from "mozilla/ContentBlockingNotifier.h";
using mozilla::ContentBlockingNotifier::BlockingDecision from "mozilla/ContentBlockingNotifier.h";
using mozilla::ContentBlocking::StorageAccessPromptChoices from "mozilla/ContentBlocking.h";
@@ -402,6 +405,8 @@ nested(upto inside_cpow) sync protocol PContent
manages PScriptCache;
manages PLoginReputation;
manages PSessionStorageObserver;
manages PSHEntry;
manages PSHistory;
manages PBenchmarkStorage;
// Depending on exactly how the new browser is being created, it might be
@@ -863,6 +868,10 @@ child:
async InitSandboxTesting(Endpoint<PSandboxTestingChild> aEndpoint);
#endif
async DestroySHEntrySharedState(uint64_t aID);
async EvictContentViewers(uint64_t[] aToEvictSharedStateIDs);
async LoadURI(MaybeDiscardedBrowsingContext aContext, nsDocShellLoadState aLoadState, bool aSetNavigating)
returns (bool aSuccess);
@@ -870,6 +879,11 @@ child:
async DisplayLoadError(MaybeDiscardedBrowsingContext aContext, nsString aURI);
// Tell aContext's docshell to update its mOSHE and mLSHE entries
async UpdateSHEntriesInDocShell(CrossProcessSHEntry aOldEntry,
CrossProcessSHEntry aNewEntry,
MaybeDiscardedBrowsingContext aContext);
async OnAllowAccessFor(MaybeDiscardedBrowsingContext aParentContext,
nsCString aTrackingOrigin,
uint32_t aCookieBehavior,
@@ -885,9 +899,6 @@ child:
*/
async AbortOrientationPendingPromises(MaybeDiscardedBrowsingContext aContext);
async HistoryCommitLength(MaybeDiscardedBrowsingContext aContext,
uint32_t aLength);
parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
@@ -961,6 +972,11 @@ parent:
async PSessionStorageObserver();
async PSHistory(MaybeDiscardedBrowsingContext aContext);
// Clone using shared id.
sync PSHEntry(nullable PSHistory shistory, uint64_t sharedID);
async PBenchmarkStorage();
// Services remoting
@@ -1574,18 +1590,19 @@ parent:
async ReportServiceWorkerShutdownProgress(uint32_t aShutdownStateId,
Progress aProgress);
/**
* Whenever docshell updates its SH entries, we need to update them in
* the corresponding BrowsingContext
*/
async UpdateSHEntriesInBC(nullable PSHEntry aNewLSHE, nullable
PSHEntry aNewOSHE, MaybeDiscardedBrowsingContext aContext);
/**
* Whenever a document is updating the OrientationLock, we need to
* reject the orientationPendingPromises in other processes.
*/
async AbortOtherOrientationPendingPromises(MaybeDiscardedBrowsingContext aContext);
async HistoryCommit(MaybeDiscardedBrowsingContext aContext,
uint64_t aSessionHistoryEntryID);
async HistoryGo(MaybeDiscardedBrowsingContext aContext,
int32_t aOffset) returns(int32_t requestedIndex);
both:
async ScriptError(nsString message, nsString sourceName, nsString sourceLine,
uint32_t lineNumber, uint32_t colNumber, uint32_t flags,

View File

@@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PSHEntry;
include protocol PWebBrowserPersistResources;
include protocol PWebBrowserPersistSerialize;
include protocol PFileDescriptorSet;
@@ -17,9 +18,8 @@ using refcounted class nsIReferrerInfo from "mozilla/dom/ReferrerInfoUtils.h";
namespace mozilla {
// FIXME When session history lives in the parent we need to figure out how to
// point the parent process at the right entry to get the cache key.
union SessionHistoryEntryOrCacheKey {
nullable PSHEntry;
uint32_t;
};

View File

@@ -13,6 +13,7 @@
#include "WebBrowserPersistLocalDocument.h"
#include "WebBrowserPersistResourcesChild.h"
#include "WebBrowserPersistSerializeChild.h"
#include "SHEntryChild.h"
#include "mozilla/StaticPrefs_fission.h"
namespace mozilla {
@@ -57,7 +58,13 @@ void WebBrowserPersistDocumentChild::Start(
ENSURE(aDocument->GetTitle(attrs.title()));
ENSURE(aDocument->GetContentDisposition(attrs.contentDisposition()));
if (!StaticPrefs::fission_sessionHistoryInParent()) {
// shEntryChild needs to remain in scope until after the SendAttributes call,
// to keep the actor alive.
RefPtr<dom::SHEntryChild> shEntryChild;
if (StaticPrefs::fission_sessionHistoryInParent()) {
shEntryChild = aDocument->GetHistory().downcast<dom::SHEntryChild>();
attrs.sessionHistoryEntryOrCacheKey() = shEntryChild;
} else {
attrs.sessionHistoryEntryOrCacheKey() = aDocument->GetCacheKey();
}

View File

@@ -8,6 +8,7 @@
#include "WebBrowserPersistDocumentParent.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "SHEntryParent.h"
#include "mozilla/Unused.h"
#include "mozilla/ipc/BackgroundUtils.h"
@@ -28,6 +29,12 @@ WebBrowserPersistRemoteDocument ::WebBrowserPersistRemoteDocument(
} else {
NS_WARNING("Failed to obtain principal!");
}
if (mAttrs.sessionHistoryEntryOrCacheKey().type() ==
SessionHistoryEntryOrCacheKey::TPSHEntryParent) {
mSHEntry = static_cast<dom::SHEntryParent*>(
mAttrs.sessionHistoryEntryOrCacheKey().get_PSHEntryParent())
->GetSHEntry();
}
}
WebBrowserPersistRemoteDocument::~WebBrowserPersistRemoteDocument() {
@@ -95,7 +102,11 @@ NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetCacheKey(uint32_t* aCacheKey) {
*aCacheKey = 0;
if (mAttrs.sessionHistoryEntryOrCacheKey().type() ==
SessionHistoryEntryOrCacheKey::Tuint32_t) {
SessionHistoryEntryOrCacheKey::TPSHEntryParent) {
if (mSHEntry) {
*aCacheKey = mSHEntry->GetCacheKey();
}
} else {
*aCacheKey = mAttrs.sessionHistoryEntryOrCacheKey();
}
return NS_OK;

View File

@@ -807,6 +807,139 @@ description = Legacy NPAPI IPC
description = Legacy NPAPI IPC
[PPluginStream::__delete__]
description = Legacy NPAPI IPC
# Session history
[PSHistory::GetCount]
description = Standing up Fission
[PSHistory::GetIndex]
description = Standing up Fission
[PSHistory::SetIndex]
description = Standing up Fission
[PSHistory::GetRequestedIndex]
description = Standing up Fission
[PSHistory::GetEntryAtIndex]
description = Standing up Fission
[PSHistory::PurgeHistory]
description = Standing up Fission
[PSHistory::ReloadCurrentEntry]
description = Standing up Fission
[PSHistory::GotoIndex]
description = Standing up Fission
[PSHistory::GetIndexOfEntry]
description = Standing up Fission
[PSHistory::AddEntry]
description = Standing up Fission
[PSHistory::ReplaceEntry]
description = Standing up Fission
[PSHistory::NotifyOnHistoryReload]
description = Standing up Fission
[PSHistory::AddToRootSessionHistory]
description = Standing up Fission
[PSHistory::AddChildSHEntryHelper]
description = Standing up Fission
[PSHistory::RemoveEntries]
description = Standing up Fission
[PSHistory::Reload]
description = Standing up Fission
[PSHistory::GetAllEntries]
description = Standing up Fission
[PSHistory::FindEntryForBFCache]
description = Standing up Fission
[PContent::PSHEntry]
description = Standing up Fission
[PSHEntry::Clone]
description = Standing up Fission
[PSHEntry::GetURI]
description = Standing up Fission
[PSHEntry::GetOriginalURI]
description = Standing up Fission
[PSHEntry::GetResultPrincipalURI]
description = Standing up Fission
[PSHEntry::GetLoadReplace]
description = Standing up Fission
[PSHEntry::GetTitle]
description = Standing up Fission
[PSHEntry::GetIsSubFrame]
description = Standing up Fission
[PSHEntry::GetReferrerInfo]
description = Standing up Fission
[PSHEntry::GetSticky]
description = Standing up Fission
[PSHEntry::GetPostData]
description = Standing up Fission
[PSHEntry::GetParent]
description = Standing up Fission
[PSHEntry::GetLoadType]
description = Standing up Fission
[PSHEntry::GetID]
description = Standing up Fission
[PSHEntry::GetCacheKey]
description = Standing up Fission
[PSHEntry::GetExpirationStatus]
description = Standing up Fission
[PSHEntry::GetContentType]
description = Standing up Fission
[PSHEntry::GetURIWasModified]
description = Standing up Fission
[PSHEntry::GetTriggeringPrincipal]
description = Standing up Fission
[PSHEntry::GetPrincipalToInherit]
description = Standing up Fission
[PSHEntry::GetStoragePrincipalToInherit]
description = Standing up Fission
[PSHEntry::GetCsp]
description = Standing up Fission
[PSHEntry::GetStateData]
description = Standing up Fission
[PSHEntry::GetDocshellID]
description = Standing up Fission
[PSHEntry::GetIsSrcdocEntry]
description = Standing up Fission
[PSHEntry::GetSrcdocData]
description = Standing up Fission
[PSHEntry::GetBaseURI]
description = Standing up Fission
[PSHEntry::GetScrollRestorationIsManual]
description = Standing up Fission
[PSHEntry::GetLoadedInThisProcess]
description = Standing up Fission
[PSHEntry::GetLastTouched]
description = Standing up Fission
[PSHEntry::GetChildCount]
description = Standing up Fission
[PSHEntry::GetPersist]
description = Standing up Fission
[PSHEntry::GetScrollPosition]
description = Standing up Fission
[PSHEntry::GetViewerBounds]
description = Standing up Fission
[PSHEntry::HasDetachedEditor]
description = Standing up Fission
[PSHEntry::IsDynamicallyAdded]
description = Standing up Fission
[PSHEntry::HasDynamicallyAddedChild]
description = Standing up Fission
[PSHEntry::AdoptBFCacheEntry]
description = Standing up Fission
[PSHEntry::SharesDocumentWith]
description = Standing up Fission
[PSHEntry::AddChild]
description = Standing up Fission
[PSHEntry::RemoveChild]
description = Standing up Fission
[PSHEntry::GetChildAt]
description = Standing up Fission
[PSHEntry::GetChildSHEntryIfHasNoDynamicallyAddedChild]
description = Standing up Fission
[PSHEntry::ReplaceChild]
description = Standing up Fission
[PSHEntry::__delete__]
description = Standing up Fission
[PSHEntry::CreateLoadInfo]
description = Standing up Fission
[PSHEntry::SyncTreesForSubframeNavigation]
description = Standing up Fission
# The rest
[PHeapSnapshotTempFileHelper::OpenHeapSnapshotTempFile]
description = legacy sync IPC - please add detailed description

View File

@@ -11,7 +11,6 @@
#include "mozilla/ContentBlockingAllowList.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/MozPromiseInlines.h" // For MozPromise::FromDomPromise
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/StaticPrefs_security.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientChannelHelper.h"
@@ -20,7 +19,6 @@
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/net/CookieJarSettings.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/net/HttpChannelParent.h"
#include "mozilla/net/RedirectChannelRegistrar.h"
#include "mozilla/net/UrlClassifierCommon.h"
@@ -532,11 +530,6 @@ bool DocumentLoadListener::Open(
mTiming = aTiming;
mSrcdocData = aLoadState->SrcdocData();
mBaseURI = aLoadState->BaseURI();
if (StaticPrefs::fission_sessionHistoryInParent() &&
browsingContext->GetSessionHistory()) {
mSessionHistoryInfo =
browsingContext->CreateSessionHistoryEntryForLoad(aLoadState, mChannel);
}
if (auto* ctx = GetBrowsingContext()) {
ctx->StartDocumentLoad(this);
@@ -1160,11 +1153,6 @@ void DocumentLoadListener::SerializeRedirectData(
aArgs.baseUri() = mBaseURI;
aArgs.loadStateLoadFlags() = mLoadStateLoadFlags;
aArgs.loadStateLoadType() = mLoadStateLoadType;
if (mSessionHistoryInfo) {
aArgs.sessionHistoryInfo().emplace(
mSessionHistoryInfo->mId, MakeUnique<mozilla::dom::SessionHistoryInfo>(
*mSessionHistoryInfo->mInfo));
}
}
bool DocumentLoadListener::MaybeTriggerProcessSwitch() {

View File

@@ -14,7 +14,6 @@
#include "mozilla/net/PDocumentChannelParent.h"
#include "mozilla/net/ParentChannelListener.h"
#include "mozilla/net/ADocumentChannelBridge.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "nsDOMNavigationTiming.h"
#include "nsIInterfaceRequestor.h"
#include "nsIParentChannel.h"
@@ -400,8 +399,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
nsString mSrcdocData;
nsCOMPtr<nsIURI> mBaseURI;
mozilla::UniquePtr<mozilla::dom::SessionHistoryInfoAndId> mSessionHistoryInfo;
// Flags from nsDocShellLoadState::LoadFlags/Type that we want to make
// available to the new docshell if we switch processes.
uint32_t mLoadStateLoadFlags = 0;

View File

@@ -23,7 +23,6 @@ using class mozilla::net::nsHttpResponseHead from "nsHttpResponseHead.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using refcounted class nsIPropertyBag2 from "mozilla/dom/PropertyBagUtils.h";
using refcounted class nsDOMNavigationTiming from "nsDOMNavigationTiming.h";
using moveonly mozilla::dom::SessionHistoryInfoAndId from "mozilla/dom/SessionHistoryEntry.h";
namespace mozilla {
namespace net {
@@ -467,7 +466,6 @@ struct RedirectToRealChannelArgs {
nsDOMNavigationTiming? timing;
nsString srcdocData;
nsIURI baseUri;
SessionHistoryInfoAndId? sessionHistoryInfo;
};
struct TimingStructArgs {

View File

@@ -154,9 +154,7 @@ already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
// handler that always gets called (even for subframes) for any bubbling
// event.
if (aBrowsingContext->IsTop()) {
aBrowsingContext->InitSessionHistory();
}
docShell->InitSessionHistory();
NS_ENSURE_SUCCESS(docShellAsWin->Create(), nullptr);