Bug 689366: Don't ask our frame loader for its layer manager after Destroy(). r=bz a=LegNeato
authorChris Jones <jones.chris.g@gmail.com>
Mon, 26 Sep 2011 23:47:45 -0700
changeset 78827 c9155f2b618f531720bc8cfbd37cd6174f3dc258
parent 78826 a6f988cf41113facae9a46cf9a874c70136de46a
child 78828 51d973c83798caa2f7d54af54ca3fc4ee563800c
push idunknown
push userunknown
push dateunknown
reviewersbz, LegNeato
bugs689366
milestone9.0a2
Bug 689366: Don't ask our frame loader for its layer manager after Destroy(). r=bz a=LegNeato
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -558,16 +558,17 @@ BuildBackgroundPatternFor(ContainerLayer
   bgRgn.MoveBy(-translation);
   layer->SetVisibleRegion(bgRgn);
 
   aContainer->InsertAfter(layer, nsnull);
 }
 
 RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader)
   : mFrameLoader(aFrameLoader)
+  , mFrameLoaderDestroyed(false)
 {
   if (aFrameLoader) {
     mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
       new nsContentView(aFrameLoader, FrameMetrics::ROOT_SCROLL_ID);
   }
 }
 
 RenderFrameParent::~RenderFrameParent()
@@ -580,16 +581,18 @@ RenderFrameParent::Destroy()
   NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
                     "render frame must only have 0 or 1 layer manager");
 
   if (numChildren) {
     ShadowLayersParent* layers =
       static_cast<ShadowLayersParent*>(ManagedPLayersParent()[0]);
     layers->Destroy();
   }
+
+  mFrameLoaderDestroyed = true;
 }
 
 nsContentView*
 RenderFrameParent::GetContentView(ViewID aId)
 {
   return FindViewForId(mContentViews, aId);
 }
 
@@ -718,17 +721,17 @@ RenderFrameParent::ActorDestroy(ActorDes
     mFrameLoader->SetCurrentRemoteFrame(nsnull);
   }
   mFrameLoader = nsnull;
 }
 
 PLayersParent*
 RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
 {
-  if (!mFrameLoader) {
+  if (!mFrameLoader || mFrameLoaderDestroyed) {
     *aBackendType = LayerManager::LAYERS_NONE;
     return nsnull;
   }
   LayerManager* lm = GetLayerManager();
   ShadowLayerManager* slm = lm->AsShadowManager();
   if (!slm) {
     *aBackendType = LayerManager::LAYERS_NONE;
      return nsnull;
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -112,16 +112,32 @@ private:
   ContainerLayer* GetRootLayer() const;
 
   nsRefPtr<nsFrameLoader> mFrameLoader;
   nsRefPtr<ContainerLayer> mContainer;
 
   // This contains the views for all the scrollable frames currently in the
   // painted region of our remote content.
   ViewMap mContentViews;
+
+  // True after Destroy() has been called, which is triggered
+  // originally by nsFrameLoader::Destroy().  After this point, we can
+  // no longer safely ask the frame loader to find its nearest layer
+  // manager, because it may have been disconnected from the DOM.
+  // It's still OK to *tell* the frame loader that we've painted after
+  // it's destroyed; it'll just ignore us, and we won't be able to
+  // find an nsIFrame to invalidate.  See ShadowLayersUpdated().
+  //
+  // Prefer the extra bit of state to null'ing out mFrameLoader in
+  // Destroy() so that less code needs to be special-cased for after
+  // Destroy().
+  // 
+  // It's possible for mFrameLoader==null and
+  // mFrameLoaderDestroyed==false.
+  bool mFrameLoaderDestroyed;
 };
 
 } // namespace layout
 } // namespace mozilla
 
 /**
  * A DisplayRemote exists solely to graft a child process's shadow
  * layer tree (for a given RenderFrameParent) into its parent