Browse files

Fix crash with composited layers - DO NOT MERGE

Cherry-pick from master

When we have composited layers inside iframes/frames, the layers
hierarchy is not always up to date at the time of the layerSync()
call. If some of those layers are scheduled to be repainted, the
repaint operation will triggers the update of the composited layers
tree -- possibly resulting in the deallocation of the very same
GraphicsLayer we were painting from, and thus leading to a crash.

The fix consist in gathering all the root RenderLayer (for each
frame containing composited layers) and explicitely asking
RenderLayerCompositor to check if the composited tree needs to be
updated, before we traverse the tree to paint the elements.

bug:5695185
Change-Id: I33a00b847eb19c9aa4b68f0ac3adbe36709ed00b
  • Loading branch information...
1 parent 599c05f commit 61e0d189f2b74650bf72a6a2820f66a8b17c3d06 Nicolas Roard committed Dec 16, 2011
View
34 Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -963,11 +963,31 @@ void GraphicsLayerAndroid::syncMask()
}
}
-void GraphicsLayerAndroid::syncCompositingState()
+void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list)
{
- for (unsigned int i = 0; i < m_children.size(); i++)
- m_children[i]->syncCompositingState();
+ RenderLayer* renderLayer = renderLayerFromClient(m_client);
+ if (renderLayer) {
+ const RenderLayer* rootLayer = renderLayer->root();
+ bool found = false;
+ for (unsigned int i = 0; i < list.size(); i++) {
+ const RenderLayer* current = list[i];
+ if (current == rootLayer) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ list.append(rootLayer);
+ }
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ layer->gatherRootLayers(list);
+ }
+}
+
+void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly()
+{
updateScrollingLayers();
updateFixedPosition();
syncChildren();
@@ -977,6 +997,14 @@ void GraphicsLayerAndroid::syncCompositingState()
repaint();
}
+void GraphicsLayerAndroid::syncCompositingState()
+{
+ for (unsigned int i = 0; i < m_children.size(); i++)
+ m_children[i]->syncCompositingState();
+
+ syncCompositingStateForThisLayerOnly();
+}
+
void GraphicsLayerAndroid::notifyClientAnimationStarted()
{
for (unsigned int i = 0; i < m_children.size(); i++)
View
2 Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -116,7 +116,9 @@ class GraphicsLayerAndroid : public GraphicsLayer {
virtual void setZPosition(float);
+ void gatherRootLayers(Vector<const RenderLayer*>&);
virtual void syncCompositingState();
+ virtual void syncCompositingStateForThisLayerOnly();
void notifyClientAnimationStarted();
LayerAndroid* contentLayer() { return m_contentLayer; }
View
19 Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -37,12 +37,15 @@
#include "FrameLoader.h"
#include "FrameView.h"
#include "Geolocation.h"
+#include "GraphicsLayerAndroid.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "Icon.h"
#include "LayerAndroid.h"
#include "Page.h"
#include "PopupMenuAndroid.h"
+#include "RenderLayer.h"
+#include "RenderLayerCompositor.h"
#include "ScriptController.h"
#include "SearchPopupMenuAndroid.h"
#include "WebCoreFrameBridge.h"
@@ -64,7 +67,21 @@ static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedin
WebCore::GraphicsLayer* ChromeClientAndroid::layersSync()
{
if (m_rootGraphicsLayer && m_needsLayerSync && m_webFrame) {
- if (FrameView* frameView = m_webFrame->page()->mainFrame()->view())
+ // We may have more than one frame, so let's first update all of them
+ // (webkit may want to update the GraphicsLayer tree, and we do *not* want
+ // to find this out when we are painting, as it means we could be summarily
+ // deallocated while painting...)
+ GraphicsLayerAndroid* rootLayer = static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer);
+ Vector<const RenderLayer*> listRootLayers;
+ rootLayer->gatherRootLayers(listRootLayers);
+
+ for (unsigned int i = 0; i < listRootLayers.size(); i++) {
+ RenderLayer* layer = const_cast<RenderLayer*>(listRootLayers[i]);
+ layer->compositor()->updateCompositingLayers();
+ }
+
+ Frame* frame = m_webFrame->page()->mainFrame();
+ if (FrameView* frameView = frame->view())
frameView->syncCompositingStateIncludingSubframes();
}
m_needsLayerSync = false;

0 comments on commit 61e0d18

Please sign in to comment.