summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-05-29 15:44:30 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-22 10:31:53 +0000
commit2dfc0de16e1edb49bcef1d327c4b6a11bc6f4a83 (patch)
tree8050e323d043bcedd2da190e13799b73bbc91950
parent6801ec34b32444aa6a19c84488a43a150f6818c7 (diff)
downloadqtwebkit-2dfc0de16e1edb49bcef1d327c4b6a11bc6f4a83.tar.gz
Crashes and asserts in subframes
When a subframe is not composited it may be painted immediately when its parent is painted. This means that if it is not laid out, it may cause asserts during painting, if we only check the parent is laid out. The patch is based on http://svn.webkit.org/repository/webkit/trunk@180063 by Simon Fraser. Task-number: QTBUG-45428 Change-Id: Ib7e283485bef68375c7b023264f79acd7490e2c5 Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
-rw-r--r--Source/WebCore/page/FrameView.cpp37
-rw-r--r--Source/WebCore/page/FrameView.h2
2 files changed, 33 insertions, 6 deletions
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index 56698c73b..abf82bc64 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -925,7 +925,7 @@ bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
// If we sync compositing layers when a layout is pending, we may cause painting of compositing
// layer content to occur before layout has happened, which will cause paintContents() to bail.
- if (needsLayout())
+ if (needsStyleRecalcOrLayout())
return false;
// If we sync compositing layers and allow the repaint to be deferred, there is time for a
@@ -1088,7 +1088,7 @@ RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
}
-static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
+static inline void collectFrameViewChildren(const FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
{
const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
ASSERT(viewChildren);
@@ -2534,6 +2534,29 @@ bool FrameView::layoutPending() const
return m_layoutTimer.isActive();
}
+bool FrameView::needsStyleRecalcOrLayout(bool includeSubframes) const
+{
+ if (frame()->document() && frame()->document()->childNeedsStyleRecalc())
+ return true;
+
+ if (needsLayout())
+ return true;
+
+ if (!includeSubframes)
+ return false;
+
+ // Find child frames via the Widget tree, as updateLayoutAndStyleIfNeededRecursive() does.
+ Vector<RefPtr<FrameView> > childViews;
+ collectFrameViewChildren(this, childViews);
+
+ for (unsigned i = 0; i < childViews.size(); ++i) {
+ if (childViews[i]->needsStyleRecalcOrLayout())
+ return true;
+ }
+
+ return false;
+}
+
bool FrameView::needsLayout() const
{
// This can return true in cases where the document does not have a body yet.
@@ -3772,10 +3795,12 @@ void FrameView::updateLayoutAndStyleIfNeededRecursive()
// painting, so we need to flush out any deferred repaints too.
flushDeferredRepaints();
- // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame
- // needs to call layout on parent frame recursively.
- // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
- ASSERT(!needsLayout());
+ // A child frame may have dirtied us during its layout.
+ frame()->document()->updateStyleIfNeeded();
+ if (needsLayout())
+ layout();
+
+ ASSERT(!(m_frame->page() && m_frame->page()->mainFrame() == m_frame) || !needsStyleRecalcOrLayout());
}
bool FrameView::qualifiesAsVisuallyNonEmpty() const
diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h
index 24f0c2a27..b955e0964 100644
--- a/Source/WebCore/page/FrameView.h
+++ b/Source/WebCore/page/FrameView.h
@@ -115,6 +115,8 @@ public:
void setNeedsLayout();
void setViewportConstrainedObjectsNeedLayout();
+ bool needsStyleRecalcOrLayout(bool includeSubframes = true) const;
+
bool needsFullRepaint() const { return m_doFullRepaint; }
#if ENABLE(REQUEST_ANIMATION_FRAME)