Merge from Chromium at DEPS revision 37.0.2062.95

This commit was generated by merge_to_master.py.

Change-Id: Ia62d49f631717a2460a814c8830ea0477360d511
diff --git a/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported-expected.txt b/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported-expected.txt
deleted file mode 100644
index aebe249..0000000
--- a/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This tests that the fullscreenEnabled property is false when fullscreen is not supported as laid out in section 4 of the Fullscreen API living standard
-EXPECTED (document.webkitFullscreenEnabled == 'false') OK
-EXPECTED (iframe.contentDocument.webkitFullscreenEnabled == 'false') OK
-END OF TEST
-
diff --git a/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported.html b/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported.html
deleted file mode 100644
index b173011..0000000
--- a/LayoutTests/fullscreen/full-screen-not-enabled-when-unsupported.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<body>
-<div>This tests that the <code>fullscreenEnabled</code> property is false when fullscreen
-is not supported as laid out in section 4 of the 
-<a href="http://fullscreen.spec.whatwg.org/#api">Fullscreen API</a> living
-standard</div>
-<script src="full-screen-test.js"></script>
-<script>
-    window.internals.settings.setFullscreenSupported(false);
-    
-    testExpected('document.webkitFullscreenEnabled', false);
-
-    var iframe = document.documentElement.appendChild(document.createElement('iframe'));
-    iframe.setAttribute('allowfullscreen', 'true');
-    testExpected('iframe.contentDocument.webkitFullscreenEnabled', false);
-    endTest();
-</script>
-</body>
\ No newline at end of file
diff --git a/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements-expected.txt b/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements-expected.txt
deleted file mode 100644
index 3f90fa8..0000000
--- a/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-EVENT(webkitfullscreenerror)
-EVENT(webkitfullscreenchange)
-END OF TEST
-Tests for the disallowFullscreenForNonMediaElements setting which will be set in those platforms where fullscreen for non-media elements is not supported.
diff --git a/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements.html b/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements.html
deleted file mode 100644
index 4e2c0b5..0000000
--- a/LayoutTests/fullscreen/full-screen-request-disallow-for-non-media-elements.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<body>
-<script src="full-screen-test.js"></script>
-<span id="span" width="300"></span>
-<video id="video" width="300"></video>
-<div>Tests for the disallowFullscreenForNonMediaElements setting which will be set
-in those platforms where fullscreen for non-media elements is not supported.
-<script>
-    if (window.internals) {
-        window.internals.settings.setDisallowFullscreenForNonMediaElements(true);
-
-        var testStep2 = function() {
-            // Fullscreen for media elements is supported, video in this case.
-            waitForEventAndEnd(document, 'webkitfullscreenchange');
-            runWithKeyDown(function(){document.getElementById('video').webkitRequestFullScreen()});
-        };
-
-        // Fullscreen for non media elements is not supported.
-        waitForEventOnce(document, 'webkitfullscreenerror', testStep2);
-        runWithKeyDown(function(){document.getElementById('span').webkitRequestFullScreen()})
-    }
-</script>
-</body>
\ No newline at end of file
diff --git a/LayoutTests/fullscreen/full-screen-request-not-supported-expected.txt b/LayoutTests/fullscreen/full-screen-request-not-supported-expected.txt
deleted file mode 100644
index 8215ec3..0000000
--- a/LayoutTests/fullscreen/full-screen-request-not-supported-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-EVENT(webkitfullscreenerror)
-END OF TEST
-Tests for the fullscreenSupported setting which will be set to false in those platforms where fullscreen is not supported.
diff --git a/LayoutTests/fullscreen/full-screen-request-not-supported.html b/LayoutTests/fullscreen/full-screen-request-not-supported.html
deleted file mode 100644
index db7d24e..0000000
--- a/LayoutTests/fullscreen/full-screen-request-not-supported.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<body>
-<script src="full-screen-test.js"></script>
-<video id="video" width="300"></video>
-<div>Tests for the fullscreenSupported setting which will be set to false
-in those platforms where fullscreen is not supported.
-<script>
-    if (window.internals) {
-        window.internals.settings.setFullscreenSupported(false);
-
-        waitForEvent(document, 'webkitfullscreenchange', function() {
-            logResult(false, 'Entered fullscreen.');
-            endTest();
-        });
-        waitForEventAndEnd(document, 'webkitfullscreenerror');
-        runWithKeyDown(function(){document.getElementById('video').webkitRequestFullScreen()});
-    }
-</script>
-</body>
\ No newline at end of file
diff --git a/LayoutTests/fullscreen/video-fail-to-enter-full-screen-expected.txt b/LayoutTests/fullscreen/video-fail-to-enter-full-screen-expected.txt
deleted file mode 100644
index 5497735..0000000
--- a/LayoutTests/fullscreen/video-fail-to-enter-full-screen-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This tests that the video should not be rendered in full screen if requestFullScreen() fails.
-
-END OF TEST
-
diff --git a/LayoutTests/fullscreen/video-fail-to-enter-full-screen.html b/LayoutTests/fullscreen/video-fail-to-enter-full-screen.html
deleted file mode 100644
index aed847b..0000000
--- a/LayoutTests/fullscreen/video-fail-to-enter-full-screen.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<p>This tests that the video should not be rendered in full screen if requestFullScreen() fails.</p>
-<video id="video" width="300"></video>
-<script>
-    if (window.internals)
-    runPixelTests = internals.runtimeFlags.overlayFullscreenVideoEnabled;
-</script>
-<script src="full-screen-test.js"></script>
-<script src="../media/media-controls.js"></script>
-<script>
-    var video = document.getElementById('video');
-    video.webkitRequestFullScreen();
-    setTimeout(function() {
-        endTest();
-    }, 300);
-</script>
diff --git a/LayoutTests/media/video-controls-fullscreen-not-supported.html b/LayoutTests/media/video-controls-fullscreen-not-supported.html
deleted file mode 100644
index 9b2fbb2..0000000
--- a/LayoutTests/media/video-controls-fullscreen-not-supported.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-    <head>
-        <title>video controls fullscreen button</title>
-        <script src="../resources/testharness.js"></script>
-        <script src="../resources/testharnessreport.js"></script>
-        <script src="media-file.js"></script>
-        <script src="media-controls.js"></script>
-        <script src="video-controls-fullscreen.js"></script>
-    </head>
-    <body>
-        <div id="log"></div>
-        <script>
-            window.internals.settings.setFullscreenSupported(false);
-            fullscreen_not_supported_test();
-        </script>
-    </body>
-</html>
diff --git a/LayoutTests/media/video-controls-mouse-events-captured-expected.txt b/LayoutTests/media/video-controls-mouse-events-captured-expected.txt
deleted file mode 100644
index b354062..0000000
--- a/LayoutTests/media/video-controls-mouse-events-captured-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This tests that a mouse events on the controls will not be seen by the video element.
-
-Also tests keyboard input.
-
-EVENT(loadeddata)
-END OF TEST
-
diff --git a/LayoutTests/media/video-controls-mouse-events-captured.html b/LayoutTests/media/video-controls-mouse-events-captured.html
deleted file mode 100644
index 215a8a5..0000000
--- a/LayoutTests/media/video-controls-mouse-events-captured.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-</head>
-<body>
-    <video controls></video>
-    <p>This tests that a mouse events on the controls will not be seen by the video element.</p>
-    <p>Also tests keyboard input.</p>
-    <script src=media-file.js></script>
-    <script src=video-test.js></script>
-    <script src=media-controls.js></script>
-    <script>
-        waitForEventAndFail("click");
-        waitForEventAndFail("dblclick");
-        waitForEventAndFail("mousedown");
-        waitForEventAndFail("mouseup");
-        waitForEventAndFail("keydown");
-
-        waitForEventAndEnd("loadeddata", function()
-        {
-            if (window.eventSender) {
-                // click the play button
-                var coords = mediaControlsButtonCoordinates(video, "play-button");
-                eventSender.mouseMoveTo(coords[0], coords[1]);
-
-                eventSender.mouseDown();
-                eventSender.mouseUp();
-                eventSender.keyDown('A');
-
-                // Click the current time display, which should not respond to events, but
-                // should still capture them
-                coords = mediaControlsButtonCoordinates(video, "current-time-display");
-                eventSender.mouseMoveTo(coords[0], coords[1]);
-
-                eventSender.mouseDown();
-                eventSender.mouseUp();
-                eventSender.keyDown('A');
-
-                // Click the timeline - this tests that multilevel shadow DOM elements work
-                coords = mediaControlsButtonCoordinates(video, "timeline");
-                eventSender.mouseMoveTo(coords[0], coords[1]);
-
-                eventSender.mouseDown();
-                eventSender.mouseUp();
-                eventSender.keyDown('A');
-
-                waitForEventAndFail("mousemove")
-                
-                // Check that the timeline also captures mousemove
-                eventSender.mouseMoveTo(coords[0]+10, coords[1]+10)
-            }
-        });
-        video.src = findMediaFile("video", "content/test");
-    </script>
-</body>
-</html>
\ No newline at end of file
diff --git a/LayoutTests/media/video-controls-touch-events-captured-expected.txt b/LayoutTests/media/video-controls-touch-events-captured-expected.txt
deleted file mode 100644
index 8ac305e..0000000
--- a/LayoutTests/media/video-controls-touch-events-captured-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This tests that touch events on the controls will not be seen by the video element.
-
-EVENT(loadeddata)
-END OF TEST
-
diff --git a/LayoutTests/media/video-controls-touch-events-captured.html b/LayoutTests/media/video-controls-touch-events-captured.html
deleted file mode 100644
index 0cedc42..0000000
--- a/LayoutTests/media/video-controls-touch-events-captured.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-</head>
-<body>
-    <video controls></video>
-    <p>This tests that touch events on the controls will not be seen by the video element.</p>
-    <script src=media-file.js></script>
-    <script src=video-test.js></script>
-    <script src=media-controls.js></script>
-    <script>
-        waitForEventAndFail("click");
-        waitForEventAndFail("dblclick");
-        waitForEventAndFail("touchstart");
-        waitForEventAndFail("touchend");
-        waitForEventAndFail("touchmove");
-
-        waitForEventAndEnd("loadeddata", function()
-        {
-            if (window.eventSender) {
-                // click the play button
-                var coords = mediaControlsButtonCoordinates(video, "play-button");
-                eventSender.addTouchPoint(coords[0], coords[1]);
-
-                eventSender.touchStart();
-                eventSender.leapForward(100);
-                eventSender.touchEnd();
-                eventSender.cancelTouchPoint(0);
-
-                // Click the current time display, which should not respond to events, but
-                // should still capture them
-                coords = mediaControlsButtonCoordinates(video, "current-time-display");
-                eventSender.addTouchPoint(coords[0], coords[1]);
-
-                eventSender.touchStart();
-                eventSender.leapForward(100);
-                eventSender.touchEnd();
-                eventSender.cancelTouchPoint(0);
-
-
-                // Click the timeline - this tests that multilevel shadow DOM elements work
-                coords = mediaControlsButtonCoordinates(video, "timeline");
-                eventSender.addTouchPoint(coords[0], coords[1]);
-
-                eventSender.touchStart();
-                eventSender.leapForward(100);
-                eventSender.touchEnd();
-
-                // Check that the timeline also captures moves
-                eventSender.updateTouchPoint(0, coords[0]+10, coords[1]+10)
-                eventSender.touchMove();
-                eventSender.cancelTouchPoint(0);
-
-            }
-        });
-        video.src = findMediaFile("video", "content/test");
-    </script>
-</body>
-</html>
\ No newline at end of file
diff --git a/LayoutTests/platform/linux/virtual/android/fullscreen/video-fail-to-enter-full-screen-expected.png b/LayoutTests/platform/linux/virtual/android/fullscreen/video-fail-to-enter-full-screen-expected.png
deleted file mode 100644
index b2b7e77..0000000
--- a/LayoutTests/platform/linux/virtual/android/fullscreen/video-fail-to-enter-full-screen-expected.png
+++ /dev/null
Binary files differ
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp
index 1d157db..f698233 100644
--- a/Source/core/dom/Document.cpp
+++ b/Source/core/dom/Document.cpp
@@ -3454,7 +3454,10 @@
         // We need to manually repaint because we avoid doing all repaints in layout or style
         // recalc while sheets are still loading to avoid FOUC.
         m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
-        renderView()->repaintViewAndCompositedLayers();
+
+        ASSERT(renderView() || importsController());
+        if (renderView())
+            renderView()->repaintViewAndCompositedLayers();
     }
 }
 
diff --git a/Source/core/frame/Settings.in b/Source/core/frame/Settings.in
index e2c3ed2..cae66dc 100644
--- a/Source/core/frame/Settings.in
+++ b/Source/core/frame/Settings.in
@@ -203,6 +203,10 @@
 # See http://crbug.com/288037.
 wideViewportQuirkEnabled initial=false
 
+# Used by the android_webview to support a horizontal height auto-sizing
+# mode.
+forceZeroLayoutHeight initial=false, invalidate=ViewportDescription
+
 # Touch based text selection and editing on desktop.
 # crbug.com/304873 tracks removal once it's been enabled on all platforms.
 touchEditingEnabled initial=false
diff --git a/Source/core/frame/SmartClip.cpp b/Source/core/frame/SmartClip.cpp
index 40c773e..329412c 100644
--- a/Source/core/frame/SmartClip.cpp
+++ b/Source/core/frame/SmartClip.cpp
@@ -61,33 +61,14 @@
     return 0;
 }
 
-// FIXME: SmartClipData is eventually returned via
-// SLookSmartClip.DataExtractionListener:
-// http://img-developer.samsung.com/onlinedocs/sms/com/samsung/android/sdk/look/...
-// however the original author of this change chose to use a string-serialization
-// format (presumably to make IPC easy?).
-// If we're going to use this as a Pickle format, we should at least have the
-// read/write code in one place!
-String SmartClipData::toString()
+IntRect SmartClipData::rect() const
 {
-    if (m_isEmpty)
-        return emptyString();
+    return m_rect;
+}
 
-    const UChar fieldSeparator = 0xFFFE;
-    const UChar rowSeparator = 0xFFFF;
-
-    StringBuilder result;
-    result.append(String::number(m_rect.x()));
-    result.append(fieldSeparator);
-    result.append(String::number(m_rect.y()));
-    result.append(fieldSeparator);
-    result.append(String::number(m_rect.width()));
-    result.append(fieldSeparator);
-    result.append(String::number(m_rect.height()));
-    result.append(fieldSeparator);
-    result.append(m_string);
-    result.append(rowSeparator);
-    return result.toString();
+const String& SmartClipData::clipData() const
+{
+    return m_string;
 }
 
 SmartClip::SmartClip(PassRefPtr<LocalFrame> frame)
diff --git a/Source/core/frame/SmartClip.h b/Source/core/frame/SmartClip.h
index 21955a2..76b0c49 100644
--- a/Source/core/frame/SmartClip.h
+++ b/Source/core/frame/SmartClip.h
@@ -50,7 +50,8 @@
     {
     }
 
-    String toString();
+    IntRect rect() const;
+    const String& clipData() const;
 
 private:
     bool m_isEmpty;
diff --git a/Source/web/WebLocalFrameImpl.h b/Source/web/WebLocalFrameImpl.h
index 4993b76..5991c02 100644
--- a/Source/web/WebLocalFrameImpl.h
+++ b/Source/web/WebLocalFrameImpl.h
@@ -313,6 +313,9 @@
 
     PassRefPtr<WebCore::LocalFrame> initializeAsChildFrame(WebCore::FrameHost*, WebCore::FrameOwner*, const AtomicString& name, const AtomicString& fallbackName);
 
+    // Returns a hit-tested VisiblePosition for the given point
+    WebCore::VisiblePosition visiblePositionForWindowPoint(const WebPoint&);
+
 private:
     friend class FrameLoaderClientImpl;
 
@@ -323,9 +326,6 @@
 
     void loadJavaScriptURL(const WebCore::KURL&);
 
-    // Returns a hit-tested VisiblePosition for the given point
-    WebCore::VisiblePosition visiblePositionForWindowPoint(const WebPoint&);
-
     WebPlugin* focusedPluginIfInputMethodSupported();
 
     FrameLoaderClientImpl m_frameLoaderClientImpl;
diff --git a/Source/web/WebSettingsImpl.cpp b/Source/web/WebSettingsImpl.cpp
index cb81407..a6abdef 100644
--- a/Source/web/WebSettingsImpl.cpp
+++ b/Source/web/WebSettingsImpl.cpp
@@ -666,6 +666,11 @@
     m_gestureTapHighlightEnabled = enableHighlight;
 }
 
+void WebSettingsImpl::setForceZeroLayoutHeight(bool enabled)
+{
+    m_settings->setForceZeroLayoutHeight(enabled);
+}
+
 void WebSettingsImpl::setAllowCustomScrollbarInMainFrame(bool enabled)
 {
     m_settings->setAllowCustomScrollbarInMainFrame(enabled);
diff --git a/Source/web/WebSettingsImpl.h b/Source/web/WebSettingsImpl.h
index 8cb67b8..2fb0656 100644
--- a/Source/web/WebSettingsImpl.h
+++ b/Source/web/WebSettingsImpl.h
@@ -102,6 +102,7 @@
     virtual void setFixedFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) OVERRIDE;
     virtual void setFullscreenSupported(bool) OVERRIDE;
     virtual void setGestureTapHighlightEnabled(bool) OVERRIDE;
+    virtual void setForceZeroLayoutHeight(bool) OVERRIDE;
     virtual void setHyperlinkAuditingEnabled(bool) OVERRIDE;
     virtual void setIgnoreMainFrameOverflowHiddenQuirk(bool) OVERRIDE;
     virtual void setImagesEnabled(bool) OVERRIDE;
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
index 6eed6fc..2c16122 100644
--- a/Source/web/WebViewImpl.cpp
+++ b/Source/web/WebViewImpl.cpp
@@ -40,8 +40,10 @@
 #include "core/dom/Text.h"
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/HTMLInterchange.h"
 #include "core/editing/InputMethodController.h"
 #include "core/editing/TextIterator.h"
+#include "core/editing/markup.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/events/WheelEvent.h"
 #include "core/frame/EventHandlerRegistry.h"
@@ -3030,6 +3032,9 @@
         }
     }
 
+    if (page()->settings().forceZeroLayoutHeight())
+        layoutSize.height = 0;
+
     view->setLayoutSize(layoutSize);
 }
 
@@ -3495,12 +3500,48 @@
     m_contextMenuAllowed = false;
 }
 
+// FIXME: This should be removed when the chromium side patch lands
+// http://codereview.chromium.org/260623004
 WebString WebViewImpl::getSmartClipData(WebRect rect)
 {
+    return WebString();
+}
+
+void WebViewImpl::getSmartClipData(WebRect rect, WebString& clipText, WebRect& clipRect)
+{
     LocalFrame* frame = toLocalFrame(focusedWebCoreFrame());
     if (!frame)
-        return WebString();
-    return WebCore::SmartClip(frame).dataForRect(rect).toString();
+        return;
+    SmartClipData clipData = WebCore::SmartClip(frame).dataForRect(rect);
+    clipText = clipData.clipData();
+    clipRect = clipData.rect();
+}
+
+void WebViewImpl::extractSmartClipData(WebRect rect, WebString& clipText, WebString& clipHtml, WebRect& clipRect)
+{
+    LocalFrame* localFrame = toLocalFrame(focusedWebCoreFrame());
+    if (!localFrame)
+        return;
+    SmartClipData clipData = WebCore::SmartClip(localFrame).dataForRect(rect);
+    clipText = clipData.clipData();
+    clipRect = clipData.rect();
+
+    WebLocalFrameImpl* frame = mainFrameImpl();
+    if (!frame)
+        return;
+    WebPoint startPoint(rect.x, rect.y);
+    WebPoint endPoint(rect.x + rect.width, rect.y + rect.height);
+    VisiblePosition startVisiblePosition = frame->visiblePositionForWindowPoint(startPoint);
+    VisiblePosition endVisiblePosition = frame->visiblePositionForWindowPoint(endPoint);
+
+    Position startPosition = startVisiblePosition.deepEquivalent();
+    Position endPosition = endVisiblePosition.deepEquivalent();
+
+    RefPtr<Range> range = Range::create(*startPosition.document(), startPosition, endPosition);
+    if (!range)
+        return;
+
+    clipHtml = createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
 }
 
 void WebViewImpl::hidePopups()
diff --git a/Source/web/WebViewImpl.h b/Source/web/WebViewImpl.h
index 66ec102..9b42e4a 100644
--- a/Source/web/WebViewImpl.h
+++ b/Source/web/WebViewImpl.h
@@ -245,7 +245,11 @@
                                     unsigned inactiveForegroundColor) OVERRIDE;
     virtual void performCustomContextMenuAction(unsigned action) OVERRIDE;
     virtual void showContextMenu() OVERRIDE;
+    // FIXME: This should be removed when the chromium side patch lands
+    // http://codereview.chromium.org/260623004
     virtual WebString getSmartClipData(WebRect) OVERRIDE;
+    virtual void getSmartClipData(WebRect, WebString&, WebRect&) OVERRIDE;
+    virtual void extractSmartClipData(WebRect, WebString&, WebString&, WebRect&) OVERRIDE;
     virtual void hidePopups() OVERRIDE;
     virtual void addPageOverlay(WebPageOverlay*, int /* zOrder */) OVERRIDE;
     virtual void removePageOverlay(WebPageOverlay*) OVERRIDE;
diff --git a/Source/web/tests/WebFrameTest.cpp b/Source/web/tests/WebFrameTest.cpp
index d248761..31fbdaf 100644
--- a/Source/web/tests/WebFrameTest.cpp
+++ b/Source/web/tests/WebFrameTest.cpp
@@ -1368,6 +1368,86 @@
     EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor());
 }
 
+TEST_F(WebFrameTest, SetForceZeroLayoutHeight)
+{
+    UseMockScrollbarSettings mockScrollbarSettings;
+    registerMockedHttpURLLoad("200-by-300.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    FrameTestHelpers::WebViewHelper webViewHelper;
+
+    webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
+    webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
+    webViewHelper.webView()->layout();
+
+    EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+    webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
+    EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
+
+    EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+
+    webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2));
+    EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout());
+    EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+
+    webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight));
+    webViewHelper.webView()->layout();
+    EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+
+    webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false);
+    EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+}
+
+TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
+{
+    UseMockScrollbarSettings mockScrollbarSettings;
+    registerMockedHttpURLLoad("200-by-300.html");
+    registerMockedHttpURLLoad("large-div.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    FrameTestHelpers::WebViewHelper webViewHelper;
+
+    webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
+    webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
+    webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
+    webViewHelper.webView()->layout();
+
+    FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html");
+    webViewHelper.webView()->layout();
+
+    EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+}
+
+TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk)
+{
+    UseMockScrollbarSettings mockScrollbarSettings;
+    registerMockedHttpURLLoad("200-by-300.html");
+
+    FixedLayoutTestWebViewClient client;
+    client.m_screenInfo.deviceScaleFactor = 1;
+    int viewportWidth = 640;
+    int viewportHeight = 480;
+
+    FrameTestHelpers::WebViewHelper webViewHelper;
+
+    webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings);
+    webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true);
+    webViewHelper.webView()->settings()->setUseWideViewport(true);
+    webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true);
+    webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight));
+    webViewHelper.webView()->layout();
+
+    EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
+}
+
 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale)
 {
     UseMockScrollbarSettings mockScrollbarSettings;
diff --git a/Source/web/tests/WebViewTest.cpp b/Source/web/tests/WebViewTest.cpp
index 4d6dd81..af2752f 100644
--- a/Source/web/tests/WebViewTest.cpp
+++ b/Source/web/tests/WebViewTest.cpp
@@ -1548,6 +1548,26 @@
 
 TEST_F(WebViewTest, SmartClipData)
 {
+    static const char* kExpectedClipText = "\nPrice 10,000,000won";
+    static const char* kExpectedClipHtml =
+        "<div id=\"div4\" style=\"padding: 10px; margin: 10px; border: 2px "
+        "solid rgb(135, 206, 235); float: left; width: 190px; height: 30px; "
+        "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
+        "normal; font-variant: normal; font-weight: normal; letter-spacing: "
+        "normal; line-height: normal; orphans: auto; text-align: start; "
+        "text-indent: 0px; text-transform: none; white-space: normal; widows: "
+        "auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">Air "
+        "conditioner</div><div id=\"div5\" style=\"padding: 10px; margin: "
+        "10px; border: 2px solid rgb(135, 206, 235); float: left; width: "
+        "190px; height: 30px; color: rgb(0, 0, 0); font-family: myahem; "
+        "font-size: 8px; font-style: normal; font-variant: normal; "
+        "font-weight: normal; letter-spacing: normal; line-height: normal; "
+        "orphans: auto; text-align: start; text-indent: 0px; text-transform: "
+        "none; white-space: normal; widows: auto; word-spacing: 0px; "
+        "-webkit-text-stroke-width: 0px;\">Price 10,000,000won</div>";
+    WebString clipText;
+    WebString clipHtml;
+    WebRect clipRect;
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html"));
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html");
@@ -1555,9 +1575,9 @@
     webView->resize(WebSize(500, 500));
     webView->layout();
     WebRect cropRect(300, 125, 100, 50);
-
-    // FIXME: We should test the structure of the data we get back.
-    EXPECT_FALSE(webView->getSmartClipData(cropRect).isEmpty());
+    webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
+    EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str());
+    EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str());
 }
 
 class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient {
diff --git a/public/web/WebSettings.h b/public/web/WebSettings.h
index 97618da..c6156fc 100644
--- a/public/web/WebSettings.h
+++ b/public/web/WebSettings.h
@@ -125,6 +125,7 @@
     virtual void setFixedFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) = 0;
     virtual void setFullscreenSupported(bool) = 0;
     virtual void setGestureTapHighlightEnabled(bool) = 0;
+    virtual void setForceZeroLayoutHeight(bool) = 0;
     virtual void setHyperlinkAuditingEnabled(bool) = 0;
     virtual void setIgnoreMainFrameOverflowHiddenQuirk(bool) = 0;
     virtual void setImagesEnabled(bool) = 0;
diff --git a/public/web/WebView.h b/public/web/WebView.h
index 098baac..a0525bc 100644
--- a/public/web/WebView.h
+++ b/public/web/WebView.h
@@ -409,8 +409,14 @@
 
     // SmartClip support ---------------------------------------------------
 
+    // FIXME: This should be removed when the chromium side patch lands
+    // http://codereview.chromium.org/260623004
     virtual WebString getSmartClipData(WebRect) = 0;
 
+    // TODO(changwan): remove this
+    virtual void getSmartClipData(WebRect, WebString&, WebRect& resultRect) = 0;
+    virtual void extractSmartClipData(WebRect initRect, WebString& text, WebString& html, WebRect& resultRect) = 0;
+
 
     // Popup menu ----------------------------------------------------------