Title: [186871] branches/safari-600.8-branch/Source/WebCore

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;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to