diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-05-29 15:44:30 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-06-22 10:31:53 +0000 |
commit | 2dfc0de16e1edb49bcef1d327c4b6a11bc6f4a83 (patch) | |
tree | 8050e323d043bcedd2da190e13799b73bbc91950 | |
parent | 6801ec34b32444aa6a19c84488a43a150f6818c7 (diff) | |
download | qtwebkit-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.cpp | 37 | ||||
-rw-r--r-- | Source/WebCore/page/FrameView.h | 2 |
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) |