Bug 1696923 - [SHIP] Update SaveLayoutStateFlag after page load similarly to in-process session history, r=peterv

Differential Revision: https://phabricator.services.mozilla.com/D107479
This commit is contained in:
Olli Pettay 2021-03-09 18:16:58 +00:00
parent ca10096bc9
commit a2d036fda6
5 changed files with 90 additions and 68 deletions

View File

@ -953,7 +953,7 @@ class nsDocShell final : public nsDocLoader,
bool IsFrame() { return mBrowsingContext->IsFrame(); }
bool CanSetOriginAttributes();
bool ShouldBlockLoadingForBackButton();
bool ShouldDiscardLayoutState(nsIHttpChannel* aChannel);
static bool ShouldDiscardLayoutState(nsIHttpChannel* aChannel);
bool HasUnloadedParent();
bool JustStartedNetworkLoad();
bool NavigationBlockedByPrinting(bool aDisplayErrorDialog = true);

View File

@ -199,6 +199,12 @@ bool SessionHistoryInfo::IsSubFrame() const {
return mSharedState.Get()->mIsFrameNavigation;
}
void SessionHistoryInfo::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
MOZ_ASSERT(XRE_IsParentProcess());
static_cast<SHEntrySharedParentState*>(mSharedState.Get())->mSaveLayoutState =
aSaveLayoutStateFlag;
}
void SessionHistoryInfo::FillLoadInfo(nsDocShellLoadState& aLoadState) const {
aLoadState.SetOriginalURI(mOriginalURI);
aLoadState.SetMaybeResultPrincipalURI(Some(mResultPrincipalURI));

View File

@ -135,6 +135,8 @@ class SessionHistoryInfo {
uint32_t LoadType() { return mLoadType; }
void SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag);
private:
friend class SessionHistoryEntry;
friend struct mozilla::ipc::IPDLParamTraits<SessionHistoryInfo>;

View File

@ -1199,6 +1199,71 @@ void nsSHistory::LoadURIOrBFCache(LoadEntryResult& aLoadEntry) {
RefPtr<nsFrameLoader> frameLoader = she->GetFrameLoader();
if (canonicalBC->Group()->Toplevels().Length() == 1 && frameLoader &&
(!currentShe || she->SharedInfo() != currentShe->SharedInfo())) {
auto restore = [canonicalBC, loadState,
she](const nsTArray<bool> aCanSaves) {
bool canSave = !aCanSaves.Contains(false);
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
("nsSHistory::LoadURIOrBFCache "
"saving presentation=%i",
canSave));
nsCOMPtr<nsFrameLoaderOwner> frameLoaderOwner =
do_QueryInterface(canonicalBC->GetEmbedderElement());
if (frameLoaderOwner) {
RefPtr<nsFrameLoader> fl = she->GetFrameLoader();
if (fl) {
she->SetFrameLoader(nullptr);
RefPtr<BrowsingContext> loadingBC =
fl->GetMaybePendingBrowsingContext();
if (loadingBC) {
RefPtr<nsFrameLoader> currentFrameLoader =
frameLoaderOwner->GetFrameLoader();
// The current page can be bfcached, store the
// nsFrameLoader in the current SessionHistoryEntry.
if (canSave && canonicalBC->GetActiveSessionHistoryEntry()) {
canonicalBC->GetActiveSessionHistoryEntry()->SetFrameLoader(
currentFrameLoader);
Unused << canonicalBC->SetIsInBFCache(true);
}
// ReplacedBy will swap the entry back.
canonicalBC->SetActiveSessionHistoryEntry(she);
loadingBC->Canonical()->SetActiveSessionHistoryEntry(nullptr);
RemotenessChangeOptions options;
canonicalBC->ReplacedBy(loadingBC->Canonical(), options);
frameLoaderOwner->ReplaceFrameLoader(fl);
// The old page can't be stored in the bfcache,
// destroy the nsFrameLoader.
if (!canSave && currentFrameLoader) {
currentFrameLoader->Destroy();
}
// The current active entry should not store
// nsFrameLoader.
loadingBC->Canonical()->GetSessionHistory()->UpdateIndex();
loadingBC->Canonical()->HistoryCommitIndexAndLength();
Unused << loadingBC->SetIsInBFCache(false);
// ResetSHEntryHasUserInteractionCache(); ?
// browser.navigation.requireUserInteraction is still
// disabled everywhere.
return;
}
}
}
// Fall back to do a normal load.
canonicalBC->LoadURI(loadState, false);
};
if (currentShe && !currentShe->GetSaveLayoutStateFlag()) {
// Current page can't enter bfcache because of
// SaveLayoutStateFlag, just run the restore immediately.
nsTArray<bool> canSaves;
canSaves.AppendElement(false);
restore(std::move(canSaves));
return;
}
nsTArray<RefPtr<PContentParent::CanSavePresentationPromise>>
canSavePromises;
canonicalBC->Group()->EachParent([&](ContentParent* aParent) {
@ -1210,72 +1275,13 @@ void nsSHistory::LoadURIOrBFCache(LoadEntryResult& aLoadEntry) {
// Check if the current page can enter bfcache.
PContentParent::CanSavePresentationPromise::All(
GetCurrentSerialEventTarget(), canSavePromises)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[canonicalBC, loadState, she](const nsTArray<bool> aCanSaves) {
bool canSave = !aCanSaves.Contains(false);
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
("nsSHistory::LoadURIOrBFCache "
"saving presentation=%i",
canSave));
nsCOMPtr<nsFrameLoaderOwner> frameLoaderOwner =
do_QueryInterface(canonicalBC->GetEmbedderElement());
if (frameLoaderOwner) {
RefPtr<nsFrameLoader> fl = she->GetFrameLoader();
if (fl) {
she->SetFrameLoader(nullptr);
RefPtr<BrowsingContext> loadingBC =
fl->GetMaybePendingBrowsingContext();
if (loadingBC) {
RefPtr<nsFrameLoader> currentFrameLoader =
frameLoaderOwner->GetFrameLoader();
// The current page can be bfcached, store the
// nsFrameLoader in the current SessionHistoryEntry.
if (canSave &&
canonicalBC->GetActiveSessionHistoryEntry()) {
canonicalBC->GetActiveSessionHistoryEntry()
->SetFrameLoader(currentFrameLoader);
Unused << canonicalBC->SetIsInBFCache(true);
}
// ReplacedBy will swap the entry back.
canonicalBC->SetActiveSessionHistoryEntry(she);
loadingBC->Canonical()->SetActiveSessionHistoryEntry(
nullptr);
RemotenessChangeOptions options;
canonicalBC->ReplacedBy(loadingBC->Canonical(), options);
frameLoaderOwner->ReplaceFrameLoader(fl);
// The old page can't be stored in the bfcache,
// destroy the nsFrameLoader.
if (!canSave && currentFrameLoader) {
currentFrameLoader->Destroy();
}
// The current active entry should not store
// nsFrameLoader.
loadingBC->Canonical()
->GetSessionHistory()
->UpdateIndex();
loadingBC->Canonical()->HistoryCommitIndexAndLength();
Unused << loadingBC->SetIsInBFCache(false);
// ResetSHEntryHasUserInteractionCache(); ?
// browser.navigation.requireUserInteraction is still
// disabled everywhere.
return;
}
}
}
// Fall back to do a normal load.
canonicalBC->LoadURI(loadState, false);
},
[canonicalBC, loadState](mozilla::ipc::ResponseRejectReason) {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
("nsSHistory::LoadURIOrBFCache "
"error in trying to save presentation"));
canonicalBC->LoadURI(loadState, false);
});
->Then(GetMainThreadSerialEventTarget(), __func__, std::move(restore),
[canonicalBC, loadState](mozilla::ipc::ResponseRejectReason) {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
("nsSHistory::LoadURIOrBFCache "
"error in trying to save presentation"));
canonicalBC->LoadURI(loadState, false);
});
return;
}
if (frameLoader) {

View File

@ -1634,7 +1634,10 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
(mLoadStateLoadType == LOAD_NORMAL ||
mLoadStateLoadType == LOAD_HISTORY || mLoadStateLoadType == LOAD_LINK ||
mLoadStateLoadType == LOAD_STOP_CONTENT ||
mLoadStateLoadType == LOAD_STOP_CONTENT_AND_REPLACE)) {
mLoadStateLoadType == LOAD_STOP_CONTENT_AND_REPLACE) &&
(!browsingContext->GetActiveSessionHistoryEntry() ||
browsingContext->GetActiveSessionHistoryEntry()
->GetSaveLayoutStateFlag())) {
options.mReplaceBrowsingContext = true;
options.mTryUseBFCache = true;
}
@ -2134,6 +2137,11 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_TOP_LEVEL_LOAD_IN_PROGRESS;
loadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
}
if (mLoadingSessionHistoryInfo &&
nsDocShell::ShouldDiscardLayoutState(httpChannel)) {
mLoadingSessionHistoryInfo->mInfo.SetSaveLayoutStateFlag(false);
}
}
auto* loadingContext = GetLoadingBrowsingContext();