Carry out a resize even if no layout has been performed.

Add a FrameView resize in WebviewImpl::performResize if no layout has been
performed. This to fix the case where a layout is not performed because the
layout height is forced to zero (and therefore no layouts are performed when
the actual height is changed).

There were conflicts here -- some of the code that was supposed to be
edited in this commit in WebViewImpl::layoutUpdated had not been moved from
WebViewImpl::refreshPageScaleFactorAfterLayout to
WebViewImpl::layoutUpdated on this branch.

BUG=457159

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

Change-Id: I2775bc0ba2684f914a9966a69cd580dbccd1e1a4
git-svn-id: svn://svn.chromium.org/blink/trunk@190424 bbb929c8-8fbe-4397-9dbb-9b2b20218538
Bug: 19105464
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
index b9e8617..932fb5a 100644
--- a/Source/web/WebViewImpl.cpp
+++ b/Source/web/WebViewImpl.cpp
@@ -1685,6 +1685,11 @@
     if (pinchVirtualViewportEnabled())
         page()->frameHost().pinchViewport().setSize(m_size);
 
+    if (localFrameRootTemporary()->frameView()) {
+        if (!localFrameRootTemporary()->frameView()->needsLayout())
+            postLayoutResize(localFrameRootTemporary());
+    }
+
     // When device emulation is enabled, device size values may change - they are
     // usually set equal to the view size. These values are not considered viewport-dependent
     // (see MediaQueryExp::isViewportDependent), since they are only viewport-dependent in emulation mode,
@@ -3255,8 +3260,7 @@
         m_pageScaleConstraintsSet.adjustFinalConstraintsToContentsSize(contentsSize(), verticalScrollbarWidth);
     }
 
-    if (pinchVirtualViewportEnabled())
-        view->resize(mainFrameSize());
+    postLayoutResize(localFrameRootTemporary());
 
     float newPageScaleFactor = pageScaleFactor();
     if (m_pageScaleConstraintsSet.needsReset() && m_pageScaleConstraintsSet.finalConstraints().initialScale != -1) {
@@ -3954,6 +3958,18 @@
     }
 }
 
+void WebViewImpl::postLayoutResize(WebLocalFrameImpl* webframe)
+{
+    FrameView* view = webframe->frame()->view();
+    if (pinchVirtualViewportEnabled()) {
+        if (webframe == mainFrame()) {
+            view->resize(mainFrameSize());
+        } else {
+            view->resize(webframe->frameView()->layoutSize());
+        }
+    }
+}
+
 void WebViewImpl::layoutUpdated(WebLocalFrameImpl* webframe)
 {
     if (!m_client || !webframe->frame()->isLocalRoot())
diff --git a/Source/web/WebViewImpl.h b/Source/web/WebViewImpl.h
index f0a2149..3ef53db 100644
--- a/Source/web/WebViewImpl.h
+++ b/Source/web/WebViewImpl.h
@@ -359,6 +359,8 @@
     // not take the user away from the current page.
     void didCommitLoad(bool isNewNavigation, bool isNavigationWithinPage);
 
+    void postLayoutResize(WebLocalFrameImpl* webframe);
+
     // Indicates two things:
     //   1) This view may have a new layout now.
     //   2) Calling layout() is a no-op.
diff --git a/Source/web/tests/WebFrameTest.cpp b/Source/web/tests/WebFrameTest.cpp
index 2d24c78..ab870aa 100644
--- a/Source/web/tests/WebFrameTest.cpp
+++ b/Source/web/tests/WebFrameTest.cpp
@@ -1314,6 +1314,49 @@
     EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
 }
 
+TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksWithRelayoutsWhenHeightChanged)
+{
+    // this unit test is an attempt to target a real world case where an app could
+    // 1. call resize(width, 0) and setForceZeroLayoutHeight(true)
+    // 2. load content (hoping that the viewport height would increase
+    // as more content is added)
+    // 3. fail to register touch events aimed at the loaded content
+    // because the layout is only updated if either width or height is changed
+    UseMockScrollbarSettings mockScrollbarSettings;
+    registerMockedHttpURLLoad("button.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    FrameTestHelpers::WebViewHelper webViewHelper;
+
+    webViewHelper.initializeAndLoad(m_baseURL + "button.html", true, 0, &client, configurePinchVirtualViewport);
+    // set view height to zero so that if the height of the view is not
+    // successfully updated during later resizes touch events will fail
+    // (as in not hit content included in the view)
+    webViewHelper.webView()->resize(WebSize(viewportWidth, 0));
+    webViewHelper.webView()->layout();
+
+    webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
+    webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
+
+    IntPoint hitPoint = IntPoint(30, 30); // button size is 100x100
+
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.webView()->mainFrame());
+    Document* document = frame->frame()->document();
+    Element* element = document->getElementById("tap_button");
+
+    ASSERT_NE(nullptr, element);
+    EXPECT_EQ(String("oldValue"), element->innerText());
+
+    PlatformGestureEvent gestureEvent(PlatformEvent::Type::GestureTap, hitPoint, hitPoint, IntSize(0, 0), 0, false, false, false, false, 0.0, 0.0, 0.0, 0.0, false);
+    webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().handleGestureEvent(gestureEvent);
+    // when pressed, the button changes its own text to "updatedValue"
+    EXPECT_EQ(String("updatedValue"), element->innerText());
+}
+
 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
 {
     UseMockScrollbarSettings mockScrollbarSettings;
diff --git a/Source/web/tests/data/button.html b/Source/web/tests/data/button.html
new file mode 100644
index 0000000..20aee88
--- /dev/null
+++ b/Source/web/tests/data/button.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+function changeText(id, newText) {
+  var node = document.getElementById(id);
+  node.childNodes[0].nodeValue = newText;
+}
+</script>
+
+  <meta name='viewport' content='width=device-width'/>
+  <style>
+    body {
+      margin: 0px;
+    }
+  </style>
+</head>
+
+<body>
+  <button type="button" id="tap_button" onclick="changeText('tap_button', 'updatedValue')" style="width:100px;height:100px">oldValue</button>
+</body>
+
+</html>
+