Changeset 183788 in webkit


Ignore:
Timestamp:
May 4, 2015 8:22:35 PM (9 years ago)
Author:
Alan Bujtas
Message:

RenderWidget::setWidgetGeometry() can end up destroying *this*.
https://bugs.webkit.org/show_bug.cgi?id=144601

Reviewed by Andreas Kling.

This is a speculative fix to ensure we don't crash on an invalid *this* renderer
while flattening the current iframe.
Calling RenderWidget::setWidgetGeometry() can result in destroying the current renderer.
While it is not a issue in case of normal layout flow as widget positions are updated at post layout,
frame flattening initiates this action in the middle of layout.
This patch re-introduces refcount model for RenderWidgets so that the renderer is protected during layout
when frame flattening is in use.

  • rendering/RenderFrameBase.cpp:

(WebCore::RenderFrameBase::layoutWithFlattening): Let's be paranoid about child view.

  • rendering/RenderObject.cpp:

(WebCore::RenderObject::destroy):

  • rendering/FrameView.cpp:

(WebCore::FrameView::layout):

  • rendering/RenderView.h:
  • rendering/RenderWidget.cpp:

(WebCore::RenderWidget::~RenderWidget):

  • rendering/RenderWidget.h:

(WebCore::RenderWidget::ref):
(WebCore::RenderWidget::deref):

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r183783 r183788  
     12015-05-04  Zalan Bujtas  <zalan@apple.com>
     2
     3        RenderWidget::setWidgetGeometry() can end up destroying *this*.
     4        https://bugs.webkit.org/show_bug.cgi?id=144601
     5
     6        Reviewed by Andreas Kling.
     7
     8        This is a speculative fix to ensure we don't crash on an invalid *this* renderer
     9        while flattening the current iframe.
     10        Calling RenderWidget::setWidgetGeometry() can result in destroying the current renderer.
     11        While it is not a issue in case of normal layout flow as widget positions are updated at post layout,
     12        frame flattening initiates this action in the middle of layout.
     13        This patch re-introduces refcount model for RenderWidgets so that the renderer is protected during layout
     14        when frame flattening is in use.
     15
     16        * rendering/RenderFrameBase.cpp:
     17        (WebCore::RenderFrameBase::layoutWithFlattening): Let's be paranoid about child view.
     18        * rendering/RenderObject.cpp:
     19        (WebCore::RenderObject::destroy):
     20        * rendering/FrameView.cpp:
     21        (WebCore::FrameView::layout):
     22        * rendering/RenderView.h:
     23        * rendering/RenderWidget.cpp:
     24        (WebCore::RenderWidget::~RenderWidget):
     25        * rendering/RenderWidget.h:
     26        (WebCore::RenderWidget::ref):
     27        (WebCore::RenderWidget::deref):
     28
    1292015-05-04  Doug Russell  <d_russell@apple.com>
    230
  • trunk/Source/WebCore/page/FrameView.cpp

    r183777 r183788  
    13621362        root->view().repaintRootContents();
    13631363
     1364    root->view().releaseProtectedRenderWidgets();
     1365
    13641366    ASSERT(!root->needsLayout());
    13651367
  • trunk/Source/WebCore/rendering/RenderFrameBase.cpp

    r177259 r183788  
    5555void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
    5656{
    57     FrameView* childFrameView = childView();
    58     RenderView* childRoot = childFrameView ? childFrameView->frame().contentRenderer() : 0;
     57    view().protectRenderWidgetUntilLayoutIsDone(*this);
     58    RenderView* childRoot = childView() ? childView()->frame().contentRenderer() : 0;
    5959
    6060    if (!childRoot || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
    6161        updateWidgetPosition();
    62         if (childFrameView)
    63             childFrameView->layout();
     62        if (childView())
     63            childView()->layout();
    6464        clearNeedsLayout();
    6565        return;
     
    8484        // update again to pass the new width to the child frame
    8585        updateWidgetPosition();
    86         childFrameView->layout();
     86        if (childView())
     87            childView()->layout();
    8788    }
    8889
    89     // expand the frame by setting frame height = content height
    90     if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
    91         setHeight(std::max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
    92     if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
    93         setWidth(std::max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));
    94 
     90    if (childView()) {
     91        // expand the frame by setting frame height = content height
     92        if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
     93            setHeight(std::max<LayoutUnit>(height(), childView()->contentsHeight() + vBorder));
     94        if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
     95            setWidth(std::max<LayoutUnit>(width(), childView()->contentsWidth() + hBorder));
     96    }
    9597    updateWidgetPosition();
    9698
    97     ASSERT(!childFrameView->layoutPending());
     99    ASSERT(!childView()->layoutPending());
    98100    ASSERT(!childRoot->needsLayout());
    99101    ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChildSlow() || !childRoot->firstChild()->firstChildSlow()->needsLayout());
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r183314 r183788  
    6161#include "RenderTheme.h"
    6262#include "RenderView.h"
     63#include "RenderWidget.h"
    6364#include "SVGRenderSupport.h"
    6465#include "Settings.h"
     
    20252026
    20262027    willBeDestroyed();
     2028    if (is<RenderWidget>(*this)) {
     2029        downcast<RenderWidget>(*this).deref();
     2030        return;
     2031    }
    20272032    delete this;
    20282033}
  • trunk/Source/WebCore/rendering/RenderView.h

    r183636 r183788  
    2727#include "Region.h"
    2828#include "RenderBlockFlow.h"
     29#include "RenderWidget.h"
    2930#include "SelectionSubtreeRoot.h"
    3031#include <memory>
     
    245246    void unscheduleLazyRepaint(RenderBox&);
    246247
     248    void protectRenderWidgetUntilLayoutIsDone(RenderWidget& widget) { m_protectedRenderWidgets.append(&widget); }
     249    void releaseProtectedRenderWidgets() { m_protectedRenderWidgets.clear(); }
     250
    247251protected:
    248252    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
     
    363367
    364368    HashSet<RenderElement*> m_renderersWithPausedImageAnimation;
     369    Vector<RefPtr<RenderWidget>> m_protectedRenderWidgets;
    365370
    366371#if ENABLE(SERVICE_CONTROLS)
  • trunk/Source/WebCore/rendering/RenderWidget.cpp

    r180063 r183788  
    107107RenderWidget::~RenderWidget()
    108108{
     109    ASSERT(!m_refCount);
    109110}
    110111
  • trunk/Source/WebCore/rendering/RenderWidget.h

    r177259 r183788  
    7575    WeakPtr<RenderWidget> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
    7676
     77    void ref() { ++m_refCount; }
     78    void deref();
     79
    7780protected:
    7881    RenderWidget(HTMLFrameOwnerElement&, Ref<RenderStyle>&&);
     
    103106    RefPtr<Widget> m_widget;
    104107    IntRect m_clipRect; // The rectangle needs to remain correct after scrolling, so it is stored in content view coordinates, and not clipped to window.
     108    unsigned m_refCount { 1 };
    105109};
     110
     111inline void RenderWidget::deref()
     112{
     113    ASSERT(m_refCount);
     114    if (!--m_refCount)
     115        delete this;
     116}
    106117
    107118} // namespace WebCore
Note: See TracChangeset for help on using the changeset viewer.