Bug 673984 - Fix crash in nsImageLoader::DoRedraw by clearing image loaders even on ignore of frame destruction callbacks. [r=dbaron,dholbert]
authorScott Johnson <sjohnson@mozilla.com>
Mon, 15 Aug 2011 11:44:15 -0700
changeset 75322 f9be98f4a042f3f6a6e8779d3f61ff314bb551e9
parent 75321 485f0838da930c169ee790875405dfc0760b754e
child 75323 edd7aab15b8b902f77ef4a3910e9a1db5c512404
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersdbaron, dholbert
bugs673984
milestone8.0a1
Bug 673984 - Fix crash in nsImageLoader::DoRedraw by clearing image loaders even on ignore of frame destruction callbacks. [r=dbaron,dholbert]
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1054,37 +1054,40 @@ nsPresContext::SetShell(nsIPresShell* aS
       }
 
       if (mLangService) {
         doc->AddCharSetObserver(this);
         UpdateCharSet(doc->GetDocumentCharacterSet());
       }
     }
   } else {
-    // Destroy image loaders now that the presshell is going away.
-    // This is important since imageloaders can have pointers to frames and
-    // we don't want those pointers to outlive the destruction of the frame
-    // arena.
-    for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i) {
-      mImageLoaders[i].Enumerate(destroy_loads, nsnull);
-      mImageLoaders[i].Clear();
-    }
-
     if (mTransitionManager) {
       mTransitionManager->Disconnect();
       mTransitionManager = nsnull;
     }
     if (mAnimationManager) {
       mAnimationManager->Disconnect();
       mAnimationManager = nsnull;
     }
   }
 }
 
 void
+nsPresContext::DestroyImageLoaders()
+{
+  // Destroy image loaders. This is important to do when frames are being
+  // destroyed because imageloaders can have pointers to frames and we don't
+  // want those pointers to outlive the destruction of the frame arena.
+  for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i) {
+    mImageLoaders[i].Enumerate(destroy_loads, nsnull);
+    mImageLoaders[i].Clear();
+  }
+}
+
+void
 nsPresContext::UpdateCharSet(const nsAFlatCString& aCharSet)
 {
   if (mLangService) {
     NS_IF_RELEASE(mLanguage);
     mLanguage = mLangService->LookupCharSet(aCharSet.get()).get();  // addrefs
     // this will be a language group (or script) code rather than a true language code
 
     // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -967,16 +967,18 @@ public:
   }
 
   void NotifyDestroyingFrame(nsIFrame* aFrame)
   {
     PropertyTable()->DeleteAllFor(aFrame);
   }
   inline void ForgetUpdatePluginGeometryFrame(nsIFrame* aFrame);
 
+  void DestroyImageLoaders();
+
   PRBool GetContainsUpdatePluginGeometryFrame()
   {
     return mContainsUpdatePluginGeometryFrame;
   }
 
   void SetContainsUpdatePluginGeometryFrame(PRBool aValue)
   {
     mContainsUpdatePluginGeometryFrame = aValue;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2981,16 +2981,22 @@ PresShell::FireResizeEvent()
     nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
     mInResize = PR_FALSE;
   }
 }
 
 void
 PresShell::SetIgnoreFrameDestruction(PRBool aIgnore)
 {
+  if (mPresContext) {
+    // We need to destroy the image loaders first, as they won't be
+    // notified when frames are destroyed once this setting takes effect.
+    // (See bug 673984)
+    mPresContext->DestroyImageLoaders();
+  }
   mIgnoreFrameDestruction = aIgnore;
 }
 
 void
 PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
 {
   NS_TIME_FUNCTION_MIN(1.0);