Bug 1546759 - Change nsSHistory::WalkHistoryEntries to walk browsing context tree instead of doc shell tree, r=peterv,nika

WalkHistoryEntries function gets called by nsSHistory::CloneAndReplaceChild
and nsSHistory::SetChildHistoryEntry recursively, so those have to be moved
into the parent process. This eliminates many sync IPC calls.

To facilitate transition to a new session history design,
we are mirroring mOSHE and mLSHE SH entries from docshell to browsing context.
Whenever we update those entries in docshell, we will also update those in BC,
and vice versa.

Differential Revision: https://phabricator.services.mozilla.com/D56201

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Anny Gakhokidze 2020-03-10 14:28:22 +00:00
parent 9542f19af8
commit 5986a2de44
24 changed files with 828 additions and 220 deletions

View File

@ -16,6 +16,7 @@
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "nsISHistory.h"
#include "nsISHEntry.h"
namespace mozilla {
namespace dom {
@ -110,6 +111,25 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// if the top-level browsing context has been discarded.
MediaController* GetMediaController();
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();
@ -171,6 +191,10 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// browsing context tree, so it would only exist in the top level browsing
// context.
RefPtr<MediaController> mTabMediaController;
// These are being mirrored from docshell
nsCOMPtr<nsISHEntry> mOSHE;
nsCOMPtr<nsISHEntry> mLSHE;
};
} // namespace dom

View File

@ -38,6 +38,7 @@
#include "mozilla/StaticPrefs_extensions.h"
#include "mozilla/StaticPrefs_privacy.h"
#include "mozilla/StaticPrefs_ui.h"
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/StartupTimeline.h"
#include "mozilla/StorageAccess.h"
#include "mozilla/Telemetry.h"
@ -71,8 +72,8 @@
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/dom/LoadURIOptionsBinding.h"
#include "mozilla/dom/JSWindowActorChild.h"
#include "mozilla/net/DocumentChannel.h"
#include "nsSHEntry.h"
#include "mozilla/net/DocumentChannelChild.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "ReferrerInfo.h"
@ -194,6 +195,7 @@
#include "nsRefreshTimer.h"
#include "nsSandboxFlags.h"
#include "nsSHistory.h"
#include "SHEntryChild.h"
#include "nsStructuredCloneContainer.h"
#include "nsSubDocumentFrame.h"
#include "nsView.h"
@ -3192,35 +3194,8 @@ nsresult nsDocShell::AddChildSHEntryInternal(nsISHEntry* aCloneRef,
bool aCloneChildren) {
nsresult rv = NS_OK;
if (mSessionHistory) {
/* 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
* way to the top to clone the current SHEntry hierarchy
* and replace the subframe where a new url was loaded with
* a new entry.
*/
nsCOMPtr<nsISHEntry> currentHE;
int32_t index = mSessionHistory->Index();
if (index < 0) {
return NS_ERROR_FAILURE;
}
rv = mSessionHistory->LegacySHistory()->GetEntryAtIndex(
index, getter_AddRefs(currentHE));
NS_ENSURE_TRUE(currentHE, NS_ERROR_FAILURE);
nsCOMPtr<nsISHEntry> currentEntry(currentHE);
if (currentEntry) {
nsCOMPtr<nsISHEntry> nextEntry;
uint32_t cloneID = aCloneRef->GetID();
rv = nsSHistory::CloneAndReplace(currentEntry, this, cloneID, aNewEntry,
aCloneChildren,
getter_AddRefs(nextEntry));
if (NS_SUCCEEDED(rv)) {
rv = mSessionHistory->LegacySHistory()->AddEntry(nextEntry, true);
}
}
rv = mSessionHistory->LegacySHistory()->AddChildSHEntryHelper(
aCloneRef, aNewEntry, mBrowsingContext, aCloneChildren);
} else {
/* Just pass this along */
nsCOMPtr<nsIDocShell> parent =
@ -4258,8 +4233,7 @@ nsDocShell::Stop(uint32_t aStopFlags) {
if (mLoadType == LOAD_ERROR_PAGE) {
if (mLSHE) {
// Since error page loads never unset mLSHE, do so now
SetHistoryEntry(&mOSHE, mLSHE);
SetHistoryEntry(&mLSHE, nullptr);
SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
}
mFailedChannel = nullptr;
@ -5799,7 +5773,7 @@ nsresult nsDocShell::Embed(nsIContentViewer* aContentViewer,
// Set history.state
SetDocCurrentStateObj(mLSHE);
SetHistoryEntry(&mOSHE, mLSHE);
SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
}
bool updateHistory = true;
@ -6018,7 +5992,7 @@ void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
mLoadType = LOAD_NORMAL_REPLACE;
SetHistoryEntry(&mLSHE, nullptr);
SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
}
}
@ -6153,7 +6127,7 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
// Clear the mLSHE reference to indicate document loading is done one
// way or another.
SetHistoryEntry(&mLSHE, nullptr);
SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
}
// if there's a refresh header in the channel, this method
// will set it up for us.
@ -6637,7 +6611,7 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
}
// The transient about:blank viewer doesn't have a session history entry.
SetHistoryEntry(&mOSHE, nullptr);
SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
// Clear out our mTiming like we would in EndPageLoad, if we didn't
// have one before entering this function.
@ -7057,7 +7031,7 @@ nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
MOZ_LOG(gPageCacheLog, LogLevel::Debug,
("restoring presentation from session history: %s", spec.get()));
SetHistoryEntry(&mLSHE, aSHEntry);
SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
// Post an event that will remove the request after we've returned
// to the event loop. This mimics the way it is called by nsIChannel
@ -7361,7 +7335,7 @@ nsresult nsDocShell::RestoreFromHistory() {
NS_ENSURE_SUCCESS(rv, rv);
// mLSHE is now our currently-loaded document.
SetHistoryEntry(&mOSHE, mLSHE);
SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
// We aren't going to restore any items from the LayoutHistoryState,
// but we don't want them to stay around in case the page is reloaded.
@ -8613,7 +8587,8 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
// History loads, SetCurrentURI() called from OnNewURI() will send proper
// onLocationChange() notifications to the browser to update back/forward
// buttons.
SetHistoryEntry(&mLSHE, aLoadState->SHEntry());
SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
Nothing());
// Set the doc's URI according to the new history entry's URI.
RefPtr<Document> doc = GetDocument();
@ -8697,7 +8672,7 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
* loads.
*/
if (mLSHE) {
SetHistoryEntry(&mOSHE, mLSHE);
SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
// Save the postData obtained from the previous page
// in to the session history entry created for the
// anchor page, so that any history load of the anchor
@ -8716,7 +8691,7 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
/* Restore the original LSHE if we were loading something
* while same document navigation was initiated.
*/
SetHistoryEntry(&mLSHE, oldLSHE);
SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
/* 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.
*/
@ -9128,7 +9103,8 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// been called. But when loading an error page, do not clear the
// mLSHE for the real page.
if (mLoadType != LOAD_ERROR_PAGE) {
SetHistoryEntry(&mLSHE, aLoadState->SHEntry());
SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
Nothing());
if (aLoadState->SHEntry()) {
// We're making history navigation or a reload. Make sure our history ID
// points to the same ID as SHEntry's docshell ID.
@ -10543,7 +10519,7 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
// If this is a refresh to the currently loaded url, we don't
// have to update session or global history.
if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
SetHistoryEntry(&mLSHE, mOSHE);
SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
}
/* If the user pressed shift-reload, cache will create a new cache key
@ -11253,48 +11229,19 @@ nsresult nsDocShell::AddToSessionHistory(
saveLayoutState, expired);
if (root == static_cast<nsIDocShellTreeItem*>(this) && mSessionHistory) {
// If we need to clone our children onto the new session
// history entry, do so now.
if (aCloneChildren && mOSHE) {
uint32_t cloneID = mOSHE->GetID();
nsCOMPtr<nsISHEntry> newEntry;
nsSHistory::CloneAndReplace(mOSHE, this, cloneID, entry, true,
getter_AddRefs(newEntry));
NS_ASSERTION(entry == newEntry,
"The new session history should be in the new entry");
bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
Maybe<int32_t> previousEntryIndex;
Maybe<int32_t> loadedEntryIndex;
rv = mSessionHistory->LegacySHistory()->AddToRootSessionHistory(
aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
shouldPersist, &previousEntryIndex, &loadedEntryIndex);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not add entry to root session history");
if (previousEntryIndex.isSome()) {
mPreviousEntryIndex = previousEntryIndex.value();
}
// This is the root docshell
bool addToSHistory =
!LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY);
if (!addToSHistory) {
// Replace current entry in session history; If the requested index is
// valid, it indicates the loading was triggered by a history load, and
// we should replace the entry at requested index instead.
int32_t index = mSessionHistory->LegacySHistory()->GetRequestedIndex();
if (index == -1) {
index = mSessionHistory->Index();
}
// Replace the current entry with the new entry
if (index >= 0) {
rv = mSessionHistory->LegacySHistory()->ReplaceEntry(index, entry);
} else {
// If we're trying to replace an inexistant shistory entry, append.
addToSHistory = true;
}
}
if (addToSHistory) {
// Add to session history
mPreviousEntryIndex = mSessionHistory->Index();
bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
rv = mSessionHistory->LegacySHistory()->AddEntry(entry, shouldPersist);
mLoadedEntryIndex = mSessionHistory->Index();
MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,
mLoadedEntryIndex));
if (loadedEntryIndex.isSome()) {
mLoadedEntryIndex = loadedEntryIndex.value();
}
} else {
// This is a subframe.
@ -11427,6 +11374,36 @@ void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
}
}
void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
const Maybe<nsISHEntry*>& aOSHE) {
if (aLSHE.isSome()) {
SetHistoryEntry(&mLSHE, aLSHE.value());
MOZ_ASSERT(mLSHE.get() == aLSHE.value());
}
if (aOSHE.isSome()) {
SetHistoryEntry(&mOSHE, aOSHE.value());
MOZ_ASSERT(mOSHE.get() == aOSHE.value());
}
// If the SH pref is off and we are not a parent process do not update
// canonical BC
if (!StaticPrefs::fission_sessionHistoryInParent() &&
XRE_IsContentProcess()) {
return;
}
ContentChild* cc = ContentChild::GetSingleton();
RefPtr<BrowsingContext> bc =
mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
if (XRE_IsParentProcess()) {
// We are in the parent process, thus we can update the entries directly
mBrowsingContext->Canonical()->UpdateSHEntries(mLSHE, mOSHE);
} else {
// 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()), bc);
}
}
void nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr,
nsISHEntry* aEntry) {
// We need to sync up the docshell and session history trees for
@ -11435,32 +11412,14 @@ void nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr,
// to their corresponding entries in the new session history tree.
// If we don't do this, then we can cache a content viewer on the wrong
// cloned entry, and subsequently restore it at the wrong time.
nsCOMPtr<nsISHEntry> newRootEntry = nsSHistory::GetRootSHEntry(aEntry);
if (newRootEntry) {
// newRootEntry is now the new root entry.
// Find the old root entry as well.
// Need a strong ref. on |oldRootEntry| so it isn't destroyed when
// SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(*aPtr);
if (oldRootEntry) {
nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
GetInProcessSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
if (rootShell) { // if we're the root just set it, nothing to swap
nsSHistory::SwapEntriesData data = {this, newRootEntry};
nsIDocShell* rootIDocShell = static_cast<nsIDocShell*>(rootShell);
nsDocShell* rootDocShell = static_cast<nsDocShell*>(rootIDocShell);
#ifdef DEBUG
nsresult rv =
#endif
nsSHistory::SetChildHistoryEntry(oldRootEntry, rootDocShell, 0,
&data);
NS_ASSERTION(NS_SUCCEEDED(rv), "SetChildHistoryEntry failed");
}
}
RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
if (topBC->IsDiscarded()) {
topBC = nullptr;
}
RefPtr<BrowsingContext> currBC =
mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
if (topBC && *aPtr) {
(*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
}
*aPtr = aEntry;

View File

@ -661,6 +661,11 @@ class nsDocShell final : public nsDocLoader,
// in the case of a subframe navigation.
void SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry);
// This method calls SetHistoryEntry and updates mOSHE and mLSHE in BC to be
// the same as in docshell
void SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
const Maybe<nsISHEntry*>& aOSHE);
//
// URI Load
//

View File

@ -108,6 +108,10 @@ parent:
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);

View File

@ -62,6 +62,22 @@ parent:
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:

View File

@ -604,9 +604,11 @@ SHEntryChild::Create(
NS_IMETHODIMP
SHEntryChild::Clone(nsISHEntry** aResult) {
NS_IF_ADDREF(*aResult = static_cast<SHEntryChild*>(
ContentChild::GetSingleton()->SendPSHEntryConstructor(
mShared->mSHistory, this)));
RefPtr<CrossProcessSHEntry> result;
if (!SendClone(&result)) {
return NS_ERROR_FAILURE;
}
*aResult = result ? do_AddRef(result->ToSHEntryChild()).take() : nullptr;
return NS_OK;
}
@ -1009,6 +1011,31 @@ SHEntryChild::GetBfcacheID(uint64_t* aBFCacheID) {
return NS_OK;
}
NS_IMETHODIMP_(void)
SHEntryChild::SyncTreesForSubframeNavigation(nsISHEntry* aEntry,
BrowsingContext* aBC,
BrowsingContext* aIgnoreBC) {
nsTArray<SwapEntriesDocshellData> entriesToUpdate;
Unused << SendSyncTreesForSubframeNavigation(
static_cast<SHEntryChild*>(aEntry), aBC, aIgnoreBC, &entriesToUpdate);
for (auto& data : entriesToUpdate) {
// data.context() is a MaybeDiscardedBrowsingContext
// It can't be null, but if it has been discarded we will update
// the docshell anyway
MOZ_ASSERT(!data.context().IsNull(), "Browsing context cannot be null");
nsDocShell* docshell = static_cast<nsDocShell*>(
data.context().GetMaybeDiscarded()->GetDocShell());
if (docshell) {
RefPtr<SHEntryChild> oldEntry = data.oldEntry()->ToSHEntryChild();
RefPtr<SHEntryChild> newEntry;
if (data.newEntry()) {
newEntry = data.newEntry()->ToSHEntryChild();
}
docshell->SwapHistoryEntries(oldEntry, newEntry);
}
}
}
void SHEntryChild::EvictContentViewer() {
nsCOMPtr<nsIContentViewer> viewer = GetContentViewer();
if (viewer) {

View File

@ -64,6 +64,13 @@ LegacySHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
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;
}
@ -582,5 +589,31 @@ bool SHEntryParent::RecvUpdateLayoutHistoryState(
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

@ -77,6 +77,8 @@ class LegacySHEntry final : public nsSHEntry, public CrossProcessSHEntry {
return mShared.get();
}
NS_IMETHOD Clone(nsISHEntry** aResult) override;
private:
friend class SHEntryParent;
friend class SHistoryParent;
@ -203,6 +205,12 @@ class SHEntryParent final : public PSHEntryParent {
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,

View File

@ -8,6 +8,11 @@
#include "SHEntryChild.h"
#include "nsISHistoryListener.h"
namespace mozilla {
namespace dom {
class SwapEntriesDocshellData;
}
} // namespace mozilla
#define CONTENT_VIEWER_TIMEOUT_SECONDS \
"browser.sessionhistory.contentViewerTimeout"
@ -392,5 +397,70 @@ nsresult SHistoryChild::LoadURI(nsTArray<LoadSHEntryData>& aLoadData) {
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

@ -47,19 +47,12 @@ SHistoryParent::SHistoryParent(CanonicalBrowsingContext* aContext)
SHistoryParent::~SHistoryParent() { mHistory->mSHistoryParent = nullptr; }
SHEntryParent* SHistoryParent::CreateEntry(
PContentParent* aContentParent, PSHistoryParent* aSHistoryParent,
const PSHEntryOrSharedID& aEntryOrSharedID) {
RefPtr<LegacySHEntry> entry;
if (aEntryOrSharedID.type() == PSHEntryOrSharedID::Tuint64_t) {
entry = new LegacySHEntry(
aContentParent, static_cast<SHistoryParent*>(aSHistoryParent)->mHistory,
aEntryOrSharedID.get_uint64_t());
} else {
entry = new LegacySHEntry(*(
static_cast<const SHEntryParent*>(aEntryOrSharedID.get_PSHEntryParent())
->mEntry));
}
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();
}
@ -375,5 +368,65 @@ LegacySHistory::ReloadCurrentEntry() {
: 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

@ -59,7 +59,14 @@ class SHistoryParent final : public PSHistoryParent {
static SHEntryParent* CreateEntry(PContentParent* aContentParent,
PSHistoryParent* aSHistoryParent,
const PSHEntryOrSharedID& aEntryOrSharedID);
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;
@ -99,7 +106,21 @@ class SHistoryParent final : public PSHistoryParent {
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;
};

View File

@ -37,10 +37,12 @@ class SHEntrySharedParentState;
}
class nsSHEntryShared;
class nsDocShellLoadState;
struct EntriesAndBrowsingContextData;
%}
[ref] native nsIntRect(nsIntRect);
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
[ptr] native nsDocShellLoadStatePtr(nsDocShellLoadState);
webidl BrowsingContext;
[builtinclass, scriptable, uuid(0dad26b8-a259-42c7-93f1-2fa7fc076e45)]
interface nsISHEntry : nsISupports
@ -429,5 +431,17 @@ interface nsISHEntry : nsISupports
* lives there. With in-process session history this method is no-op.
*/
void synchronizeLayoutHistoryState();
/**
* Sync up the docshell and session history trees for subframe navigation.
*
* @param aEntry new entry
* @param aTopBC top BC corresponding to the root ancestor
of the docshell that called this method
* @param aIgnoreBC current BC
*/
[notxpcom] void SyncTreesForSubframeNavigation(in nsISHEntry aEntry,
in BrowsingContext aTopBC,
in BrowsingContext aIgnoreBC);
};

View File

@ -9,13 +9,16 @@ interface nsIBFCacheEntry;
interface nsISHEntry;
interface nsISHistoryListener;
interface nsIURI;
webidl BrowsingContext;
%{C++
#include "nsTArrayForwardDeclare.h"
#include "mozilla/Maybe.h"
struct EntriesAndBrowsingContextData;
%}
[ref] native nsDocshellIDArray(nsTArray<nsID>);
native MaybeInt32(Maybe<int32_t>);
/**
* An interface to the primary properties of the Session History
* component. In an embedded browser environment, the nsIWebBrowser
@ -266,4 +269,14 @@ interface nsISHistory: nsISupports
[notxpcom] void EvictContentViewersOrReplaceEntry(in nsISHEntry aNewSHEntry, in bool aReplace);
nsISHEntry createEntry();
[noscript] void AddToRootSessionHistory(in bool aCloneChildren, in nsISHEntry aOSHE,
in BrowsingContext aBC, in nsISHEntry aEntry,
in unsigned long aLoadType,
in bool aShouldPersist,
out MaybeInt32 aPreviousEntryIndex,
out MaybeInt32 aLoadedEntryIndex);
[noscript] void AddChildSHEntryHelper(in nsISHEntry aCloneRef, in nsISHEntry aNewEntry,
in BrowsingContext aBC, in bool aCloneChildren);
};

View File

@ -1020,6 +1020,48 @@ nsSHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
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
// contexts to their corresponding entries in the new session history tree. If
// we don't do this, then we can cache a content viewer on the wrong cloned
// entry, and subsequently restore it at the wrong time.
nsCOMPtr<nsISHEntry> newRootEntry = nsSHistory::GetRootSHEntry(aEntry);
if (newRootEntry) {
// newRootEntry is now the new root entry.
// Find the old root entry as well.
// Need a strong ref. on |oldRootEntry| so it isn't destroyed when
// SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(this);
if (oldRootEntry) {
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) {

View File

@ -28,6 +28,17 @@ 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:
NS_DECL_ISUPPORTS
@ -37,6 +48,11 @@ 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);

View File

@ -32,6 +32,9 @@
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/TabGroup.h"
#include "nsIWebNavigation.h"
#include "nsDocShellLoadTypes.h"
#include "base/process.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -63,6 +66,8 @@ LazyLogModule gSHistoryLog("nsSHistory");
#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
extern mozilla::LazyLogModule gPageCacheLog;
// This macro makes it easier to print a log message which includes a URI's
// spec. Example use:
//
@ -363,7 +368,7 @@ already_AddRefed<nsISHEntry> nsSHistory::GetRootSHEntry(nsISHEntry* aEntry) {
// static
nsresult nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
nsDocShell* aRootShell,
BrowsingContext* aBC,
WalkHistoryEntriesFunc aCallback,
void* aData) {
NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
@ -380,24 +385,30 @@ nsresult nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
continue;
}
nsDocShell* childShell = nullptr;
if (aRootShell) {
// Walk the children of aRootShell and see if one of them
// has srcChild as a SHEntry.
int32_t length;
aRootShell->GetInProcessChildCount(&length);
for (int32_t i = 0; i < length; i++) {
nsCOMPtr<nsIDocShellTreeItem> item;
nsresult rv = aRootShell->GetInProcessChildAt(i, getter_AddRefs(item));
NS_ENSURE_SUCCESS(rv, rv);
nsDocShell* child = static_cast<nsDocShell*>(item.get());
if (child->HasHistoryEntry(childEntry)) {
childShell = child;
break;
BrowsingContext* childBC = nullptr;
if (aBC) {
for (BrowsingContext* child : aBC->GetChildren()) {
// If the SH pref is on, or we are in the parent process, update
// canonical BC directly
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;
}
}
}
}
nsresult rv = aCallback(childEntry, childShell, i, aData);
nsresult rv = aCallback(childEntry, childBC, i, aData);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -407,32 +418,42 @@ 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;
};
// static
nsresult nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
nsDocShell* aShell,
int32_t aEntryIndex, void* aData) {
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) {
data->destTreeParent->AddChild(nullptr, aEntryIndex);
data->destTreeParent->AddChild(nullptr, aChildIndex);
}
return NS_OK;
}
@ -453,47 +474,108 @@ nsresult nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
if (srcID != cloneID || data->cloneChildren) {
// Walk the children
CloneAndReplaceData childData(cloneID, replaceEntry, data->cloneChildren,
dest);
rv = WalkHistoryEntries(aEntry, aShell, CloneAndReplaceChild, &childData);
dest, otherPid, data->entriesToUpdate);
rv = nsSHistory::WalkHistoryEntries(aEntry, aOwnerBC, CloneAndReplaceChild,
&childData);
NS_ENSURE_SUCCESS(rv, rv);
}
if (srcID != cloneID && aShell) {
aShell->SwapHistoryEntries(aEntry, dest);
if (srcID != cloneID && aOwnerBC) {
nsSHistory::HandleEntriesToSwapInDocShell(aOwnerBC, aEntry, dest,
data->entriesToUpdate, otherPid);
}
if (data->destTreeParent) {
data->destTreeParent->AddChild(dest, aEntryIndex);
data->destTreeParent->AddChild(dest, aChildIndex);
}
data->resultEntry = dest;
return rv;
}
// static
nsresult nsSHistory::CloneAndReplace(nsISHEntry* aSrcEntry,
nsDocShell* aSrcShell, uint32_t aCloneID,
nsISHEntry* aReplaceEntry,
bool aCloneChildren,
nsISHEntry** aResultEntry) {
NS_ENSURE_ARG_POINTER(aResultEntry);
nsresult nsSHistory::CloneAndReplace(
nsISHEntry* aSrcEntry, BrowsingContext* aOwnerBC, uint32_t aCloneID,
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);
nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
data.resultEntry.swap(*aResultEntry);
CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr,
aOtherPid, aEntriesToUpdate);
nsresult rv = CloneAndReplaceChild(aSrcEntry, aOwnerBC, 0, &data);
data.resultEntry.swap(*aDestEntry);
return rv;
}
// static
nsresult nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry,
nsDocShell* aShell,
int32_t aEntryIndex, void* aData) {
SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
nsDocShell* ignoreShell = data->ignoreShell;
NS_IMETHODIMP
nsSHistory::AddChildSHEntryHelper(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
BrowsingContext* aBC, bool aCloneChildren) {
nsCOMPtr<nsISHEntry> 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;
}
if (!aShell || aShell == ignoreShell) {
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
* way to the top to clone the current SHEntry hierarchy
* and replace the subframe where a new url was loaded with
* a new entry.
*/
nsCOMPtr<nsISHEntry> currentHE;
int32_t index = mIndex;
if (index < 0) {
return NS_ERROR_FAILURE;
}
GetEntryAtIndex(index, getter_AddRefs(currentHE));
NS_ENSURE_TRUE(currentHE, NS_ERROR_FAILURE);
nsresult rv = NS_OK;
uint32_t cloneID = aCloneRef->GetID();
rv = nsSHistory::CloneAndReplace(currentHE, aBC, cloneID, aNewEntry,
aCloneChildren, aNextEntry, aOtherPid,
aEntriesToUpdate);
if (NS_SUCCEEDED(rv)) {
rv = AddEntry(*aNextEntry, true, aEntriesPurged);
}
return rv;
}
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;
}
@ -533,11 +615,125 @@ nsresult nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry,
destEntry = destTreeRoot;
}
aShell->SwapHistoryEntries(aEntry, destEntry);
nsSHistory::HandleEntriesToSwapInDocShell(aBC, aEntry, destEntry,
data->entriesToUpdate, otherPid);
// Now handle the children of aEntry.
SwapEntriesData childData = {ignoreShell, destTreeRoot, destEntry};
return WalkHistoryEntries(aEntry, aShell, SetChildHistoryEntry, &childData);
SwapEntriesData childData = {data->ignoreBC, destTreeRoot, destEntry,
otherPid, data->entriesToUpdate};
return nsSHistory::WalkHistoryEntries(aEntry, aBC, SetChildHistoryEntry,
&childData);
}
// static
void nsSHistory::HandleEntriesToSwapInDocShell(
mozilla::dom::BrowsingContext* aBC, nsISHEntry* aOldEntry,
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 {
// 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);
}
}
NS_IMETHODIMP
nsSHistory::AddToRootSessionHistory(bool aCloneChildren, nsISHEntry* aOSHE,
BrowsingContext* aBC, nsISHEntry* aEntry,
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
// history entry, do so now.
if (aCloneChildren && aOSHE) {
uint32_t cloneID = aOSHE->GetID();
nsCOMPtr<nsISHEntry> newEntry;
nsSHistory::CloneAndReplace(aOSHE, aBC, cloneID, aEntry, true,
getter_AddRefs(newEntry), aOtherPid,
aEntriesToUpdate);
NS_ASSERTION(aEntry == newEntry,
"The new session history should be in the new entry");
}
// This is the root docshell
bool addToSHistory = !LOAD_TYPE_HAS_FLAGS(
aLoadType, nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY);
if (!addToSHistory) {
// Replace current entry in session history; If the requested index is
// valid, it indicates the loading was triggered by a history load, and
// we should replace the entry at requested index instead.
int32_t index = mRequestedIndex;
if (index == -1) {
index = mIndex;
}
// Replace the current entry with the new entry
if (index >= 0) {
rv = ReplaceEntry(index, aEntry);
} else {
// If we're trying to replace an inexistant shistory entry, append.
addToSHistory = true;
}
}
if (addToSHistory) {
// Add to session history
*previousEntryIndex = Some(mIndex);
rv = AddEntry(aEntry, aShouldPersist, aEntriesPurged);
*aLoadedEntryIndex = Some(mIndex);
MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
("Previous index: %d, Loaded index: %d",
previousEntryIndex->value(), aLoadedEntryIndex->value()));
}
return rv;
}
/* Add an entry to the History list at mIndex and
@ -552,6 +748,7 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist) {
nsresult nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist,
int32_t* aEntriesPurged) {
NS_ENSURE_ARG(aSHEntry);
*aEntriesPurged = 0;
nsCOMPtr<nsISHistory> shistoryOfEntry = aSHEntry->GetShistory();
if (shistoryOfEntry != this) {

View File

@ -58,10 +58,15 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
// Structure used in SetChildHistoryEntry
struct SwapEntriesData {
nsDocShell* ignoreShell; // constant; the shell to ignore
mozilla::dom::BrowsingContext*
ignoreBC; // constant; the browsing context to ignore
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;
};
nsSHistory(mozilla::dom::BrowsingContext* aRootBC, const nsID& aDocShellID);
@ -83,11 +88,15 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
static already_AddRefed<nsISHEntry> GetRootSHEntry(nsISHEntry* aEntry);
// Callback prototype for WalkHistoryEntries.
// aEntry is the child history entry, aShell is its corresponding docshell,
// aChildIndex is the child's index in its parent entry, and aData is
// the opaque pointer passed to WalkHistoryEntries.
// `aEntry` is the child history entry, `aBC` is its corresponding browsing
// context, `aChildIndex` is the child's index in its parent entry, and
// `aData` is the opaque pointer passed to WalkHistoryEntries. Both structs
// that are passed as `aData` to this function have a field
// `aEntriesToUpdate`, which is an array of entries we need to update in
// docshell, if the 'SH in parent' pref is on (which implies that this method
// is executed in the parent)
typedef nsresult (*WalkHistoryEntriesFunc)(nsISHEntry* aEntry,
nsDocShell* aShell,
mozilla::dom::BrowsingContext* aBC,
int32_t aChildIndex, void* aData);
// Clone a session history tree for subframe navigation.
@ -98,26 +107,45 @@ 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, nsDocShell* aSrcShell,
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, nsDocShell* aShell,
static nsresult CloneAndReplaceChild(nsISHEntry* aEntry,
mozilla::dom::BrowsingContext* aOwnerBC,
int32_t aChildIndex, void* aData);
// Child-walking callback for SetHistoryEntry
static nsresult SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
static nsresult SetChildHistoryEntry(nsISHEntry* aEntry,
mozilla::dom::BrowsingContext* aBC,
int32_t aEntryIndex, void* aData);
// For each child of aRootEntry, find the corresponding docshell which is
// a child of aRootShell, and call aCallback. The opaque pointer aData
// For each child of aRootEntry, find the corresponding shell which is
// a child of aBC, and call aCallback. The opaque pointer aData
// is passed to the callback.
static nsresult WalkHistoryEntries(nsISHEntry* aRootEntry,
nsDocShell* aRootShell,
mozilla::dom::BrowsingContext* aBC,
WalkHistoryEntriesFunc aCallback,
void* aData);
nsresult AddToRootSessionHistory(
bool aCloneChildren, nsISHEntry* aOSHE,
mozilla::dom::BrowsingContext* aBC, nsISHEntry* aEntry,
uint32_t aLoadType, bool aShouldPersist, uint64_t aOtherPid,
Maybe<int32_t>* aPreviousEntryIndex, 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,
@ -198,6 +226,21 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
// otherwise comparison is done to aIndex - 1.
bool RemoveDuplicate(int32_t aIndex, bool aKeepNext);
// We need to update entries in docshell and browsing context.
// If our docshell is located in parent or 'SH in parent' pref is off we can
// update it directly, Otherwise, we have two choices. If the browsing context
// that owns the docshell is in the same process as the process who called us
// over IPC, then we save entries that need to be updated in a list, and once
// we have returned from the IPC call, we update the docshell in the child
// 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,
nsTArray<EntriesAndBrowsingContextData>* aEntriesToUpdate,
uint64_t aOtherPid);
protected:
// Length of mEntries.
int32_t Length() { return int32_t(mEntries.Length()); }

View File

@ -3433,19 +3433,13 @@ bool ContentChild::DeallocPSessionStorageObserverChild(
return true;
}
PSHEntryChild* ContentChild::AllocPSHEntryChild(
PSHistoryChild* aSHistory, const PSHEntryOrSharedID& aEntryOrSharedID) {
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;
if (aEntryOrSharedID.type() == PSHEntryOrSharedID::Tuint64_t) {
child = new SHEntryChild(static_cast<SHistoryChild*>(aSHistory),
aEntryOrSharedID.get_uint64_t());
} else {
child = new SHEntryChild(
static_cast<const SHEntryChild*>(aEntryOrSharedID.get_PSHEntryChild()));
}
child = new SHEntryChild(static_cast<SHistoryChild*>(aSHistory), aSharedID);
return child.forget().take();
}
@ -3764,6 +3758,19 @@ 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();
}
already_AddRefed<nsIEventTarget> ContentChild::GetSpecificMessageEventTarget(
const Message& aMsg) {
switch (aMsg.type()) {

View File

@ -622,7 +622,8 @@ class ContentChild final
PSessionStorageObserverChild* aActor);
PSHEntryChild* AllocPSHEntryChild(PSHistoryChild* aSHistory,
const PSHEntryOrSharedID& aEntryOrSharedID);
uint64_t aSharedID);
void DeallocPSHEntryChild(PSHEntryChild*);
PSHistoryChild* AllocPSHistoryChild(
@ -696,6 +697,10 @@ class ContentChild final
const nsACString& aOriginKey, const nsTArray<KeyValuePair>& aDefaultData,
const nsTArray<KeyValuePair>& aSessionData);
mozilla::ipc::IPCResult RecvUpdateSHEntriesInDocShell(
CrossProcessSHEntry* aOldEntry, CrossProcessSHEntry* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aContext);
#ifdef NIGHTLY_BUILD
// Fetch the current number of pending input events.
//

View File

@ -5732,9 +5732,9 @@ bool ContentParent::DeallocPSessionStorageObserverParent(
return mozilla::dom::DeallocPSessionStorageObserverParent(aActor);
}
PSHEntryParent* ContentParent::AllocPSHEntryParent(
PSHistoryParent* aSHistory, const PSHEntryOrSharedID& aEntryOrSharedID) {
return SHistoryParent::CreateEntry(this, aSHistory, aEntryOrSharedID);
PSHEntryParent* ContentParent::AllocPSHEntryParent(PSHistoryParent* aSHistory,
uint64_t aSharedID) {
return SHistoryParent::CreateEntry(this, aSHistory, aSharedID);
}
void ContentParent::DeallocPSHEntryParent(PSHEntryParent* aEntry) {
@ -5743,12 +5743,8 @@ void ContentParent::DeallocPSHEntryParent(PSHEntryParent* aEntry) {
PSHistoryParent* ContentParent::AllocPSHistoryParent(
const MaybeDiscarded<BrowsingContext>& aContext) {
if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
// FIXME: What should we do here?
return nullptr;
}
return new SHistoryParent(aContext.get_canonical());
MOZ_ASSERT(!aContext.IsNull());
return new SHistoryParent(aContext.GetMaybeDiscarded()->Canonical());
}
void ContentParent::DeallocPSHistoryParent(PSHistoryParent* aActor) {
@ -5866,6 +5862,35 @@ mozilla::ipc::IPCResult ContentParent::RecvNotifyMediaAudibleChanged(
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvUpdateSHEntriesInBC(
PSHEntryParent* aNewLSHE, PSHEntryParent* aNewOSHE,
const MaybeDiscarded<BrowsingContext>& aMaybeContext) {
if (aMaybeContext.IsNull()) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to update a browsing context that does not "
"exist or has been discarded"));
return IPC_OK();
}
// if aContext has been discarded we can still update the entries
auto aContext = aMaybeContext.GetMaybeDiscarded()->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::RecvNotifyMediaSessionUpdated(
const MaybeDiscarded<BrowsingContext>& aContext, bool aIsCreated) {

View File

@ -586,8 +586,8 @@ class ContentParent final
bool DeallocPSessionStorageObserverParent(
PSessionStorageObserverParent* aActor);
PSHEntryParent* AllocPSHEntryParent(
PSHistoryParent* aSHistory, const PSHEntryOrSharedID& aEntryOrSharedID);
PSHEntryParent* AllocPSHEntryParent(PSHistoryParent* aSHistory,
uint64_t aSharedID);
void DeallocPSHEntryParent(PSHEntryParent*);
@ -1271,6 +1271,10 @@ class ContentParent final
uint32_t aShutdownStateId,
ServiceWorkerShutdownState::Progress aProgress);
mozilla::ipc::IPCResult RecvUpdateSHEntriesInBC(
PSHEntryParent* aNewLSHE, PSHEntryParent* aNewOSHE,
const MaybeDiscarded<BrowsingContext>& aMaybeContext);
// Notify the ContentChild to enable the input event prioritization when
// initializing.
void MaybeEnableRemoteInputEventQueue();

View File

@ -41,6 +41,7 @@ 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";
namespace mozilla {
@ -380,5 +381,11 @@ struct OwnerShowInfo {
nsSizeMode sizeMode;
};
struct SwapEntriesDocshellData {
CrossProcessSHEntry oldEntry;
CrossProcessSHEntry newEntry;
MaybeDiscardedBrowsingContext context;
};
} // namespace dom
} // namespace mozilla

View File

@ -123,6 +123,7 @@ using mozilla::dom::ControlledMediaState from "ipc/MediaControlIPC.h";
using mozilla::dom::MaybeMediaMetadataBase from "mozilla/dom/MediaSessionIPCUtils.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";
union ChromeRegistryItem
{
@ -344,12 +345,6 @@ struct PostMessageData
uint64_t innerWindowId;
};
union PSHEntryOrSharedID
{
PSHEntry;
uint64_t;
};
struct KeyValuePair
{
nsString key;
@ -874,6 +869,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);
parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
@ -949,8 +949,8 @@ parent:
async PSHistory(MaybeDiscardedBrowsingContext aContext);
// Clone from entry or use shared id.
sync PSHEntry(nullable PSHistory shistory, PSHEntryOrSharedID entryOrSharedID);
// Clone using shared id.
sync PSHEntry(nullable PSHistory shistory, uint64_t sharedID);
async PBenchmarkStorage();
@ -1538,6 +1538,13 @@ 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);
both:
async ScriptError(nsString message, nsString sourceName, nsString sourceLine,
uint32_t lineNumber, uint32_t colNumber, uint32_t flags,

View File

@ -837,6 +837,10 @@ description = Standing up Fission
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]
@ -847,6 +851,8 @@ description = Standing up Fission
description = Standing up Fission
[PContent::PSHEntry]
description = Standing up Fission
[PSHEntry::Clone]
description = Standing up Fission
[PSHEntry::GetURI]
description = Standing up Fission
[PSHEntry::GetOriginalURI]
@ -935,6 +941,8 @@ description = Standing up Fission
description = Standing up Fission
[PSHEntry::CreateLoadInfo]
description = Standing up Fission
[PSHEntry::SyncTreesForSubframeNavigation]
description = Standing up Fission
# The rest
[PHeapSnapshotTempFileHelper::OpenHeapSnapshotTempFile]