Bug 689366: Don't ask our frame loader for its layer manager after Destroy(). r=bz a=LegNeato
--- 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