Diff
Modified: branches/safari-600.8-branch/Source/WebCore/ChangeLog (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/ChangeLog 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/ChangeLog 2015-07-15 23:31:22 UTC (rev 186871)
@@ -1,3 +1,51 @@
+2015-07-14 Matthew Hanson <matthew_han...@apple.com>
+
+ Merge r186533. rdar://problem/21533137
+
+ 2015-07-08 Lucas Forschler <lforsch...@apple.com>
+
+ Merge change for rdar://problem/21533232
+
+ 2015-07-08 Zalan Bujtas <za...@apple.com>
+
+ Do not crash when the descendant frame tree is destroyed during layout.
+ https://bugs.webkit.org/show_bug.cgi?id=144540
+ rdar://problem/20793184
+
+ Reviewed by Andreas Kling.
+
+ Widget::setFrameRect(), through WebHTMLView layout, could trigger a style recalc, which in turn
+ could initiate an onBeforeLoad callback.
+ If _javascript_ happens to destroy the current iframe in the onBeforeLoad callback, we lose the descendant
+ render tree, including the child FrameView (the iframe element's view). However the RenderIFrame
+ object stays protected until after the layout is done. (see protectRenderWidgetUntilLayoutIsDone())
+
+ Climbing back on the callstack, we need to make sure that
+ 1. the root widget of the descendant render tree (FrameView) stays valid as long as it is needed.
+ 2. RenderFrameBase::layoutWithFlattening() can handle the case when the associated widget (child FrameView) is set to nullptr.
+ (see RenderWidget::willBeDestroyed() -> setWidget(nullptr))
+
+ (and later, when layout is finished this (RenderIFrame) object gets destroyed too.)
+
+ Covered by fast/frames/flattening/crash-remove-iframe-during-object-beforeload.html.
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::setFrameRect):
+ (WebCore::FrameView::updateEmbeddedObject):
+ (WebCore::FrameView::updateWidgetPositions):
+ * platform/ScrollView.cpp:
+ (WebCore::ScrollView::setFrameRect):
+ * platform/mac/WidgetMac.mm:
+ (WebCore::Widget::setFrameRect):
+ * rendering/RenderFrameBase.cpp:
+ (WebCore::RenderFrameBase::layoutWithFlattening):
+ (WebCore::RenderFrameBase::childRenderView):
+ (WebCore::RenderFrameBase::peformLayoutWithFlattening):
+ * rendering/RenderFrameBase.h:
+ * rendering/RenderWidget.cpp:
+ (WebCore::RenderWidget::updateWidgetPosition):
+ * rendering/RenderWidget.h:
+
2015-07-15 Matthew Hanson <matthew_han...@apple.com>
Merge r186781. rdar://problem/21708063
Modified: branches/safari-600.8-branch/Source/WebCore/page/FrameView.cpp (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/page/FrameView.cpp 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/page/FrameView.cpp 2015-07-15 23:31:22 UTC (rev 186871)
@@ -416,6 +416,7 @@
void FrameView::setFrameRect(const IntRect& newRect)
{
+ Ref<FrameView> protect(*this);
IntRect oldRect = frameRect();
if (newRect == oldRect)
return;
@@ -2841,7 +2842,8 @@
if (!weakRenderer)
return;
- embeddedObject.updateWidgetPosition();
+ auto ignoreWidgetState = embeddedObject.updateWidgetPosition();
+ UNUSED_PARAM(ignoreWidgetState);
}
bool FrameView::updateEmbeddedObjects()
@@ -4554,8 +4556,10 @@
auto protectedWidgets = collectAndProtectWidgets(m_widgetsInRenderTree);
for (unsigned i = 0, size = protectedWidgets.size(); i < size; ++i) {
- if (RenderWidget* renderWidget = RenderWidget::find(protectedWidgets[i].get()))
- renderWidget->updateWidgetPosition();
+ if (RenderWidget* renderWidget = RenderWidget::find(protectedWidgets[i].get())) {
+ auto ignoreWidgetState = renderWidget->updateWidgetPosition();
+ UNUSED_PARAM(ignoreWidgetState);
+ }
}
}
Modified: branches/safari-600.8-branch/Source/WebCore/platform/ScrollView.cpp (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/platform/ScrollView.cpp 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/platform/ScrollView.cpp 2015-07-15 23:31:22 UTC (rev 186871)
@@ -1041,6 +1041,7 @@
void ScrollView::setFrameRect(const IntRect& newRect)
{
+ Ref<ScrollView> protect(*this);
IntRect oldRect = frameRect();
if (newRect == oldRect)
Modified: branches/safari-600.8-branch/Source/WebCore/platform/mac/WidgetMac.mm (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/platform/mac/WidgetMac.mm 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/platform/mac/WidgetMac.mm 2015-07-15 23:31:22 UTC (rev 186871)
@@ -159,7 +159,7 @@
return;
// Take a reference to this Widget, because sending messages to outerView can invoke arbitrary
- // code, which can deref it.
+ // code including recalc style/layout, which can deref it.
Ref<Widget> protect(*this);
NSRect frame = rect;
Modified: branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.cpp (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.cpp 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.cpp 2015-07-15 23:31:22 UTC (rev 186871)
@@ -54,24 +54,37 @@
void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
{
+ peformLayoutWithFlattening(hasFixedWidth, hasFixedHeight);
+
+ clearNeedsLayout();
+}
+
+RenderView* RenderFrameBase::childRenderView() const
+{
+ if (!childView())
+ return nullptr;
+ return childView()->renderView();
+}
+
+void RenderFrameBase::peformLayoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
+{
FrameView* childFrameView = childView();
RenderView* childRoot = childFrameView ? childFrameView->frame().contentRenderer() : 0;
- if (!childRoot || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
- updateWidgetPosition();
- if (childFrameView)
- childFrameView->layout();
- clearNeedsLayout();
- return;
+ if (!childRenderView() || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
+ if (updateWidgetPosition() == ChildWidgetState::ChildWidgetIsDestroyed)
+ return;
+ childView()->layout();
}
// need to update to calculate min/max correctly
- updateWidgetPosition();
+ if (updateWidgetPosition() == ChildWidgetState::ChildWidgetIsDestroyed)
+ return;
- // if scrollbars are off, and the width or height are fixed
+ // if scrollbars are off, and the width or height are fixedRenderView* childRoot = childView() ? childView()->frame().contentRenderer() : 0;
+
// we obey them and do not expand. With frame flattening
// no subframe much ever become scrollable.
-
bool isScrollable = frameOwnerElement().scrollingMode() != ScrollbarAlwaysOff;
// consider iframe inset border
@@ -80,25 +93,27 @@
// make sure minimum preferred width is enforced
if (isScrollable || !hasFixedWidth) {
- setWidth(std::max(width(), childRoot->minPreferredLogicalWidth() + hBorder));
+ ASSERT(childRenderView());
+ setWidth(std::max(width(), childRenderView()->minPreferredLogicalWidth() + hBorder));
// update again to pass the new width to the child frame
- updateWidgetPosition();
+ if (updateWidgetPosition() == ChildWidgetState::ChildWidgetIsDestroyed)
+ return;
childFrameView->layout();
}
+ ASSERT(childView());
// expand the frame by setting frame height = content height
if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
setHeight(std::max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
setWidth(std::max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));
- updateWidgetPosition();
+ if (updateWidgetPosition() == ChildWidgetState::ChildWidgetIsDestroyed)
+ return;
ASSERT(!childFrameView->layoutPending());
- ASSERT(!childRoot->needsLayout());
- ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChildSlow() || !childRoot->firstChild()->firstChildSlow()->needsLayout());
-
- clearNeedsLayout();
+ ASSERT(!childRenderView()->needsLayout());
+ ASSERT(!childRenderView()->firstChild() || !childRenderView()->firstChild()->firstChildSlow() || !childRenderView()->firstChild()->firstChildSlow()->needsLayout());
}
}
Modified: branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.h (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.h 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/rendering/RenderFrameBase.h 2015-07-15 23:31:22 UTC (rev 186871)
@@ -32,6 +32,7 @@
namespace WebCore {
class HTMLFrameElementBase;
+class RenderView;
// Base class for RenderFrame and RenderIFrame
class RenderFrameBase : public RenderWidget {
@@ -44,6 +45,8 @@
void layoutWithFlattening(bool fixedWidth, bool fixedHeight);
private:
+ void peformLayoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight);
+ RenderView* childRenderView() const;
void widget() const = delete;
};
Modified: branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.cpp (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.cpp 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.cpp 2015-07-15 23:31:22 UTC (rev 186871)
@@ -305,15 +305,15 @@
toFrameView(m_widget.get())->setIsOverlapped(isOverlapped);
}
-void RenderWidget::updateWidgetPosition()
+RenderWidget::ChildWidgetState RenderWidget::updateWidgetPosition()
{
if (!m_widget)
- return;
+ return ChildWidgetState::ChildWidgetIsDestroyed;
WeakPtr<RenderWidget> weakThis = createWeakPtr();
bool widgetSizeChanged = updateWidgetGeometry();
- if (!weakThis)
- return;
+ if (!weakThis || !m_widget)
+ return ChildWidgetState::ChildWidgetIsDestroyed;
// if the frame size 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.
@@ -323,6 +323,7 @@
if ((widgetSizeChanged || frameView->needsLayout()) && frameView->frame().page())
frameView->layout();
}
+ return ChildWidgetState::ChildWidgetIsValid;
}
IntRect RenderWidget::windowClipRect() const
Modified: branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.h (186870 => 186871)
--- branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.h 2015-07-15 23:13:56 UTC (rev 186870)
+++ branches/safari-600.8-branch/Source/WebCore/rendering/RenderWidget.h 2015-07-15 23:31:22 UTC (rev 186871)
@@ -67,7 +67,8 @@
static RenderWidget* find(const Widget*);
- void updateWidgetPosition();
+ enum class ChildWidgetState { ChildWidgetIsValid, ChildWidgetIsDestroyed };
+ ChildWidgetState updateWidgetPosition() WARN_UNUSED_RETURN;
IntRect windowClipRect() const;
bool requiresAcceleratedCompositing() const;