Avoid auto-resize re-entrancy problems.

ASSERT(needsLayout()) failed in various layout() methods. The reason is
that autoSizeIfEnabled() will re-enter FrameView::layout(), and upon return,
the rootForThisLayout RenderObject has already been layed out.

This CL moves the auto-sizing up to the top of FrameView::layout() to avoid
the re-entrancy problem with rootForThisLayout.

BUG=403743

Review URL: https://codereview.chromium.org/473903002

git-svn-id: svn://svn.chromium.org/blink/trunk@181258 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/Source/core/frame/FrameView.cpp b/Source/core/frame/FrameView.cpp
index 5d42bda..0112489 100644
--- a/Source/core/frame/FrameView.cpp
+++ b/Source/core/frame/FrameView.cpp
@@ -784,6 +784,9 @@
     // Every scroll that happens during layout is programmatic.
     TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
 
+    if (m_autoSizeInfo)
+        m_autoSizeInfo->autoSizeIfNeeded();
+
     m_hasPendingLayout = false;
     DocumentLifecycle::Scope lifecycleScope(lifecycle(), DocumentLifecycle::LayoutClean);
 
@@ -834,8 +837,6 @@
             }
         }
         updateCounters();
-        if (m_autoSizeInfo)
-            m_autoSizeInfo->autoSizeIfNeeded();
 
         ScrollbarMode hMode;
         ScrollbarMode vMode;
diff --git a/Source/web/tests/WebViewTest.cpp b/Source/web/tests/WebViewTest.cpp
index c45519c..ca2e263 100644
--- a/Source/web/tests/WebViewTest.cpp
+++ b/Source/web/tests/WebViewTest.cpp
@@ -82,6 +82,7 @@
 #include <gtest/gtest.h>
 
 using namespace blink;
+using blink::FrameTestHelpers::loadFrame;
 using blink::FrameTestHelpers::runPendingTasks;
 using blink::URLTestHelpers::toKURL;
 
@@ -2168,4 +2169,20 @@
     EXPECT_EQ(expected, actual);
 }
 
+TEST_F(WebViewTest, AutoResizeSubtreeLayout)
+{
+    std::string url = m_baseURL + "subtree-layout.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "subtree-layout.html");
+    WebView* webView = m_webViewHelper.initialize(true);
+
+    webView->enableAutoResizeMode(WebSize(200, 200), WebSize(200, 200));
+    loadFrame(webView->mainFrame(), url);
+
+    blink::FrameView* frameView = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
+
+    // Auto-resizing used to ASSERT(needsLayout()) in RenderBlockFlow::layout. This EXPECT is
+    // merely a dummy. The real test is that we don't trigger asserts in debug builds.
+    EXPECT_FALSE(frameView->needsLayout());
+};
+
 } // namespace
diff --git a/Source/web/tests/data/subtree-layout.html b/Source/web/tests/data/subtree-layout.html
new file mode 100644
index 0000000..c96b0a6
--- /dev/null
+++ b/Source/web/tests/data/subtree-layout.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+/* RenderObject::objectIsRelayoutBoundary() should be true */
+#relayoutBoundary {
+    overflow: hidden;
+    width: 100px;
+    height: 100px;
+}
+</style>
+<div id="relayoutBoundary">
+    <div id="layouter"></div>
+</div>
+<script>
+document.body.offsetTop;
+document.getElementById("layouter").style.position = "relative";
+document.body.offsetTop;
+</script>