зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689601, try to use bfcache for top level pages, r=peterv
Differential Revision: https://phabricator.services.mozilla.com/D105238
This commit is contained in:
Родитель
3571739670
Коммит
101955fa30
|
@ -2621,6 +2621,25 @@ void BrowsingContext::DidSet(FieldIndex<IDX_UserAgentOverride>) {
|
|||
});
|
||||
}
|
||||
|
||||
bool BrowsingContext::CanSet(FieldIndex<IDX_IsInBFCache>, bool,
|
||||
ContentParent* aSource) {
|
||||
return IsTop() && !aSource && StaticPrefs::fission_bfcacheInParent();
|
||||
}
|
||||
|
||||
void BrowsingContext::DidSet(FieldIndex<IDX_IsInBFCache>) {
|
||||
MOZ_RELEASE_ASSERT(StaticPrefs::fission_bfcacheInParent());
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsTop());
|
||||
|
||||
const bool isInBFCache = GetIsInBFCache();
|
||||
PreOrderWalk([&](BrowsingContext* aContext) {
|
||||
nsCOMPtr<nsIDocShell> shell = aContext->GetDocShell();
|
||||
if (shell) {
|
||||
static_cast<nsDocShell*>(shell.get())
|
||||
->FirePageHideShowNonRecursive(!isInBFCache);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BrowsingContext::SetCustomPlatform(const nsAString& aPlatform,
|
||||
ErrorResult& aRv) {
|
||||
Top()->SetPlatformOverride(aPlatform, aRv);
|
||||
|
|
|
@ -197,7 +197,8 @@ enum class ExplicitActiveStatus : uint8_t {
|
|||
FIELD(HasMainMediaController, bool) \
|
||||
/* The number of entries added to the session history because of this \
|
||||
* browsing context. */ \
|
||||
FIELD(HistoryEntryCount, uint32_t)
|
||||
FIELD(HistoryEntryCount, uint32_t) \
|
||||
FIELD(IsInBFCache, bool)
|
||||
|
||||
// BrowsingContext, in this context, is the cross process replicated
|
||||
// environment in which information about documents is stored. In
|
||||
|
@ -1035,6 +1036,9 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||
void DidSet(FieldIndex<IDX_TextZoom>, float aOldValue);
|
||||
void DidSet(FieldIndex<IDX_AuthorStyleDisabledDefault>);
|
||||
|
||||
bool CanSet(FieldIndex<IDX_IsInBFCache>, bool, ContentParent* aSource);
|
||||
void DidSet(FieldIndex<IDX_IsInBFCache>);
|
||||
|
||||
// True if the process attemping to set field is the same as the owning
|
||||
// process. Deprecated. New code that might use this should generally be moved
|
||||
// to WindowContext or be settable only by the parent process.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/net/DocumentLoadListener.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/StaticPrefs_fission.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "mozilla/MozPromiseInlines.h"
|
||||
#include "nsDocShell.h"
|
||||
|
@ -158,7 +159,8 @@ void CanonicalBrowsingContext::MaybeAddAsProgressListener(
|
|||
|
||||
void CanonicalBrowsingContext::ReplacedBy(CanonicalBrowsingContext* aNewContext,
|
||||
const RemotenessChangeState& aState) {
|
||||
MOZ_ASSERT(!aNewContext->EverAttached());
|
||||
MOZ_ASSERT(!aNewContext->mWebProgress);
|
||||
MOZ_ASSERT(!aNewContext->mSessionHistory);
|
||||
MOZ_ASSERT(IsTop() && aNewContext->IsTop());
|
||||
if (mStatusFilter) {
|
||||
mStatusFilter->RemoveProgressListener(mWebProgress);
|
||||
|
@ -170,8 +172,20 @@ void CanonicalBrowsingContext::ReplacedBy(CanonicalBrowsingContext* aNewContext,
|
|||
aNewContext->mFields.SetWithoutSyncing<IDX_ExplicitActive>(
|
||||
GetExplicitActive());
|
||||
|
||||
// XXXBFCache name handling is still a bit broken in Fission in general,
|
||||
// at least in case name should be cleared.
|
||||
if (aState.mTryUseBFCache) {
|
||||
aNewContext->mFields.SetWithoutSyncing<IDX_Name>(GetName());
|
||||
aNewContext->mFields.SetWithoutSyncing<IDX_HasLoadedNonInitialDocument>(
|
||||
GetHasLoadedNonInitialDocument());
|
||||
}
|
||||
|
||||
if (mSessionHistory) {
|
||||
mSessionHistory->SetBrowsingContext(aNewContext);
|
||||
if (StaticPrefs::fission_bfcacheInParent()) {
|
||||
// XXXBFCache Should we clear the epoch always?
|
||||
mSessionHistory->SetEpoch(0, Nothing());
|
||||
}
|
||||
mSessionHistory.swap(aNewContext->mSessionHistory);
|
||||
RefPtr<ChildSHistory> childSHistory = ForgetChildSHistory();
|
||||
aNewContext->SetChildSHistory(childSHistory);
|
||||
|
@ -307,6 +321,11 @@ SessionHistoryEntry* CanonicalBrowsingContext::GetActiveSessionHistoryEntry() {
|
|||
return mActiveEntry;
|
||||
}
|
||||
|
||||
void CanonicalBrowsingContext::SetActiveSessionHistoryEntry(
|
||||
SessionHistoryEntry* aEntry) {
|
||||
mActiveEntry = aEntry;
|
||||
}
|
||||
|
||||
bool CanonicalBrowsingContext::HasHistoryEntry(nsISHEntry* aEntry) {
|
||||
// XXX Should we check also loading entries?
|
||||
return aEntry && mActiveEntry == aEntry;
|
||||
|
@ -1511,6 +1530,12 @@ bool CanonicalBrowsingContext::SupportsLoadingInParent(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Session-history-in-parent implementation relies currently on getting a
|
||||
// round trip through a child process.
|
||||
if (aLoadState->LoadIsFromSessionHistory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// DocumentChannel currently only supports connecting channels into the
|
||||
// content process, so we can only support schemes that will always be loaded
|
||||
// there for now. Restrict to just http(s) for simplicity.
|
||||
|
@ -1584,12 +1609,6 @@ bool CanonicalBrowsingContext::AttemptSpeculativeLoadInParent(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Session-history-in-parent implementation relies currently on getting a
|
||||
// round trip through a child process.
|
||||
if (aLoadState->LoadIsFromSessionHistory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we successfully open the DocumentChannel, then it'll register
|
||||
// itself using aLoadIdentifier and be kept alive until it completes
|
||||
// loading.
|
||||
|
|
|
@ -120,6 +120,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
|
||||
nsISHistory* GetSessionHistory();
|
||||
SessionHistoryEntry* GetActiveSessionHistoryEntry();
|
||||
void SetActiveSessionHistoryEntry(SessionHistoryEntry* aEntry);
|
||||
|
||||
UniquePtr<LoadingSessionHistoryInfo> CreateLoadingSessionHistoryEntryForLoad(
|
||||
nsDocShellLoadState* aLoadState, nsIChannel* aChannel);
|
||||
|
|
|
@ -1195,6 +1195,64 @@ void nsDocShell::FirePageHideNotificationInternal(
|
|||
}
|
||||
}
|
||||
|
||||
void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
|
||||
MOZ_ASSERT(StaticPrefs::fission_bfcacheInParent());
|
||||
|
||||
if (!mContentViewer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Emulate what non-SHIP BFCache does too. In pageshow case
|
||||
// add and remove a request and before that call SetCurrentURI to get
|
||||
// the location change notification.
|
||||
// For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
|
||||
nsCOMPtr<nsIContentViewer> contentViewer(mContentViewer);
|
||||
if (aShow) {
|
||||
mFiredUnloadEvent = false;
|
||||
RefPtr<Document> doc = contentViewer->GetDocument();
|
||||
if (doc) {
|
||||
if (mBrowsingContext->IsTop()) {
|
||||
doc->NotifyPossibleTitleChange(false);
|
||||
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
|
||||
// XXXBFCache Resume doesn't go through oop iframes.
|
||||
mScriptGlobal->GetCurrentInnerWindowInternal()->Thaw();
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel = doc->GetChannel();
|
||||
if (channel) {
|
||||
SetCurrentURI(doc->GetDocumentURI(), channel, true, 0);
|
||||
mEODForCurrentDocument = false;
|
||||
mIsRestoringDocument = true;
|
||||
mLoadGroup->AddRequest(channel, nullptr);
|
||||
mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
|
||||
mIsRestoringDocument = false;
|
||||
}
|
||||
RefPtr<PresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
// XXXBFcache Thaw doesn't deal with OOP iframes.
|
||||
presShell->Thaw();
|
||||
}
|
||||
}
|
||||
} else if (!mFiredUnloadEvent) {
|
||||
// XXXBFCache check again that the page can enter bfcache.
|
||||
// XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
|
||||
mFiredUnloadEvent = true;
|
||||
contentViewer->PageHide(false);
|
||||
|
||||
if (mBrowsingContext->IsTop()) {
|
||||
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
|
||||
// XXXBFCache Resume doesn't go through oop iframes.
|
||||
mScriptGlobal->GetCurrentInnerWindowInternal()->Freeze();
|
||||
}
|
||||
}
|
||||
RefPtr<PresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
// XXXBFcache Freeze doesn't deal with OOP iframes.
|
||||
presShell->Freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsDocShell::Dispatch(TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable) {
|
||||
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||
|
@ -6898,6 +6956,7 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
|||
// Only save presentation for "normal" loads and link loads. Anything else
|
||||
// probably wants to refetch the page, so caching the old presentation
|
||||
// would be incorrect.
|
||||
// XXXBFCache in parent needs something like this!
|
||||
if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
|
||||
aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
|
||||
aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
|
||||
|
|
|
@ -937,6 +937,8 @@ class nsDocShell final : public nsDocLoader,
|
|||
void FirePageHideNotificationInternal(bool aIsUnload,
|
||||
bool aSkipCheckingDynEntries);
|
||||
|
||||
void FirePageHideShowNonRecursive(bool aShow);
|
||||
|
||||
nsresult Dispatch(mozilla::TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
|
|
|
@ -1348,7 +1348,8 @@ SHEntrySharedParentState* SessionHistoryEntry::SharedInfo() const {
|
|||
|
||||
void SessionHistoryEntry::SetFrameLoader(nsFrameLoader* aFrameLoader) {
|
||||
MOZ_ASSERT_IF(aFrameLoader, !SharedInfo()->mFrameLoader);
|
||||
MOZ_RELEASE_ASSERT(StaticPrefs::fission_bfcacheInParent());
|
||||
// If the pref is disabled, we still allow evicting the existing entries.
|
||||
MOZ_RELEASE_ASSERT(!aFrameLoader || StaticPrefs::fission_bfcacheInParent());
|
||||
SharedInfo()->mFrameLoader = aFrameLoader;
|
||||
if (aFrameLoader) {
|
||||
// When a new frameloader is stored, try to evict some older
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsCOMArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
@ -31,12 +32,15 @@
|
|||
#include "prsystem.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.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"
|
||||
|
@ -51,12 +55,16 @@ using namespace mozilla::dom;
|
|||
"browser.sessionhistory.max_total_viewers"
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS \
|
||||
"browser.sessionhistory.contentViewerTimeout"
|
||||
// Observe fission.bfcacheInParent so that BFCache can be enabled/disabled when
|
||||
// the pref is changed.
|
||||
#define PREF_FISSION_BFCACHEINPARENT "fission.bfcacheInParent"
|
||||
|
||||
// Default this to time out unused content viewers after 30 minutes
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30 * 60)
|
||||
|
||||
static const char* kObservedPrefs[] = {
|
||||
PREF_SHISTORY_SIZE, PREF_SHISTORY_MAX_TOTAL_VIEWERS, nullptr};
|
||||
static const char* kObservedPrefs[] = {PREF_SHISTORY_SIZE,
|
||||
PREF_SHISTORY_MAX_TOTAL_VIEWERS,
|
||||
PREF_FISSION_BFCACHEINPARENT, nullptr};
|
||||
|
||||
static int32_t gHistoryMaxSize = 50;
|
||||
// List of all SHistory objects, used for content viewer cache eviction
|
||||
|
@ -76,6 +84,7 @@ LazyLogModule gSHistoryLog("nsSHistory");
|
|||
#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
|
||||
|
||||
extern mozilla::LazyLogModule gPageCacheLog;
|
||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||
|
||||
// This macro makes it easier to print a log message which includes a URI's
|
||||
// spec. Example use:
|
||||
|
@ -342,7 +351,8 @@ uint32_t nsSHistory::CalcMaxTotalViewers() {
|
|||
// static
|
||||
void nsSHistory::UpdatePrefs() {
|
||||
Preferences::GetInt(PREF_SHISTORY_SIZE, &gHistoryMaxSize);
|
||||
if (mozilla::SessionHistoryInParent()) {
|
||||
if (mozilla::SessionHistoryInParent() &&
|
||||
!StaticPrefs::fission_bfcacheInParent()) {
|
||||
sHistoryMaxTotalViewers = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -1165,10 +1175,114 @@ nsSHistory::EvictAllContentViewers() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsSHistory::LoadURIOrBFCache(LoadEntryResult& aLoadEntry) {
|
||||
if (mozilla::SessionHistoryInParent() &&
|
||||
StaticPrefs::fission_bfcacheInParent() &&
|
||||
aLoadEntry.mBrowsingContext->IsTop()) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
RefPtr<nsDocShellLoadState> loadState = aLoadEntry.mLoadState;
|
||||
RefPtr<CanonicalBrowsingContext> canonicalBC =
|
||||
aLoadEntry.mBrowsingContext->Canonical();
|
||||
nsCOMPtr<SessionHistoryEntry> she = do_QueryInterface(loadState->SHEntry());
|
||||
nsCOMPtr<SessionHistoryEntry> currentShe =
|
||||
canonicalBC->GetActiveSessionHistoryEntry();
|
||||
MOZ_ASSERT(she);
|
||||
RefPtr<nsFrameLoader> frameLoader = she->GetFrameLoader();
|
||||
if (canonicalBC->Group()->Toplevels().Length() == 1 && frameLoader &&
|
||||
(!currentShe || she->SharedInfo() != currentShe->SharedInfo())) {
|
||||
nsTArray<RefPtr<PContentParent::CanSavePresentationPromise>>
|
||||
canSavePromises;
|
||||
canonicalBC->Group()->EachParent([&](ContentParent* aParent) {
|
||||
RefPtr<PContentParent::CanSavePresentationPromise> canSave =
|
||||
aParent->SendCanSavePresentation(canonicalBC, Nothing());
|
||||
canSavePromises.AppendElement(canSave);
|
||||
});
|
||||
|
||||
// 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);
|
||||
RemotenessChangeState state;
|
||||
canonicalBC->ReplacedBy(loadingBC->Canonical(), state);
|
||||
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);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (frameLoader) {
|
||||
she->SetFrameLoader(nullptr);
|
||||
frameLoader->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
aLoadEntry.mBrowsingContext->LoadURI(aLoadEntry.mLoadState, false);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsSHistory::LoadURIs(nsTArray<LoadEntryResult>& aLoadResults) {
|
||||
for (LoadEntryResult& loadEntry : aLoadResults) {
|
||||
loadEntry.mBrowsingContext->LoadURI(loadEntry.mLoadState, false);
|
||||
LoadURIOrBFCache(loadEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
|
|||
};
|
||||
|
||||
static void LoadURIs(nsTArray<LoadEntryResult>& aLoadResults);
|
||||
static void LoadURIOrBFCache(LoadEntryResult& aLoadEntry);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
#include "mozilla/StaticPrefs_browser.h"
|
||||
#include "mozilla/StaticPrefs_docshell.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_fission.h"
|
||||
#include "mozilla/StaticPrefs_full_screen_api.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
|
@ -10784,6 +10785,7 @@ bool Document::CanSavePresentation(nsIRequest* aNewRequest,
|
|||
}
|
||||
}
|
||||
|
||||
if (!StaticPrefs::fission_bfcacheInParent()) {
|
||||
// BFCache is currently not compatible with remote subframes (bug 1609324)
|
||||
if (RefPtr<BrowsingContext> browsingContext = GetBrowsingContext()) {
|
||||
for (auto& child : browsingContext->Children()) {
|
||||
|
@ -10794,6 +10796,7 @@ bool Document::CanSavePresentation(nsIRequest* aNewRequest,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (win) {
|
||||
auto* globalWindow = nsGlobalWindowInner::Cast(win);
|
||||
|
|
|
@ -193,12 +193,17 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
mWillChangeProcess(false),
|
||||
mObservingOwnerContent(false),
|
||||
mTabProcessCrashFired(false),
|
||||
mNotifyingCrash(false) {}
|
||||
mNotifyingCrash(false) {
|
||||
nsCOMPtr<nsFrameLoaderOwner> owner = do_QueryInterface(aOwner);
|
||||
owner->AttachFrameLoader(this);
|
||||
}
|
||||
|
||||
nsFrameLoader::~nsFrameLoader() {
|
||||
if (mMessageManager) {
|
||||
mMessageManager->Disconnect();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mOwnerContent);
|
||||
MOZ_RELEASE_ASSERT(mDestroyCalled);
|
||||
}
|
||||
|
||||
|
@ -1870,6 +1875,9 @@ void nsFrameLoader::StartDestroy(bool aForProcessSwitch) {
|
|||
!doc->InUnlinkOrDeletion();
|
||||
doc->SetSubDocumentFor(mOwnerContent, nullptr);
|
||||
MaybeUpdatePrimaryBrowserParent(eBrowserParentRemoved);
|
||||
|
||||
nsCOMPtr<nsFrameLoaderOwner> owner = do_QueryInterface(mOwnerContent);
|
||||
owner->FrameLoaderDestroying(this);
|
||||
SetOwnerContent(nullptr);
|
||||
}
|
||||
|
||||
|
@ -2057,8 +2065,17 @@ void nsFrameLoader::SetOwnerContent(Element* aContent) {
|
|||
mObservingOwnerContent = false;
|
||||
mOwnerContent->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
if (RefPtr<nsFrameLoaderOwner> owner = do_QueryObject(mOwnerContent)) {
|
||||
owner->DeattachFrameLoader(this);
|
||||
}
|
||||
|
||||
mOwnerContent = aContent;
|
||||
|
||||
if (RefPtr<nsFrameLoaderOwner> owner = do_QueryObject(mOwnerContent)) {
|
||||
owner->AttachFrameLoader(this);
|
||||
}
|
||||
|
||||
if (mSessionStoreListener && mOwnerContent) {
|
||||
// mOwnerContent will only be null when the frame loader is being destroyed,
|
||||
// so the session store listener will be destroyed along with it.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
|
@ -98,7 +99,8 @@ typedef struct _GtkWidget GtkWidget;
|
|||
|
||||
class nsFrameLoader final : public nsStubMutationObserver,
|
||||
public mozilla::dom::ipc::MessageManagerCallback,
|
||||
public nsWrapperCache {
|
||||
public nsWrapperCache,
|
||||
public mozilla::LinkedListElement<nsFrameLoader> {
|
||||
friend class AutoResetInShow;
|
||||
friend class AutoResetInFrameSwap;
|
||||
friend class nsFrameLoaderOwner;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/FrameLoaderBinding.h"
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "mozilla/StaticPrefs_fission.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
|
||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -126,16 +129,37 @@ void nsFrameLoaderOwner::ChangeRemotenessCommon(
|
|||
// or want, so we use the initial (possibly pending) browsing context
|
||||
// directly, instead.
|
||||
bc = mFrameLoader->GetMaybePendingBrowsingContext();
|
||||
networkCreated = mFrameLoader->IsNetworkCreated();
|
||||
|
||||
MOZ_ASSERT_IF(aState.mTryUseBFCache, aState.mReplaceBrowsingContext);
|
||||
if (aState.mTryUseBFCache) {
|
||||
if (bc) {
|
||||
SessionHistoryEntry* she =
|
||||
bc->Canonical()->GetActiveSessionHistoryEntry();
|
||||
if (she) {
|
||||
MOZ_LOG(
|
||||
gSHIPBFCacheLog, LogLevel::Debug,
|
||||
("nsFrameLoaderOwner::ChangeRemotenessCommon: store the old "
|
||||
"page in bfcache"));
|
||||
Unused << bc->SetIsInBFCache(true);
|
||||
she->SetFrameLoader(mFrameLoader);
|
||||
// Session history owns now the frameloader.
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mFrameLoader) {
|
||||
if (aContextType == ChangeRemotenessContextType::PRESERVE) {
|
||||
mFrameLoader->SetWillChangeProcess();
|
||||
}
|
||||
|
||||
// Preserve the networkCreated status, as nsDocShells created after a
|
||||
// process swap may shouldn't change their dynamically-created status.
|
||||
networkCreated = mFrameLoader->IsNetworkCreated();
|
||||
mFrameLoader->Destroy(aSwitchingInProgressLoad);
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
mFrameLoader = nsFrameLoader::Recreate(
|
||||
owner, bc, aGroup, aState, aIsRemote, networkCreated,
|
||||
|
@ -154,34 +178,38 @@ void nsFrameLoaderOwner::ChangeRemotenessCommon(
|
|||
}
|
||||
}
|
||||
|
||||
ChangeFrameLoaderCommon(owner);
|
||||
}
|
||||
|
||||
void nsFrameLoaderOwner::ChangeFrameLoaderCommon(Element* aOwner) {
|
||||
// Now that we've got a new FrameLoader, we need to reset our
|
||||
// nsSubDocumentFrame to use the new FrameLoader.
|
||||
if (nsSubDocumentFrame* ourFrame = do_QueryFrame(owner->GetPrimaryFrame())) {
|
||||
if (nsSubDocumentFrame* ourFrame = do_QueryFrame(aOwner->GetPrimaryFrame())) {
|
||||
ourFrame->ResetFrameLoader();
|
||||
}
|
||||
|
||||
// If the element is focused, or the current mouse over target then
|
||||
// we need to update that state for the new BrowserParent too.
|
||||
if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
|
||||
if (fm->GetFocusedElement() == owner) {
|
||||
fm->ActivateRemoteFrameIfNeeded(*owner,
|
||||
if (fm->GetFocusedElement() == aOwner) {
|
||||
fm->ActivateRemoteFrameIfNeeded(*aOwner,
|
||||
nsFocusManager::GenerateFocusActionId());
|
||||
}
|
||||
}
|
||||
|
||||
if (owner->GetPrimaryFrame()) {
|
||||
if (aOwner->GetPrimaryFrame()) {
|
||||
EventStateManager* eventManager =
|
||||
owner->GetPrimaryFrame()->PresContext()->EventStateManager();
|
||||
eventManager->RecomputeMouseEnterStateForRemoteFrame(*owner);
|
||||
aOwner->GetPrimaryFrame()->PresContext()->EventStateManager();
|
||||
eventManager->RecomputeMouseEnterStateForRemoteFrame(*aOwner);
|
||||
}
|
||||
|
||||
if (owner->IsXULElement()) {
|
||||
if (aOwner->IsXULElement()) {
|
||||
// Assuming this element is a XULFrameElement, once we've reset our
|
||||
// FrameLoader, fire an event to act like we've recreated ourselves, similar
|
||||
// to what XULFrameElement does after rebinding to the tree.
|
||||
// ChromeOnlyDispatch is turns on to make sure this isn't fired into
|
||||
// content.
|
||||
(new mozilla::AsyncEventDispatcher(owner, u"XULFrameLoaderCreated"_ns,
|
||||
(new mozilla::AsyncEventDispatcher(aOwner, u"XULFrameLoaderCreated"_ns,
|
||||
mozilla::CanBubble::eYes,
|
||||
mozilla::ChromeOnlyDispatch::eYes))
|
||||
->RunDOMEventWhenSafe();
|
||||
|
@ -283,3 +311,42 @@ void nsFrameLoaderOwner::SubframeCrashed() {
|
|||
/* inProgress */ false, /* isRemote */ false,
|
||||
/* group */ nullptr, frameLoaderInit, IgnoreErrors());
|
||||
}
|
||||
|
||||
void nsFrameLoaderOwner::ReplaceFrameLoader(nsFrameLoader* aNewFrameLoader) {
|
||||
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
|
||||
("nsFrameLoaderOwner::ReplaceFrameLoader: Replace frameloader"));
|
||||
|
||||
mFrameLoader = aNewFrameLoader;
|
||||
|
||||
if (auto* browserParent = mFrameLoader->GetBrowserParent()) {
|
||||
browserParent->AddWindowListeners();
|
||||
browserParent->ResumeProgressEvents();
|
||||
}
|
||||
|
||||
RefPtr<Element> owner = do_QueryObject(this);
|
||||
ChangeFrameLoaderCommon(owner);
|
||||
}
|
||||
|
||||
void nsFrameLoaderOwner::AttachFrameLoader(nsFrameLoader* aFrameLoader) {
|
||||
mFrameLoaderList.insertBack(aFrameLoader);
|
||||
}
|
||||
|
||||
void nsFrameLoaderOwner::DeattachFrameLoader(nsFrameLoader* aFrameLoader) {
|
||||
if (aFrameLoader->isInList()) {
|
||||
MOZ_ASSERT(mFrameLoaderList.contains(aFrameLoader));
|
||||
aFrameLoader->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void nsFrameLoaderOwner::FrameLoaderDestroying(nsFrameLoader* aFrameLoader) {
|
||||
if (aFrameLoader == mFrameLoader) {
|
||||
while (!mFrameLoaderList.isEmpty()) {
|
||||
RefPtr<nsFrameLoader> loader = mFrameLoaderList.popFirst();
|
||||
if (loader != mFrameLoader) {
|
||||
loader->Destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DeattachFrameLoader(aFrameLoader);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class BrowsingContext;
|
|||
class BrowsingContextGroup;
|
||||
class BrowserBridgeChild;
|
||||
class ContentParent;
|
||||
class Element;
|
||||
struct RemotenessOptions;
|
||||
struct RemotenessChangeState;
|
||||
} // namespace dom
|
||||
|
@ -79,6 +80,12 @@ class nsFrameLoaderOwner : public nsISupports {
|
|||
|
||||
void SubframeCrashed();
|
||||
|
||||
void ReplaceFrameLoader(nsFrameLoader* aNewFrameLoader);
|
||||
|
||||
void AttachFrameLoader(nsFrameLoader* aFrameLoader);
|
||||
void DeattachFrameLoader(nsFrameLoader* aFrameLoader);
|
||||
void FrameLoaderDestroying(nsFrameLoader* aFrameLoader);
|
||||
|
||||
private:
|
||||
bool UseRemoteSubframes();
|
||||
|
||||
|
@ -102,9 +109,13 @@ class nsFrameLoaderOwner : public nsISupports {
|
|||
std::function<void()>& aFrameLoaderInit,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void ChangeFrameLoaderCommon(mozilla::dom::Element* aOwner);
|
||||
|
||||
protected:
|
||||
virtual ~nsFrameLoaderOwner() = default;
|
||||
RefPtr<nsFrameLoader> mFrameLoader;
|
||||
|
||||
mozilla::LinkedList<nsFrameLoader> mFrameLoaderList;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsFrameLoaderOwner, NS_FRAMELOADEROWNER_IID)
|
||||
|
|
|
@ -710,6 +710,7 @@ class BrowserParent final : public PBrowserParent,
|
|||
// Suspend nsIWebProgressListener events. This is used to block any further
|
||||
// progress events from the old process when process switching away.
|
||||
void SuspendProgressEvents() { mSuspendedProgressEvents = true; }
|
||||
void ResumeProgressEvents() { mSuspendedProgressEvents = false; }
|
||||
|
||||
bool CanCancelContentJS(nsIRemoteTab::NavigationType aNavigationType,
|
||||
int32_t aNavigationIndex,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "mozilla/Components.h"
|
||||
#include "mozilla/HangDetails.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/MemoryTelemetry.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
|
@ -108,6 +109,7 @@
|
|||
#include "mozilla/media/MediaChild.h"
|
||||
#include "mozilla/net/CaptivePortalService.h"
|
||||
#include "mozilla/net/CookieServiceChild.h"
|
||||
#include "mozilla/net/DocumentChannelChild.h"
|
||||
#include "mozilla/net/HttpChannelChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
|
@ -120,7 +122,9 @@
|
|||
#include "nsFocusManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIInputStreamChannel.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIOpenWindowInfo.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIURIMutator.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
@ -290,6 +294,8 @@
|
|||
# include "mozilla/CodeCoverageHandler.h"
|
||||
#endif
|
||||
|
||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::ipc;
|
||||
|
@ -4242,6 +4248,69 @@ mozilla::ipc::IPCResult ContentChild::RecvDispatchBeforeUnloadToSubtree(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvCanSavePresentation(
|
||||
const MaybeDiscarded<BrowsingContext>& aTopLevelContext,
|
||||
Maybe<uint64_t> aDocumentChannelId,
|
||||
CanSavePresentationResolver&& aResolver) {
|
||||
if (aTopLevelContext.IsNullOrDiscarded()) {
|
||||
aResolver(false);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool canSave = true;
|
||||
// XXXBFCache pass the flags to telemetry.
|
||||
uint16_t flags = 0;
|
||||
BrowsingContext* browsingContext = aTopLevelContext.get();
|
||||
browsingContext->PreOrderWalk([&](BrowsingContext* aContext) {
|
||||
nsIDocShell* docShell = aContext->GetDocShell();
|
||||
if (docShell) {
|
||||
Document* doc = docShell->GetDocument();
|
||||
if (doc) {
|
||||
nsIRequest* request = nullptr;
|
||||
if (aDocumentChannelId.isSome() && aContext->IsTop()) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
if (loadGroup) {
|
||||
nsCOMPtr<nsISimpleEnumerator> requests;
|
||||
loadGroup->GetRequests(getter_AddRefs(requests));
|
||||
bool hasMore = false;
|
||||
if (NS_SUCCEEDED(requests->HasMoreElements(&hasMore)) && hasMore) {
|
||||
// If there is any requests, the only one we allow with bfcache
|
||||
// is the DocumentChannel request.
|
||||
nsCOMPtr<nsISupports> elem;
|
||||
requests->GetNext(getter_AddRefs(elem));
|
||||
nsCOMPtr<nsIIdentChannel> identChannel = do_QueryInterface(elem);
|
||||
if (identChannel &&
|
||||
identChannel->ChannelId() == aDocumentChannelId.value()) {
|
||||
request = identChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Go through also the subdocuments so that flags are collected.
|
||||
bool canSaveDoc = doc->CanSavePresentation(request, flags, false);
|
||||
canSave = canSaveDoc && canSave;
|
||||
|
||||
if (MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Debug)) {
|
||||
nsAutoCString uri;
|
||||
if (doc->GetDocumentURI()) {
|
||||
uri = doc->GetDocumentURI()->GetSpecOrDefault();
|
||||
}
|
||||
|
||||
MOZ_LOG(
|
||||
gSHIPBFCacheLog, LogLevel::Debug,
|
||||
("ContentChild::RecvCanSavePresentation can save presentation "
|
||||
"[%i] for [%s]",
|
||||
canSaveDoc, uri.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
aResolver(canSave);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
/* static */ void ContentChild::DispatchBeforeUnloadToSubtree(
|
||||
BrowsingContext* aStartingAt,
|
||||
const DispatchBeforeUnloadToSubtreeResolver& aResolver) {
|
||||
|
|
|
@ -824,6 +824,11 @@ class ContentChild final : public PContentChild,
|
|||
const MaybeDiscarded<BrowsingContext>& aStartingAt,
|
||||
DispatchBeforeUnloadToSubtreeResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCanSavePresentation(
|
||||
const MaybeDiscarded<BrowsingContext>& aTopLevelContext,
|
||||
Maybe<uint64_t> aDocumentChannelId,
|
||||
CanSavePresentationResolver&& aResolve);
|
||||
|
||||
public:
|
||||
static void DispatchBeforeUnloadToSubtree(
|
||||
BrowsingContext* aStartingAt,
|
||||
|
|
|
@ -9,6 +9,7 @@ include protocol PBrowser;
|
|||
include protocol PCompositorManager;
|
||||
include protocol PContentPermissionRequest;
|
||||
include protocol PCycleCollectWithLogs;
|
||||
include protocol PDocumentChannel;
|
||||
include protocol PExternalHelperApp;
|
||||
include protocol PHandlerService;
|
||||
include protocol PFileDescriptorSet;
|
||||
|
@ -945,6 +946,9 @@ child:
|
|||
async DispatchBeforeUnloadToSubtree(MaybeDiscardedBrowsingContext aStartingAt)
|
||||
returns (PermitUnloadResult result);
|
||||
|
||||
async CanSavePresentation(MaybeDiscardedBrowsingContext aTopLevelContext,
|
||||
uint64_t? aDocumentChannelId) returns (bool success);
|
||||
|
||||
// Update the cached list of codec supported in the given process.
|
||||
async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/net/HttpBaseChannel.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/StaticPrefs_fission.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
|
@ -174,7 +175,14 @@ IPCResult DocumentChannelChild::RecvDisconnectChildListeners(
|
|||
// notify them of the failure. If this is a process switch, then we can just
|
||||
// ignore it silently, and trust that the switch will shut down our docshell
|
||||
// and cancel us when it's ready.
|
||||
if (!aSwitchedProcess) {
|
||||
// XXXBFCache This should be fixed in some better way.
|
||||
bool disconnectChildListeners = !aSwitchedProcess;
|
||||
if (!disconnectChildListeners && StaticPrefs::fission_bfcacheInParent()) {
|
||||
nsDocShell* shell = GetDocShell();
|
||||
disconnectChildListeners = shell && shell->GetBrowsingContext() &&
|
||||
shell->GetBrowsingContext()->IsTop();
|
||||
}
|
||||
if (disconnectChildListeners) {
|
||||
DisconnectChildListeners(aStatus, aLoadGroupStatus);
|
||||
}
|
||||
return IPC_OK();
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "nsQueryObject.h"
|
||||
#include "nsRedirectHistoryEntry.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsSHistory.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsURILoader.h"
|
||||
#include "nsWebNavigationInfo.h"
|
||||
|
@ -64,6 +65,8 @@
|
|||
mozilla::LazyLogModule gDocumentChannelLog("DocumentChannel");
|
||||
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
|
||||
|
||||
extern mozilla::LazyLogModule gSHIPBFCacheLog;
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -1623,6 +1626,18 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
changeState.mReplaceBrowsingContext = true;
|
||||
}
|
||||
|
||||
if (mozilla::SessionHistoryInParent() &&
|
||||
StaticPrefs::fission_bfcacheInParent() &&
|
||||
nsSHistory::GetMaxTotalViewers() > 0 && !parentWindow &&
|
||||
!browsingContext->HadOriginalOpener() &&
|
||||
browsingContext->Group()->Toplevels().Length() == 1 &&
|
||||
!changeState.mRemoteType.IsEmpty() &&
|
||||
browsingContext->GetHasLoadedNonInitialDocument() &&
|
||||
mLoadStateLoadType != LOAD_ERROR_PAGE) {
|
||||
changeState.mReplaceBrowsingContext = true;
|
||||
changeState.mTryUseBFCache = true;
|
||||
}
|
||||
|
||||
LOG(("GetRemoteTypeForPrincipal -> current:%s remoteType:%s",
|
||||
currentRemoteType.get(), changeState.mRemoteType.get()));
|
||||
|
||||
|
@ -1644,6 +1659,44 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
// If we're doing a document load, we can immediately perform a process
|
||||
// switch.
|
||||
if (mIsDocumentLoad) {
|
||||
if (changeState.mTryUseBFCache && wgp) {
|
||||
if (RefPtr<BrowserParent> browserParent = wgp->GetBrowserParent()) {
|
||||
nsTArray<RefPtr<PContentParent::CanSavePresentationPromise>>
|
||||
canSavePromises;
|
||||
browsingContext->Group()->EachParent([&](ContentParent* aParent) {
|
||||
RefPtr<PContentParent::CanSavePresentationPromise> canSave =
|
||||
aParent->SendCanSavePresentation(browsingContext,
|
||||
mDocumentChannelId);
|
||||
canSavePromises.AppendElement(canSave);
|
||||
});
|
||||
|
||||
PContentParent::CanSavePresentationPromise::All(
|
||||
GetCurrentSerialEventTarget(), canSavePromises)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr{this}, browsingContext,
|
||||
changeState](const nsTArray<bool> aCanSaves) mutable {
|
||||
bool canSave = !aCanSaves.Contains(false);
|
||||
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
|
||||
("DocumentLoadListener::MaybeTriggerProcessSwitch "
|
||||
"saving presentation=%i",
|
||||
canSave));
|
||||
changeState.mTryUseBFCache = canSave;
|
||||
self->TriggerProcessSwitch(browsingContext, changeState);
|
||||
},
|
||||
[self = RefPtr{this}, browsingContext,
|
||||
changeState](ipc::ResponseRejectReason) mutable {
|
||||
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
|
||||
("DocumentLoadListener::MaybeTriggerProcessSwitch "
|
||||
"error in trying to save presentation"));
|
||||
changeState.mTryUseBFCache = false;
|
||||
self->TriggerProcessSwitch(browsingContext, changeState);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
changeState.mTryUseBFCache = false;
|
||||
TriggerProcessSwitch(browsingContext, changeState);
|
||||
return true;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче