Changeset 25726 in webkit


Ignore:
Timestamp:
Sep 25, 2007 11:35:54 AM (17 years ago)
Author:
bdakin
Message:

Reviewed by Darin.

Fix for <rdar://problem/5466459> CrashTracer: [USER] 1 crash in
NetNewsWire at com.apple.WebCore: WebCore::bidiNext + 485 (15241)

Mitz discovered that this crash appeared because r25128 made it
possible for RenderPartObject::updateWidget() to be called during
layout. updateWidget() can, through a series of calls, cause an
attach/detach to happen, which is very bad in the middle of a
layout and is what led to this crash. This patch fixes that by
having the FrameView keep track of a queue of RenderPartObjects
that need to call updateWidget(), and it goes through the queue
calling updateWidget() as soon as layout is done.

  • page/FrameView.cpp: We only want to call updateWidget() if we are not in a nested layout. Unfortunately, the existing variables on FrameViewPrivate do not have exactly the information that we need, so I added nestedLayoutCount. (WebCore::FrameViewPrivate::reset): Reset nestedLayoutCount. (WebCore::FrameView::layout): Increment nestedLayoutCount once we have gotten through all of the early returns. Call updateWidget() after layout is nestedLayoutCount is 1 and there are widgets to update. Decrement nestedLayoutCount at the end. (WebCore::FrameView::addWidgetToUpdate): (WebCore::FrameView::removeWidgetToUpdate):
  • page/FrameView.h:
  • rendering/RenderPartObject.cpp: (WebCore::RenderPartObject::~RenderPartObject): Remove this from the FrameView's update set. (WebCore::RenderPartObject::layout): Instead of calling updateWidget() immediately, add this to the update widget set on FrameView.
  • rendering/RenderPartObject.h:
Location:
trunk/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r25724 r25726  
     12007-09-25  Beth Dakin  <bdakin@apple.com>
     2
     3        Reviewed by Darin.
     4
     5        Fix for <rdar://problem/5466459> CrashTracer: [USER] 1 crash in
     6        NetNewsWire at com.apple.WebCore: WebCore::bidiNext + 485 (15241)
     7
     8        Mitz discovered that this crash appeared because r25128 made it
     9        possible for RenderPartObject::updateWidget() to be called during
     10        layout. updateWidget() can, through a series of calls, cause an
     11        attach/detach to happen, which is very bad in the middle of a
     12        layout and is what led to this crash. This patch fixes that by
     13        having the FrameView keep track of a queue of RenderPartObjects
     14        that need to call updateWidget(), and it goes through the queue
     15        calling updateWidget() as soon as layout is done.
     16
     17        * page/FrameView.cpp: We only want to call updateWidget() if we are
     18        not in a nested layout. Unfortunately, the existing variables on
     19        FrameViewPrivate do not have exactly the information that we need,
     20        so I added nestedLayoutCount.
     21        (WebCore::FrameViewPrivate::reset): Reset nestedLayoutCount.
     22        (WebCore::FrameView::layout): Increment nestedLayoutCount once we
     23        have gotten through all of the early returns. Call updateWidget()
     24        after layout is nestedLayoutCount is 1 and there are widgets to
     25        update. Decrement nestedLayoutCount at the end.
     26        (WebCore::FrameView::addWidgetToUpdate):
     27        (WebCore::FrameView::removeWidgetToUpdate):
     28        * page/FrameView.h:
     29        * rendering/RenderPartObject.cpp:
     30        (WebCore::RenderPartObject::~RenderPartObject): Remove this from
     31        the FrameView's update set.
     32        (WebCore::RenderPartObject::layout): Instead of calling
     33        updateWidget() immediately, add this to the update widget set on
     34        FrameView.
     35        * rendering/RenderPartObject.h:
     36
    1372007-09-25  David Kilzer  <ddkilzer@webkit.org>
    238
  • trunk/WebCore/page/FrameView.cpp

    r25703 r25726  
    3939#include "OverflowEvent.h"
    4040#include "RenderPart.h"
     41#include "RenderPartObject.h"
    4142#include "RenderTheme.h"
    4243#include "RenderView.h"
     
    8283        midLayout = false;
    8384        layoutCount = 0;
     85        nestedLayoutCount = 0;
    8486        firstLayout = true;
    8587        repaintRects.clear();
     
    103105    bool midLayout;
    104106    int layoutCount;
     107    unsigned nestedLayoutCount;
    105108
    106109    bool firstLayout;
     
    346349        return;
    347350    }
     351
     352    d->nestedLayoutCount++;
    348353
    349354    ScrollbarMode hMode = d->hmode;
     
    473478                             visibleHeight() < contentsHeight());
    474479
     480    if (m_widgetUpdateSet && d->nestedLayoutCount == 1) {
     481        HashSet<RenderPartObject*> set;
     482        m_widgetUpdateSet->swap(set);
     483       
     484        HashSet<RenderPartObject*>::iterator end = set.end();
     485        for (HashSet<RenderPartObject*>::iterator it = set.begin(); it != end; ++it)
     486            (*it)->updateWidget(false);
     487    }
     488
    475489    // Allow events scheduled during layout to fire
    476490    resumeScheduledEvents();
     491
     492    d->nestedLayoutCount--;
     493}
     494
     495void FrameView::addWidgetToUpdate(RenderPartObject* object)
     496{
     497    if (!m_widgetUpdateSet)
     498        m_widgetUpdateSet.set(new HashSet<RenderPartObject*>);
     499
     500    m_widgetUpdateSet->add(object);
     501}
     502
     503void FrameView::removeWidgetToUpdate(RenderPartObject* object)
     504{
     505    if (!m_widgetUpdateSet)
     506        return;
     507
     508    m_widgetUpdateSet->remove(object);
    477509}
    478510
  • trunk/WebCore/page/FrameView.h

    r25703 r25726  
    2929#include "IntSize.h"
    3030#include <wtf/Forward.h>
     31#include <wtf/OwnPtr.h>
    3132
    3233namespace WebCore {
     
    4243class RenderLayer;
    4344class RenderObject;
     45class RenderPartObject;
    4446class String;
    4547
     
    126128    void setWasScrolledByUser(bool);
    127129
     130    void addWidgetToUpdate(RenderPartObject*);
     131    void removeWidgetToUpdate(RenderPartObject*);
     132
    128133    // FIXME: This method should be used by all platforms, but currently depends on ScrollView::children,
    129134    // which not all methods have. Once FrameView and ScrollView are merged, this #if should be removed.
     
    152157    IntSize m_size;
    153158    IntSize m_margins;
     159    OwnPtr<HashSet<RenderPartObject*> > m_widgetUpdateSet;
    154160    RefPtr<Frame> m_frame;
    155161    FrameViewPrivate* d;
  • trunk/WebCore/rendering/RenderPartObject.cpp

    r25283 r25726  
    4141#include "MIMETypeRegistry.h"
    4242#include "Page.h"
     43#include "RenderView.h"
    4344#include "Text.h"
    4445
     
    5354    setInline(true);
    5455    m_hasFallbackContent = false;
     56}
     57
     58RenderPartObject::~RenderPartObject()
     59{
     60    if (m_view)
     61        m_view->removeWidgetToUpdate(this);
    5562}
    5663
     
    268275    RenderPart::layout();
    269276
    270     if (!m_widget)
    271         updateWidget(false);
     277    if (!m_widget && m_view)
     278        m_view->addWidgetToUpdate(this);
    272279   
    273280    setNeedsLayout(false);
  • trunk/WebCore/rendering/RenderPartObject.h

    r25128 r25726  
    3333public:
    3434    RenderPartObject(HTMLFrameOwnerElement*);
     35    virtual ~RenderPartObject();
    3536
    3637    virtual const char* renderName() const { return "RenderPartObject"; }
Note: See TracChangeset for help on using the changeset viewer.