diff options
author | Patrick Scott <phanna@android.com> | 2009-09-29 14:11:16 -0400 |
---|---|---|
committer | Patrick Scott <phanna@android.com> | 2009-09-30 14:48:54 -0400 |
commit | 30027e43592c7246954056a89ce410c01d4dd86f (patch) | |
tree | bb8fa40a2f3bf31e04afadda893a098eb68e3947 /WebCore | |
parent | 418164343aa2437668796a013c1326c43ef318ac (diff) | |
download | external_webkit-30027e43592c7246954056a89ce410c01d4dd86f.zip external_webkit-30027e43592c7246954056a89ce410c01d4dd86f.tar.gz external_webkit-30027e43592c7246954056a89ce410c01d4dd86f.tar.bz2 |
Fix the random crash around iframes.
The problem is that if updateWidgetPosition calls layout, the FrameView will
layout with 0x0 dimensions. Then, we resize the view and try to relayout. This
causes the body to be marked as needing a layout. But, the body does not get a
chance to relayout. If updateWidgetPosition does not layout, the view size will
match and the body will not be marked for layout. This makes everything sane
after layout of the iframe.
The root of the problem is that we are calling FrameView::layout() while in the
midst of a layout. This is causing a child RenderObject to need a layout
without the parent object needing a layout. We avoid this by not laying out
until we set the FrameView dimensions.
Bug: 2048855, 2134215
Diffstat (limited to 'WebCore')
-rw-r--r-- | WebCore/rendering/RenderPartObject.cpp | 26 | ||||
-rw-r--r-- | WebCore/rendering/RenderWidget.cpp | 2 |
2 files changed, 24 insertions, 4 deletions
diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp index 5f6d903..72298c6 100644 --- a/WebCore/rendering/RenderPartObject.cpp +++ b/WebCore/rendering/RenderPartObject.cpp @@ -386,11 +386,13 @@ void RenderPartObject::layout() h = 0; if (w != view->width() || h != view->height()) { view->resize(w, h); - root->setNeedsLayout(true, false); } + // Layout the view. - if (view->needsLayout()) + do { view->layout(); + } while (view->layoutPending() || root->needsLayout()); + int contentHeight = view->contentsHeight(); int contentWidth = view->contentsWidth(); // Only change the width or height if scrollbars are visible or @@ -403,6 +405,20 @@ void RenderPartObject::layout() // Update one last time updateWidgetPosition(); + +#if !ASSERT_DISABLED + ASSERT(!view->layoutPending()); + ASSERT(!root->needsLayout()); + // Sanity check when assertions are enabled. + RenderObject* c = root->nextInPreOrder(); + while (c) { + ASSERT(!c->needsLayout()); + c = c->nextInPreOrder(); + } + Node* body = document()->body(); + if (body) + ASSERT(!body->renderer()->needsLayout()); +#endif } } } @@ -446,8 +462,9 @@ void RenderPartObject::calcWidth() { updateWidgetPosition(); // Layout to get the content width - while (view->needsLayout()) + do { view->layout(); + } while (view->layoutPending() || root->needsLayout()); setWidth(max(width(), view->contentsWidth() + extraWidth)); @@ -471,8 +488,9 @@ void RenderPartObject::calcHeight() { updateWidgetPosition(); // Layout to get the content height - while (view->needsLayout()) + do { view->layout(); + } while (view->layoutPending() || root->needsLayout()); int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); setHeight(max(width(), view->contentsHeight() + extraHeight)); diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 16526ca..36f4fed 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -255,6 +255,7 @@ void RenderWidget::updateWidgetPosition() deref(arena); } +#ifndef FLATTEN_IFRAME // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget->isFrameView()) { @@ -262,6 +263,7 @@ void RenderWidget::updateWidgetPosition() if (boundsChanged || frameView->needsLayout()) frameView->layout(); } +#endif } void RenderWidget::setSelectionState(SelectionState state) |