From 5b75fd5effccf0af68b7ba8dd54ccaec505e0a00 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 6 Dec 2012 15:21:18 -0500 Subject: [PATCH] Bug 818371. Don't fire visibility change events until we're done updating vsibility states in the entire docshell tree. r=smaug --- content/base/public/nsIDocument.h | 8 +++-- content/base/src/nsDocument.cpp | 44 ++++++++++++++----------- content/base/src/nsDocument.h | 7 ++-- docshell/base/nsDocShell.cpp | 2 +- docshell/test/chrome/Makefile.in | 1 + docshell/test/chrome/test_bug818371.xul | 43 ++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 29 deletions(-) create mode 100644 docshell/test/chrome/test_bug818371.xul diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index d26f7485d38ac..7a25e62eff551 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -79,8 +79,8 @@ class Element; } // namespace mozilla #define NS_IDOCUMENT_IID \ -{ 0xd69b94c2, 0x92ed, 0x4baa, \ - { 0x82, 0x08, 0x56, 0xe4, 0xc4, 0xb3, 0xf3, 0xc8 } } +{ 0xcc604bdc, 0xd55e, 0x4918, \ + { 0xaa, 0x82, 0xb2, 0xde, 0xbf, 0x01, 0x09, 0x5d } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -1669,7 +1669,9 @@ class nsIDocument : public nsINode #undef DEPRECATED_OPERATION void WarnOnceAbout(DeprecatedOperations aOperation, bool asError = false); - virtual void PostVisibilityUpdateEvent() = 0; + // This method may fire a DOM event; if it does so it will happen + // synchronously if aFireEventSync is true, asynchronously otherwise. + virtual void UpdateVisibilityState(bool aFireEventSync) = 0; bool IsSyntheticDocument() { return mIsSyntheticDocument; } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 2205dbf10e2c9..f8670a7803bec 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -7063,7 +7063,7 @@ nsDocument::OnPageShow(bool aPersisted, SetImagesNeedAnimating(true); } - UpdateVisibilityState(); + UpdateVisibilityState(true); nsCOMPtr target = aDispatchStartTarget; if (!target) { @@ -7125,7 +7125,7 @@ nsDocument::OnPageHide(bool aPersisted, mVisible = false; - UpdateVisibilityState(); + UpdateVisibilityState(true); EnumerateExternalResources(NotifyPageHide, &aPersisted); EnumerateFreezableElements(NotifyActivityChanged, nullptr); @@ -9482,25 +9482,37 @@ nsDocument::GetMozPointerLockElement(nsIDOMElement** aPointerLockedElement) #undef TOUCH_EVENT #undef EVENT -void -nsDocument::UpdateVisibilityState() +/* virtual */ void +nsDocument::UpdateVisibilityState(bool aFireEventSync) { VisibilityState oldState = mVisibilityState; mVisibilityState = GetVisibilityState(); if (oldState != mVisibilityState) { - nsContentUtils::DispatchTrustedEvent(this, static_cast(this), - NS_LITERAL_STRING("visibilitychange"), - /* bubbles = */ true, - /* cancelable = */ false); - nsContentUtils::DispatchTrustedEvent(this, static_cast(this), - NS_LITERAL_STRING("mozvisibilitychange"), - /* bubbles = */ true, - /* cancelable = */ false); + if (aFireEventSync) { + FireVisibilityChangeEvent(); + } else { + nsCOMPtr event = + NS_NewRunnableMethod(this, &nsDocument::FireVisibilityChangeEvent); + NS_DispatchToMainThread(event); + } EnumerateFreezableElements(NotifyActivityChanged, nullptr); } } +void +nsDocument::FireVisibilityChangeEvent() +{ + nsContentUtils::DispatchTrustedEvent(this, static_cast(this), + NS_LITERAL_STRING("visibilitychange"), + /* bubbles = */ true, + /* cancelable = */ false); + nsContentUtils::DispatchTrustedEvent(this, static_cast(this), + NS_LITERAL_STRING("mozvisibilitychange"), + /* bubbles = */ true, + /* cancelable = */ false); +} + nsDocument::VisibilityState nsDocument::GetVisibilityState() const { @@ -9519,14 +9531,6 @@ nsDocument::GetVisibilityState() const return eVisible; } -/* virtual */ void -nsDocument::PostVisibilityUpdateEvent() -{ - nsCOMPtr event = - NS_NewRunnableMethod(this, &nsDocument::UpdateVisibilityState); - NS_DispatchToMainThread(event); -} - NS_IMETHODIMP nsDocument::GetMozHidden(bool* aHidden) { diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 4c4cb78cdb4a3..b0d4ecd658ff9 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -995,11 +995,8 @@ class nsDocument : public nsIDocument, bool SetPointerLock(Element* aElement, int aCursorStyle); static void UnlockPointer(); - // This method may fire a DOM event; if it does so it will happen - // synchronously. - void UpdateVisibilityState(); - // Posts an event to call UpdateVisibilityState - virtual void PostVisibilityUpdateEvent(); + virtual void UpdateVisibilityState(bool aFireEventSync); + void FireVisibilityChangeEvent(); virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const; // DocSizeOfIncludingThis is inherited from nsIDocument. diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 3301fd14c8cb5..2c58d328f6ada 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -5211,7 +5211,7 @@ nsDocShell::SetIsActive(bool aIsActive) win->SetIsBackground(!aIsActive); nsCOMPtr doc = do_QueryInterface(win->GetExtantDocument()); if (doc) { - doc->PostVisibilityUpdateEvent(); + doc->UpdateVisibilityState(false); } } diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in index d3625655117e2..1d36a4747923c 100644 --- a/docshell/test/chrome/Makefile.in +++ b/docshell/test/chrome/Makefile.in @@ -96,6 +96,7 @@ MOCHITEST_CHROME_FILES = \ test_bug789773.xul \ test_bug754029.xul \ bug754029_window.xul \ + test_bug818371.xul \ docshell_helpers.js \ generic.html \ $(NULL) diff --git a/docshell/test/chrome/test_bug818371.xul b/docshell/test/chrome/test_bug818371.xul new file mode 100644 index 0000000000000..31ebd71686d72 --- /dev/null +++ b/docshell/test/chrome/test_bug818371.xul @@ -0,0 +1,43 @@ + + + + + + +