Bug 1689601, nested freeze/thaw, r=peterv

Non-SHIP bfcache seems to be rather complicated here, since it needs to explicitly store inner windows and what not.
SHIP should be able to handle this in a simpler way.
It is possible that some ordering needs still tweaking.

Differential Revision: https://phabricator.services.mozilla.com/D105360
This commit is contained in:
Olli Pettay 2021-03-02 12:13:20 +00:00
Родитель 0d8dbfb17e
Коммит bba6b348ae
6 изменённых файлов: 57 добавлений и 51 удалений

Просмотреть файл

@ -1213,10 +1213,9 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
if (doc) {
if (mBrowsingContext->IsTop()) {
doc->NotifyPossibleTitleChange(false);
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
// XXXBFCache Resume doesn't go through oop iframes.
mScriptGlobal->GetCurrentInnerWindowInternal()->Thaw();
}
}
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
mScriptGlobal->GetCurrentInnerWindowInternal()->Thaw(false);
}
nsCOMPtr<nsIChannel> channel = doc->GetChannel();
if (channel) {
@ -1229,8 +1228,7 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
}
RefPtr<PresShell> presShell = GetPresShell();
if (presShell) {
// XXXBFcache Thaw doesn't deal with OOP iframes.
presShell->Thaw();
presShell->Thaw(false);
}
}
} else if (!mFiredUnloadEvent) {
@ -1239,16 +1237,12 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
mFiredUnloadEvent = true;
contentViewer->PageHide(false);
if (mBrowsingContext->IsTop()) {
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
// XXXBFCache Resume doesn't go through oop iframes.
mScriptGlobal->GetCurrentInnerWindowInternal()->Freeze();
}
if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindowInternal()) {
mScriptGlobal->GetCurrentInnerWindowInternal()->Freeze(false);
}
RefPtr<PresShell> presShell = GetPresShell();
if (presShell) {
// XXXBFcache Freeze doesn't deal with OOP iframes.
presShell->Freeze();
presShell->Freeze(false);
}
}
}

Просмотреть файл

@ -2419,11 +2419,13 @@ bool nsPIDOMWindowInner::IsSecureContext() const {
return nsGlobalWindowInner::Cast(this)->IsSecureContext();
}
void nsPIDOMWindowInner::Suspend() {
nsGlobalWindowInner::Cast(this)->Suspend();
void nsPIDOMWindowInner::Suspend(bool aIncludeSubWindows) {
nsGlobalWindowInner::Cast(this)->Suspend(aIncludeSubWindows);
}
void nsPIDOMWindowInner::Resume() { nsGlobalWindowInner::Cast(this)->Resume(); }
void nsPIDOMWindowInner::Resume(bool aIncludeSubWindows) {
nsGlobalWindowInner::Cast(this)->Resume(aIncludeSubWindows);
}
void nsPIDOMWindowInner::SyncStateFromParentWindow() {
nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
@ -5441,7 +5443,7 @@ already_AddRefed<StorageEvent> nsGlobalWindowInner::CloneStorageEvent(
return event.forget();
}
void nsGlobalWindowInner::Suspend() {
void nsGlobalWindowInner::Suspend(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
// We can only safely suspend windows that are the current inner window. If
@ -5459,7 +5461,9 @@ void nsGlobalWindowInner::Suspend() {
// All children are also suspended. This ensure mSuspendDepth is
// set properly and the timers are properly canceled for each child.
CallOnInProcessChildren(&nsGlobalWindowInner::Suspend);
if (aIncludeSubWindows) {
CallOnInProcessChildren(&nsGlobalWindowInner::Suspend, aIncludeSubWindows);
}
mSuspendDepth += 1;
if (mSuspendDepth != 1) {
@ -5491,7 +5495,7 @@ void nsGlobalWindowInner::Suspend() {
}
}
void nsGlobalWindowInner::Resume() {
void nsGlobalWindowInner::Resume(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
// We can only safely resume a window if its the current inner window. If
@ -5506,7 +5510,9 @@ void nsGlobalWindowInner::Resume() {
// Resume all children. This restores timers recursively canceled
// in Suspend() and ensures all children have the correct mSuspendDepth.
CallOnInProcessChildren(&nsGlobalWindowInner::Resume);
if (aIncludeSubWindows) {
CallOnInProcessChildren(&nsGlobalWindowInner::Resume, aIncludeSubWindows);
}
if (mSuspendDepth == 0) {
// Ignore if the window is not suspended.
@ -5556,20 +5562,23 @@ bool nsGlobalWindowInner::IsSuspended() const {
return mSuspendDepth != 0;
}
void nsGlobalWindowInner::Freeze() {
void nsGlobalWindowInner::Freeze(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
Suspend();
FreezeInternal();
Suspend(aIncludeSubWindows);
FreezeInternal(aIncludeSubWindows);
}
void nsGlobalWindowInner::FreezeInternal() {
void nsGlobalWindowInner::FreezeInternal(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
HintIsLoading(false);
CallOnInProcessChildren(&nsGlobalWindowInner::FreezeInternal);
if (aIncludeSubWindows) {
CallOnInProcessChildren(&nsGlobalWindowInner::FreezeInternal,
aIncludeSubWindows);
}
mFreezeDepth += 1;
MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
@ -5592,18 +5601,21 @@ void nsGlobalWindowInner::FreezeInternal() {
NotifyDOMWindowFrozen(this);
}
void nsGlobalWindowInner::Thaw() {
void nsGlobalWindowInner::Thaw(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
ThawInternal();
Resume();
ThawInternal(aIncludeSubWindows);
Resume(aIncludeSubWindows);
}
void nsGlobalWindowInner::ThawInternal() {
void nsGlobalWindowInner::ThawInternal(bool aIncludeSubWindows) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
CallOnInProcessChildren(&nsGlobalWindowInner::ThawInternal);
if (aIncludeSubWindows) {
CallOnInProcessChildren(&nsGlobalWindowInner::ThawInternal,
aIncludeSubWindows);
}
MOZ_ASSERT(mFreezeDepth != 0);
mFreezeDepth -= 1;

Просмотреть файл

@ -310,19 +310,19 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
nsresult PostHandleEvent(mozilla::EventChainPostVisitor& aVisitor) override;
void Suspend();
void Resume();
void Suspend(bool aIncludeSubWindows = true);
void Resume(bool aIncludeSubWindows = true);
virtual bool IsSuspended() const override;
// Calling Freeze() on a window will automatically Suspend() it. In
// addition, the window and its children are further treated as no longer
// suitable for interaction with the user. For example, it may be marked
// non-visible, cannot be focused, etc. All worker threads are also frozen
// bringing them to a complete stop. A window can have Freeze() called
// multiple times and will only thaw after a matching number of Thaw()
// calls.
void Freeze();
void Thaw();
// addition, the window and its children (if aIncludeSubWindows is true) are
// further treated as no longer suitable for interaction with the user. For
// example, it may be marked non-visible, cannot be focused, etc. All worker
// threads are also frozen bringing them to a complete stop. A window can
// have Freeze() called multiple times and will only thaw after a matching
// number of Thaw() calls.
void Freeze(bool aIncludeSubWindows = true);
void Thaw(bool aIncludeSubWindows = true);
virtual bool IsFrozen() const override;
void SyncStateFromParentWindow();
@ -1064,8 +1064,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
return (aWindow->*aMethod)(aArgs...);
}
void FreezeInternal();
void ThawInternal();
void FreezeInternal(bool aIncludeSubWindows);
void ThawInternal(bool aIncludeSubWindows);
mozilla::CallState ShouldReportForServiceWorkerScopeInternal(
const nsACString& aScope, bool* aResultOut);

Просмотреть файл

@ -297,12 +297,12 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// Calling suspend should prevent any asynchronous tasks from
// executing javascript for this window. This means setTimeout,
// requestAnimationFrame, and events should not be fired. Suspending
// a window also suspends its children and workers. Workers may
// a window maybe also suspends its children. Workers may
// continue to perform computations in the background. A window
// can have Suspend() called multiple times and will only resume after
// a matching number of Resume() calls.
void Suspend();
void Resume();
void Suspend(bool aIncludeSubWindows = true);
void Resume(bool aIncludeSubWindows = true);
// Whether or not this window was suspended by the BrowserContextGroup
bool GetWasSuspendedByGroup() const { return mWasSuspendedByGroup; }

Просмотреть файл

@ -9316,7 +9316,7 @@ static CallState FreezeSubDocument(Document& aDocument) {
return CallState::Continue;
}
void PresShell::Freeze() {
void PresShell::Freeze(bool aIncludeSubDocuments) {
mUpdateApproximateFrameVisibilityEvent.Revoke();
MaybeReleaseCapturingContent();
@ -9327,7 +9327,7 @@ void PresShell::Freeze() {
mPaintingSuppressed = true;
if (mDocument) {
if (aIncludeSubDocuments && mDocument) {
mDocument->EnumerateSubDocuments(FreezeSubDocument);
}
@ -9370,14 +9370,14 @@ void PresShell::FireOrClearDelayedEvents(bool aFireEvents) {
}
}
void PresShell::Thaw() {
void PresShell::Thaw(bool aIncludeSubDocuments) {
nsPresContext* presContext = GetPresContext();
if (presContext &&
presContext->RefreshDriver()->GetPresContext() == presContext) {
presContext->RefreshDriver()->Thaw();
}
if (mDocument) {
if (aIncludeSubDocuments && mDocument) {
mDocument->EnumerateSubDocuments([](Document& aSubDoc) {
if (PresShell* presShell = aSubDoc.GetPresShell()) {
presShell->Thaw();

Просмотреть файл

@ -743,7 +743,7 @@ class PresShell final : public nsStubDocumentObserver,
* state.
* XXX this should include image animations
*/
void Freeze();
void Freeze(bool aIncludeSubDocuments = true);
bool IsFrozen() { return mFrozen; }
/**
@ -751,7 +751,7 @@ class PresShell final : public nsStubDocumentObserver,
* presentations of subdocuments, then do a full invalidate of the content
* area.
*/
void Thaw();
void Thaw(bool aIncludeSubDocuments = true);
void FireOrClearDelayedEvents(bool aFireEvents);