Commit 61bcb1d1 authored by Olli Pettay's avatar Olli Pettay
Browse files

Bug 1596958 - Synchronize layouthistorystate to parent process, r=peterv

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

--HG--
extra : moz-landing-system : lando
parent 0e2faee1
......@@ -3442,6 +3442,13 @@ nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
return NS_OK;
}
NS_IMETHODIMP nsDocShell::SynchronizeLayoutHistoryState() {
if (mOSHE) {
mOSHE->SynchronizeLayoutHistoryState();
}
return NS_OK;
}
nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr);
return mScriptGlobal;
......
......@@ -1153,4 +1153,9 @@ interface nsIDocShell : nsIDocShellTreeItem
* nsIWebNavigation.loadURI
*/
[infallible] readonly attribute boolean isNavigating;
/**
* @see nsISHEntry synchronizeLayoutHistoryState().
*/
void synchronizeLayoutHistoryState();
};
......@@ -6,6 +6,7 @@ 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";
......@@ -108,6 +109,9 @@ parent:
async ClearEntry(uint64_t aNewSharedID);
sync CreateLoadInfo() returns (nsDocShellLoadState loadState);
async UpdateLayoutHistoryState(bool scrollPositionOnly,
nsCString[] keys, PresState[] states);
sync __delete__();
};
......
......@@ -454,14 +454,12 @@ SHEntryChild::SetPostData(nsIInputStream* aPostData) {
NS_IMETHODIMP
SHEntryChild::GetLayoutHistoryState(nsILayoutHistoryState** aResult) {
// FIXME Bug 1547734 Move to parent.
NS_IF_ADDREF(*aResult = mShared->mLayoutHistoryState);
return NS_OK;
}
NS_IMETHODIMP
SHEntryChild::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
// FIXME Bug 1547734 Move to parent.
mShared->mLayoutHistoryState = aState;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(
......@@ -472,7 +470,6 @@ SHEntryChild::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
NS_IMETHODIMP
SHEntryChild::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
// FIXME Bug 1547734 Move to parent.
nsCOMPtr<nsILayoutHistoryState> historyState;
if (mShared->mLayoutHistoryState) {
historyState = mShared->mLayoutHistoryState;
......@@ -486,6 +483,20 @@ SHEntryChild::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
return NS_OK;
}
NS_IMETHODIMP
SHEntryChild::SynchronizeLayoutHistoryState() {
if (!mShared->mLayoutHistoryState) {
return NS_OK;
}
bool scrollPositionOnly = false;
nsTArray<nsCString> keys;
nsTArray<mozilla::PresState> states;
mShared->mLayoutHistoryState->GetContents(&scrollPositionOnly, keys, states);
Unused << SendUpdateLayoutHistoryState(scrollPositionOnly, keys, states);
return NS_OK;
}
NS_IMETHODIMP
SHEntryChild::GetLoadType(uint32_t* aResult) {
return SendGetLoadType(aResult) ? NS_OK : NS_ERROR_FAILURE;
......
......@@ -558,5 +558,29 @@ bool SHEntryParent::RecvCreateLoadInfo(
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;
}
} // namespace dom
} // namespace mozilla
......@@ -204,6 +204,10 @@ class SHEntryParent final : public PSHEntryParent {
bool RecvCreateLoadInfo(RefPtr<nsDocShellLoadState>* aLoadState);
bool RecvUpdateLayoutHistoryState(const bool& aScrollPositionOnly,
nsTArray<nsCString>&& aKeys,
nsTArray<PresState>&& aStates);
RefPtr<LegacySHEntry> mEntry;
};
......
......@@ -422,5 +422,12 @@ interface nsISHEntry : nsISupports
[noscript] nsDocShellLoadStatePtr CreateLoadInfo();
[infallible] readonly attribute unsigned long long bfcacheID;
/**
* synchronizeLayoutHistoryState() can be used to synchronize
* layoutHistoryState object to the parent process in case session history
* lives there. With in-process session history this method is no-op.
*/
void synchronizeLayoutHistoryState();
};
......@@ -234,25 +234,33 @@ nsSHEntry::SetPostData(nsIInputStream* aPostData) {
NS_IMETHODIMP
nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
*aResult = mShared->mLayoutHistoryState;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
MOZ_ASSERT(!mShared->mLayoutHistoryState);
mShared->mLayoutHistoryState = aState;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(
!mShared->mSaveLayoutState);
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
MOZ_CRASH(
"Classes inheriting from nsSHEntry should implement this. "
"Bug 1546344 will clean this up.");
if (!mShared->mLayoutHistoryState) {
nsCOMPtr<nsILayoutHistoryState> historyState;
historyState = NS_NewLayoutHistoryState();
SetLayoutHistoryState(historyState);
}
nsCOMPtr<nsILayoutHistoryState> state = GetLayoutHistoryState();
state.forget(aState);
return NS_OK;
}
......@@ -1025,6 +1033,12 @@ void nsSHEntry::EvictContentViewer() {
}
}
NS_IMETHODIMP
nsSHEntry::SynchronizeLayoutHistoryState() {
// No-op on purpose. See nsISHEntry.idl
return NS_OK;
}
nsLegacySHEntry::nsLegacySHEntry(nsISHistory* aHistory, uint64_t aID)
: nsSHEntry(new nsSHEntryShared(aHistory, aID)) {}
......@@ -1040,37 +1054,6 @@ nsLegacySHEntry::GetContentViewer(nsIContentViewer** aResult) {
return NS_OK;
}
NS_IMETHODIMP
nsLegacySHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult) {
*aResult = GetState()->mLayoutHistoryState;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsLegacySHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
GetState()->mLayoutHistoryState = aState;
if (GetState()->mLayoutHistoryState) {
GetState()->mLayoutHistoryState->SetScrollPositionOnly(
!GetState()->mSaveLayoutState);
}
return NS_OK;
}
NS_IMETHODIMP
nsLegacySHEntry::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
if (!GetState()->mLayoutHistoryState) {
nsCOMPtr<nsILayoutHistoryState> historyState;
historyState = NS_NewLayoutHistoryState();
SetLayoutHistoryState(historyState);
}
nsCOMPtr<nsILayoutHistoryState> state = GetLayoutHistoryState();
state.forget(aState);
return NS_OK;
}
NS_IMETHODIMP
nsLegacySHEntry::Create(
nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
......@@ -1081,9 +1064,9 @@ nsLegacySHEntry::Create(
nsIURI* aResultPrincipalURI, bool aLoadReplace,
nsIReferrerInfo* aReferrerInfo, const nsAString& aSrcdocData,
bool aSrcdocEntry, nsIURI* aBaseURI, bool aSaveLayoutState, bool aExpired) {
GetState()->mLayoutHistoryState = nullptr;
mShared->mLayoutHistoryState = nullptr;
GetState()->mSaveLayoutState = aSaveLayoutState;
mShared->mSaveLayoutState = aSaveLayoutState;
return nsSHEntry::Create(aURI, aTitle, aInputStream, aCacheKey, aContentType,
aTriggeringPrincipal, aPrincipalToInherit,
......@@ -1102,15 +1085,15 @@ nsLegacySHEntry::Clone(nsISHEntry** aResult) {
NS_IMETHODIMP
nsLegacySHEntry::GetSaveLayoutStateFlag(bool* aFlag) {
*aFlag = GetState()->mSaveLayoutState;
*aFlag = mShared->mSaveLayoutState;
return NS_OK;
}
NS_IMETHODIMP
nsLegacySHEntry::SetSaveLayoutStateFlag(bool aFlag) {
GetState()->mSaveLayoutState = aFlag;
if (GetState()->mLayoutHistoryState) {
GetState()->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
mShared->mSaveLayoutState = aFlag;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
}
return NS_OK;
......
......@@ -89,9 +89,6 @@ class nsLegacySHEntry final : public nsSHEntry {
using nsISHEntry::GetRefreshURIList;
NS_IMETHOD GetRefreshURIList(nsIMutableArray** aRefreshURIList) override;
NS_IMETHOD SetRefreshURIList(nsIMutableArray* aRefreshURIList) override;
using nsSHEntry::GetLayoutHistoryState;
NS_IMETHOD GetLayoutHistoryState(nsILayoutHistoryState** aResult) override;
NS_IMETHOD SetLayoutHistoryState(nsILayoutHistoryState* aState) override;
using nsISHEntry::GetSaveLayoutStateFlag;
NS_IMETHOD GetSaveLayoutStateFlag(bool* aSaveLayoutStateFlag) override;
NS_IMETHOD SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) override;
......@@ -100,7 +97,6 @@ class nsLegacySHEntry final : public nsSHEntry {
nsIDocShellTreeItem** aShell) override;
NS_IMETHOD_(void) ClearChildShells() override;
NS_IMETHOD_(void) SyncPresentationState() override;
NS_IMETHOD InitLayoutHistoryState(nsILayoutHistoryState** aState) override;
NS_IMETHOD Create(
nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
uint32_t aCacheKey, const nsACString& aContentType,
......
......@@ -41,7 +41,8 @@ SHEntrySharedParentState::SHEntrySharedParentState(nsIWeakReference* aSHistory,
mIsFrameNavigation(false),
mSticky(true),
mDynamicallyCreated(false),
mExpired(false) {}
mExpired(false),
mSaveLayoutState(true) {}
SHEntrySharedParentState::~SHEntrySharedParentState() {}
......@@ -51,6 +52,7 @@ void SHEntrySharedParentState::CopyFrom(SHEntrySharedParentState* aEntry) {
mPrincipalToInherit = aEntry->mPrincipalToInherit;
mStoragePrincipalToInherit = aEntry->mStoragePrincipalToInherit;
mCsp = aEntry->mCsp;
mSaveLayoutState = aEntry->mSaveLayoutState;
mContentType.Assign(aEntry->mContentType);
mIsFrameNavigation = aEntry->mIsFrameNavigation;
mSticky = aEntry->mSticky;
......
......@@ -72,6 +72,9 @@ class SHEntrySharedParentState {
nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCOMPtr<nsIPrincipal> mStoragePrincipalToInherit;
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
// Child side updates layout history state when page is being unloaded or
// moved to bfcache.
nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
nsCString mContentType;
nsIntRect mViewerBounds;
......@@ -90,6 +93,8 @@ class SHEntrySharedParentState {
// This flag is about necko cache, not bfcache.
bool mExpired;
bool mSaveLayoutState;
};
/**
......@@ -129,6 +134,9 @@ class SHEntrySharedChildState {
/**
* nsSHEntryShared holds the shared state if the session history is not stored
* in the parent process, or if the load itself happens in the parent process.
* Note, since nsSHEntryShared inherits both SHEntrySharedParentState and
* SHEntrySharedChildState and those have some same member variables,
* the ones from SHEntrySharedParentState should be used.
*/
class nsSHEntryShared final : public nsIBFCacheEntry,
public nsStubMutationObserver,
......
......@@ -10330,6 +10330,11 @@ void Document::RemovedFromDocShell() {
child = child->GetNextSibling()) {
child->SaveSubtreeState();
}
nsIDocShell* docShell = GetDocShell();
if (docShell) {
docShell->SynchronizeLayoutHistoryState();
}
}
 
already_AddRefed<nsILayoutHistoryState> Document::GetLayoutHistoryState()
......
......@@ -1697,6 +1697,7 @@ nsDocumentViewer::Close(nsISHEntry* aSHEntry) {
static void DetachContainerRecurse(nsIDocShell* aShell) {
// Unhook this docshell's presentation
aShell->SynchronizeLayoutHistoryState();
nsCOMPtr<nsIContentViewer> viewer;
aShell->GetContentViewer(getter_AddRefs(viewer));
if (viewer) {
......@@ -1824,6 +1825,7 @@ nsDocumentViewer::Destroy() {
// and shEntry has no window state at this point we'll be ok; we just won't
// cache ourselves.
shEntry->SyncPresentationState();
shEntry->SynchronizeLayoutHistoryState();
// Shut down accessibility for the document before we start to tear it down.
#ifdef ACCESSIBILITY
......
......@@ -13,6 +13,7 @@
[ptr] native PresStatePtr(mozilla::PresState);
native PresStateUnique(mozilla::UniquePtr<mozilla::PresState>);
native PresState(mozilla::PresState);
[ref] native nsCString(const nsCString);
native constBool(const bool);
......@@ -94,6 +95,18 @@ interface nsILayoutHistoryState : nsISupports
* Resets PresState::GetScrollState of all PresState objects to 0,0.
*/
[noscript, notxpcom, nostdcall] void ResetScrollState();
/**
* Get the contents of the layout history.
*/
[noscript, notxpcom, nostdcall] void GetContents(out boolean aScrollPositionOnly,
out Array<ACString> aKeys,
out Array<PresState> aStates);
/**
* Remove all the states and clear the scroll position only flag.
*/
[noscript, notxpcom, nostdcall] void Reset();
};
%{C++
......
......@@ -135,6 +135,23 @@ void nsLayoutHistoryState::ResetScrollState() {
}
}
void nsLayoutHistoryState::GetContents(bool* aScrollPositionOnly,
nsTArray<nsCString>& aKeys,
nsTArray<mozilla::PresState>& aStates) {
*aScrollPositionOnly = mScrollPositionOnly;
aKeys.SetCapacity(mStates.Count());
aStates.SetCapacity(mStates.Count());
for (auto iter = mStates.Iter(); !iter.Done(); iter.Next()) {
aKeys.AppendElement(iter.Key());
aStates.AppendElement(*(iter.Data().get()));
}
}
void nsLayoutHistoryState::Reset() {
mScrollPositionOnly = false;
mStates.Clear();
}
namespace mozilla {
UniquePtr<PresState> NewPresState() {
return MakeUnique<PresState>(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment