Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / WebViewTest.cpp
index 1a29fca..004dcce 100644 (file)
  */
 
 #include "config.h"
-#include "WebView.h"
+#include "public/web/WebView.h"
 
-#include <gtest/gtest.h>
-#include "FrameTestHelpers.h"
-#include "URLTestHelpers.h"
-#include "WebAutofillClient.h"
-#include "WebContentDetectionResult.h"
-#include "WebDateTimeChooserCompletion.h"
-#include "WebDocument.h"
-#include "WebElement.h"
-#include "WebFrame.h"
-#include "WebFrameClient.h"
-#include "WebFrameImpl.h"
-#include "WebHelperPlugin.h"
-#include "WebHitTestResult.h"
-#include "WebInputEvent.h"
-#include "WebSettings.h"
-#include "WebViewClient.h"
-#include "WebViewImpl.h"
-#include "WebWidget.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
+#include "core/editing/FrameSelection.h"
+#include "core/frame/EventHandlerRegistry.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/Settings.h"
 #include "core/html/HTMLDocument.h"
 #include "core/html/HTMLIFrameElement.h"
 #include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLTextAreaElement.h"
 #include "core/loader/FrameLoadRequest.h"
-#include "core/frame/FrameView.h"
 #include "core/page/Chrome.h"
-#include "core/frame/Settings.h"
+#include "core/page/Page.h"
+#include "core/paint/LayerPainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include "core/testing/URLTestHelpers.h"
 #include "platform/KeyboardCodes.h"
-#include "platform/Timer.h"
+#include "platform/geometry/IntSize.h"
 #include "platform/graphics/Color.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebClipboard.h"
+#include "public/platform/WebDragData.h"
 #include "public/platform/WebSize.h"
 #include "public/platform/WebThread.h"
 #include "public/platform/WebUnitTestSupport.h"
+#include "public/web/WebAutofillClient.h"
+#include "public/web/WebContentDetectionResult.h"
+#include "public/web/WebDateTimeChooserCompletion.h"
+#include "public/web/WebDocument.h"
+#include "public/web/WebDragOperation.h"
+#include "public/web/WebElement.h"
+#include "public/web/WebFrame.h"
+#include "public/web/WebFrameClient.h"
+#include "public/web/WebHitTestResult.h"
+#include "public/web/WebInputEvent.h"
+#include "public/web/WebScriptSource.h"
+#include "public/web/WebSettings.h"
+#include "public/web/WebViewClient.h"
+#include "public/web/WebWidget.h"
 #include "public/web/WebWidgetClient.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkBitmapDevice.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WebSettingsImpl.h"
+#include "web/WebViewImpl.h"
+#include "web/tests/FrameTestHelpers.h"
+#include <gtest/gtest.h>
 
 using namespace blink;
+using blink::FrameTestHelpers::loadFrame;
 using blink::FrameTestHelpers::runPendingTasks;
 using blink::URLTestHelpers::toKURL;
 
@@ -106,7 +119,7 @@ private:
     WebViewImpl* m_webView;
 };
 
-class AutoResizeWebViewClient : public WebViewClient {
+class AutoResizeWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     // WebViewClient methods
     virtual void didAutoResize(const WebSize& newSize) { m_testData.setSize(newSize); }
@@ -118,7 +131,20 @@ private:
     TestData m_testData;
 };
 
-class TapHandlingWebViewClient : public WebViewClient {
+class SaveImageFromDataURLWebViewClient : public FrameTestHelpers::TestWebViewClient {
+public:
+    // WebViewClient methods
+    virtual void saveImageFromDataURL(const WebString& dataURL) { m_dataURL = dataURL; }
+
+    // Local methods
+    const WebString& result() const { return m_dataURL; }
+    void reset() { m_dataURL = WebString(); }
+
+private:
+    WebString m_dataURL;
+};
+
+class TapHandlingWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     // WebViewClient methods
     virtual void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled)
@@ -152,55 +178,7 @@ private:
     int m_longpressY;
 };
 
-class HelperPluginCreatingWebViewClient : public WebViewClient {
-public:
-    // WebViewClient methods
-    virtual blink::WebWidget* createPopupMenu(blink::WebPopupType popupType) OVERRIDE
-    {
-        EXPECT_EQ(WebPopupTypeHelperPlugin, popupType);
-        // The caller owns the object, but we retain a pointer for use in closeWidgetNow().
-        m_helperPluginWebWidget = blink::WebHelperPlugin::create(this);
-        return m_helperPluginWebWidget;
-    }
-
-    virtual void initializeHelperPluginWebFrame(blink::WebHelperPlugin* plugin) OVERRIDE
-    {
-        ASSERT_TRUE(m_webFrameClient);
-        plugin->initializeFrame(m_webFrameClient);
-    }
-
-    // WebWidgetClient methods
-    virtual void closeWidgetSoon() OVERRIDE
-    {
-        ASSERT_TRUE(m_helperPluginWebWidget);
-        // m_helperPluginWebWidget->close() must be called asynchronously.
-        if (!m_closeTimer.isActive())
-            m_closeTimer.startOneShot(0);
-    }
-
-    void closeWidgetNow(WebCore::Timer<HelperPluginCreatingWebViewClient>* timer)
-    {
-        m_helperPluginWebWidget->close();
-        m_helperPluginWebWidget = 0;
-    }
-
-    // Local methods
-    HelperPluginCreatingWebViewClient()
-        : m_helperPluginWebWidget(0)
-        , m_webFrameClient(0)
-        , m_closeTimer(this, &HelperPluginCreatingWebViewClient::closeWidgetNow)
-    {
-    }
-
-    void setWebFrameClient(WebFrameClient* client) { m_webFrameClient = client; }
-
-private:
-    WebWidget* m_helperPluginWebWidget;
-    WebFrameClient* m_webFrameClient;
-    WebCore::Timer<HelperPluginCreatingWebViewClient> m_closeTimer;
-};
-
-class DateTimeChooserWebViewClient : public WebViewClient {
+class DateTimeChooserWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     WebDateTimeChooserCompletion* chooserCompletion()
     {
@@ -213,7 +191,7 @@ public:
     }
 
     // WebViewClient methods
-    virtual bool openDateTimeChooser(const WebDateTimeChooserParams&, WebDateTimeChooserCompletion* chooser_completion) OVERRIDE
+    virtual bool openDateTimeChooser(const WebDateTimeChooserParams&, WebDateTimeChooserCompletion* chooser_completion) override
     {
         m_chooserCompletion = chooser_completion;
         return true;
@@ -237,6 +215,11 @@ public:
     }
 
 protected:
+    void registerMockedHttpURLLoad(const std::string& fileName)
+    {
+        URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
+    }
+
     void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
                         const std::string& pageWidth, const std::string& pageHeight,
                         int expectedWidth, int expectedHeight,
@@ -244,49 +227,103 @@ protected:
 
     void testTextInputType(WebTextInputType expectedType, const std::string& htmlFile);
     void testInputMode(const WebString& expectedInputMode, const std::string& htmlFile);
+    void testSelectionRootBounds(const char* htmlFile, float pageScaleFactor);
 
     std::string m_baseURL;
     FrameTestHelpers::WebViewHelper m_webViewHelper;
 };
 
+TEST_F(WebViewTest, SaveImageAt)
+{
+    SaveImageFromDataURLWebViewClient client;
+
+    std::string url = m_baseURL + "image-with-data-url.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-with-data-url.html");
+    WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
+    webView->resize(WebSize(400, 400));
+
+    client.reset();
+    webView->saveImageAt(WebPoint(1, 1));
+    EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
+        ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
+
+    client.reset();
+    webView->saveImageAt(WebPoint(1, 2));
+    EXPECT_EQ(WebString(), client.result());
+
+    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
+};
+
+TEST_F(WebViewTest, CopyImageAt)
+{
+    std::string url = m_baseURL + "canvas-copy-image.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "canvas-copy-image.html");
+    WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
+    webView->resize(WebSize(400, 400));
+    webView->copyImageAt(WebPoint(50, 50));
+
+    WebData data = Platform::current()->clipboard()->readImage(WebClipboard::Buffer());
+    WebImage image = WebImage::fromData(data, WebSize());
+
+    SkAutoLockPixels autoLock(image.getSkBitmap());
+    EXPECT_EQ(SkColorSetARGB(255, 255, 0, 0), image.getSkBitmap().getColor(0, 0));
+};
+
 TEST_F(WebViewTest, SetBaseBackgroundColor)
 {
     const WebColor kWhite    = 0xFFFFFFFF;
     const WebColor kBlue     = 0xFF0000FF;
     const WebColor kDarkCyan = 0xFF227788;
     const WebColor kTranslucentPutty = 0x80BFB196;
+    const WebColor kTransparent = 0x00000000;
 
-    WebView* webView = m_webViewHelper.initialize();
+    WebViewImpl* webView = m_webViewHelper.initialize();
     EXPECT_EQ(kWhite, webView->backgroundColor());
 
     webView->setBaseBackgroundColor(kBlue);
     EXPECT_EQ(kBlue, webView->backgroundColor());
 
     WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
-    webView->mainFrame()->loadHTMLString(
-        "<html><head><style>body {background-color:#227788}</style></head></html>", baseURL);
-    Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
+    FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:#227788}</style></head></html>", baseURL);
     EXPECT_EQ(kDarkCyan, webView->backgroundColor());
 
-    webView->mainFrame()->loadHTMLString(
-        "<html><head><style>body {background-color:rgba(255,0,0,0.5)}</style></head></html>", baseURL);
-    Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
+    FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:rgba(255,0,0,0.5)}</style></head></html>", baseURL);
     // Expected: red (50% alpha) blended atop base of kBlue.
     EXPECT_EQ(0xFF7F0080, webView->backgroundColor());
 
     webView->setBaseBackgroundColor(kTranslucentPutty);
     // Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha.
     EXPECT_EQ(0xBFE93B32, webView->backgroundColor());
+
+    webView->setBaseBackgroundColor(kTransparent);
+    FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:transparent}</style></head></html>", baseURL);
+    // Expected: transparent on top of kTransparent will still be transparent.
+    EXPECT_EQ(kTransparent, webView->backgroundColor());
+
+    LocalFrame* frame = webView->mainFrameImpl()->frame();
+
+    // Creating a new frame view with the background color having 0 alpha.
+    frame->createView(IntSize(1024, 768), Color::transparent, true);
+    EXPECT_EQ(kTransparent, frame->view()->baseBackgroundColor());
+
+    Color kTransparentRed(100, 0, 0, 0);
+    frame->createView(IntSize(1024, 768), kTransparentRed, true);
+    EXPECT_EQ(kTransparentRed, frame->view()->baseBackgroundColor());
 }
 
 TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame)
 {
     const WebColor kBlue = 0xFF0000FF;
-    WebView* webView = WebViewImpl::create(0);
+    FrameTestHelpers::TestWebViewClient webViewClient;
+    WebView* webView = WebViewImpl::create(&webViewClient);
     EXPECT_NE(kBlue, webView->backgroundColor());
     // webView does not have a frame yet, but we should still be able to set the background color.
     webView->setBaseBackgroundColor(kBlue);
     EXPECT_EQ(kBlue, webView->backgroundColor());
+    WebLocalFrameImpl* frame = WebLocalFrameImpl::create(0);
+    webView->setMainFrame(frame);
+    webView->close();
+    frame->close();
 }
 
 TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
@@ -296,8 +333,9 @@ TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
     const int kWidth = 100;
     const int kHeight = 100;
 
-    // Set WebView background to green with alpha.
     WebView* webView = m_webViewHelper.initialize();
+
+    // Set WebView background to green with alpha.
     webView->setBaseBackgroundColor(kAlphaGreen);
     webView->settings()->setShouldClearDocumentBackground(false);
     webView->resize(WebSize(kWidth, kHeight));
@@ -305,17 +343,23 @@ TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
 
     // Set canvas background to red with alpha.
     SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, kWidth, kHeight);
-    bitmap.allocPixels();
-    SkBitmapDevice device(bitmap);
-    SkCanvas canvas(&device);
+    bitmap.allocN32Pixels(kWidth, kHeight);
+    SkCanvas canvas(bitmap);
     canvas.clear(kAlphaRed);
-    webView->paint(&canvas, WebRect(0, 0, kWidth, kHeight));
+
+    GraphicsContext context(&canvas);
+
+    // Paint the root of the main frame in the way that CompositedLayerMapping would.
+    FrameView* view = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
+    RenderLayer* rootLayer = view->renderView()->layer();
+    IntRect paintRect(0, 0, kWidth, kHeight);
+    LayerPaintingInfo paintingInfo(rootLayer, paintRect, PaintBehaviorNormal, LayoutSize());
+    LayerPainter(*rootLayer).paintLayerContents(&context, paintingInfo, PaintLayerPaintingCompositingAllPhases);
 
     // The result should be a blend of red and green.
     SkColor color = bitmap.getColor(kWidth / 2, kHeight / 2);
-    EXPECT_TRUE(WebCore::redChannel(color));
-    EXPECT_TRUE(WebCore::greenChannel(color));
+    EXPECT_TRUE(redChannel(color));
+    EXPECT_TRUE(greenChannel(color));
 }
 
 TEST_F(WebViewTest, FocusIsInactive)
@@ -325,10 +369,10 @@ TEST_F(WebViewTest, FocusIsInactive)
 
     webView->setFocus(true);
     webView->setIsActive(true);
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
 
-    WebCore::HTMLDocument* document = WebCore::toHTMLDocument(frame->frame()->document());
+    HTMLDocument* document = toHTMLDocument(frame->frame()->document());
     EXPECT_TRUE(document->hasFocus());
     webView->setFocus(false);
     webView->setIsActive(false);
@@ -372,14 +416,14 @@ TEST_F(WebViewTest, HitTestResultAtWithPageScale)
     // Image is at top left quandrant, so should not hit it.
     WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
     ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
-    EXPECT_FALSE(negativeResult.node().to<WebElement>().hasTagName("img"));
+    EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
     negativeResult.reset();
 
     // Scale page up 2x so image should occupy the whole viewport.
-    webView->setPageScaleFactor(2.0f, WebPoint(0, 0));
+    webView->setPageScaleFactor(2.0f);
     WebHitTestResult positiveResult = webView->hitTestResultAt(hitPoint);
     ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
-    EXPECT_TRUE(positiveResult.node().to<WebElement>().hasTagName("img"));
+    EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
     positiveResult.reset();
 }
 
@@ -394,8 +438,8 @@ void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& ma
     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
     client.testData().setWebView(webView);
 
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
-    WebCore::FrameView* frameView = frame->frame()->view();
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    FrameView* frameView = frame->frame()->view();
     frameView->layout();
     EXPECT_FALSE(frameView->layoutPending());
     EXPECT_FALSE(frameView->needsLayout());
@@ -415,7 +459,7 @@ void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& ma
     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
 }
 
-TEST_F(WebViewTest, DISABLED_AutoResizeMinimumSize)
+TEST_F(WebViewTest, AutoResizeMinimumSize)
 {
     WebSize minAutoResize(91, 56);
     WebSize maxAutoResize(403, 302);
@@ -453,7 +497,7 @@ TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
 
 // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
 // It seems we can run three AutoResize tests, then the next one breaks.
-TEST_F(WebViewTest, DISABLED_AutoResizeInBetweenSizes)
+TEST_F(WebViewTest, AutoResizeInBetweenSizes)
 {
     WebSize minAutoResize(90, 95);
     WebSize maxAutoResize(200, 300);
@@ -465,7 +509,7 @@ TEST_F(WebViewTest, DISABLED_AutoResizeInBetweenSizes)
                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
 }
 
-TEST_F(WebViewTest, DISABLED_AutoResizeOverflowSizes)
+TEST_F(WebViewTest, AutoResizeOverflowSizes)
 {
     WebSize minAutoResize(90, 95);
     WebSize maxAutoResize(200, 300);
@@ -477,7 +521,7 @@ TEST_F(WebViewTest, DISABLED_AutoResizeOverflowSizes)
                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
 }
 
-TEST_F(WebViewTest, DISABLED_AutoResizeMaxSize)
+TEST_F(WebViewTest, AutoResizeMaxSize)
 {
     WebSize minAutoResize(90, 95);
     WebSize maxAutoResize(200, 300);
@@ -527,13 +571,24 @@ TEST_F(WebViewTest, InputMode)
     testInputMode(WebString("verbatim"), "input_mode_textarea_verbatim.html");
 }
 
+TEST_F(WebViewTest, TextInputInfoWithReplacedElements)
+{
+    std::string url = m_baseURL + "div_with_image.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "div_with_image.html");
+    WebView* webView = m_webViewHelper.initializeAndLoad(url);
+    webView->setInitialFocus(false);
+    WebTextInputInfo info = webView->textInputInfo();
+
+    EXPECT_EQ("foo\xef\xbf\xbc", info.value.utf8());
+}
+
 TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
 {
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
     webView->setInitialFocus(false);
-    webView->setEditableSelectionOffsets(5, 13);
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(5, 13);
     EXPECT_EQ("56789abc", frame->selectionAsText());
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
@@ -545,8 +600,8 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_populated.html"));
     webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_editable_populated.html");
     webView->setInitialFocus(false);
-    webView->setEditableSelectionOffsets(8, 19);
-    frame = toWebFrameImpl(webView->mainFrame());
+    frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(8, 19);
     EXPECT_EQ("89abcdefghi", frame->selectionAsText());
     info = webView->textInputInfo();
     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
@@ -606,8 +661,9 @@ TEST_F(WebViewTest, InsertNewLinePlacementAfterConfirmComposition)
 
     WebVector<WebCompositionUnderline> emptyUnderlines;
 
-    webView->setEditableSelectionOffsets(4, 4);
-    webView->setCompositionFromExistingText(8, 12, emptyUnderlines);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(4, 4);
+    frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
 
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
@@ -637,14 +693,15 @@ TEST_F(WebViewTest, ExtendSelectionAndDelete)
 {
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
     webView->setInitialFocus(false);
-    webView->setEditableSelectionOffsets(10, 10);
-    webView->extendSelectionAndDelete(5, 8);
+    frame->setEditableSelectionOffsets(10, 10);
+    frame->extendSelectionAndDelete(5, 8);
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ("01234ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
     EXPECT_EQ(5, info.selectionStart);
     EXPECT_EQ(5, info.selectionEnd);
-    webView->extendSelectionAndDelete(10, 0);
+    frame->extendSelectionAndDelete(10, 0);
     info = webView->textInputInfo();
     EXPECT_EQ("ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
 }
@@ -655,9 +712,10 @@ TEST_F(WebViewTest, SetCompositionFromExistingText)
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
     webView->setInitialFocus(false);
     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
-    underlines[0] = blink::WebCompositionUnderline(0, 4, 0, false);
-    webView->setEditableSelectionOffsets(4, 10);
-    webView->setCompositionFromExistingText(8, 12, underlines);
+    underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(4, 10);
+    frame->setCompositionFromExistingText(8, 12, underlines);
     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
     EXPECT_EQ(8u, underlineResults[0].startOffset);
     EXPECT_EQ(12u, underlineResults[0].endOffset);
@@ -667,7 +725,7 @@ TEST_F(WebViewTest, SetCompositionFromExistingText)
     EXPECT_EQ(8, info.compositionStart);
     EXPECT_EQ(12, info.compositionEnd);
     WebVector<WebCompositionUnderline> emptyUnderlines;
-    webView->setCompositionFromExistingText(0, 0, emptyUnderlines);
+    frame->setCompositionFromExistingText(0, 0, emptyUnderlines);
     info = webView->textInputInfo();
     EXPECT_EQ(4, info.selectionStart);
     EXPECT_EQ(10, info.selectionEnd);
@@ -681,15 +739,16 @@ TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea)
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
     webView->setInitialFocus(false);
     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
-    underlines[0] = blink::WebCompositionUnderline(0, 4, 0, false);
-    webView->setEditableSelectionOffsets(27, 27);
+    underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(27, 27);
     std::string newLineText("\n");
     webView->confirmComposition(WebString::fromUTF8(newLineText.c_str()));
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
 
-    webView->setEditableSelectionOffsets(31, 31);
-    webView->setCompositionFromExistingText(30, 34, underlines);
+    frame->setEditableSelectionOffsets(31, 31);
+    frame->setCompositionFromExistingText(30, 34, underlines);
     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
     EXPECT_EQ(2u, underlineResults[0].startOffset);
     EXPECT_EQ(6u, underlineResults[0].endOffset);
@@ -730,7 +789,8 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
     EXPECT_EQ(6, info.compositionStart);
     EXPECT_EQ(11, info.compositionEnd);
 
-    webView->setEditableSelectionOffsets(6, 6);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(6, 6);
     info = webView->textInputInfo();
     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
     EXPECT_EQ(6, info.selectionStart);
@@ -738,7 +798,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
     EXPECT_EQ(6, info.compositionStart);
     EXPECT_EQ(11, info.compositionEnd);
 
-    webView->setEditableSelectionOffsets(8, 8);
+    frame->setEditableSelectionOffsets(8, 8);
     info = webView->textInputInfo();
     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
     EXPECT_EQ(8, info.selectionStart);
@@ -746,7 +806,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
     EXPECT_EQ(6, info.compositionStart);
     EXPECT_EQ(11, info.compositionEnd);
 
-    webView->setEditableSelectionOffsets(11, 11);
+    frame->setEditableSelectionOffsets(11, 11);
     info = webView->textInputInfo();
     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
     EXPECT_EQ(11, info.selectionStart);
@@ -754,7 +814,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
     EXPECT_EQ(6, info.compositionStart);
     EXPECT_EQ(11, info.compositionEnd);
 
-    webView->setEditableSelectionOffsets(6, 11);
+    frame->setEditableSelectionOffsets(6, 11);
     info = webView->textInputInfo();
     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
     EXPECT_EQ(6, info.selectionStart);
@@ -762,7 +822,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
     EXPECT_EQ(6, info.compositionStart);
     EXPECT_EQ(11, info.compositionEnd);
 
-    webView->setEditableSelectionOffsets(2, 2);
+    frame->setEditableSelectionOffsets(2, 2);
     info = webView->textInputInfo();
     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
     EXPECT_EQ(2, info.selectionStart);
@@ -777,8 +837,9 @@ TEST_F(WebViewTest, IsSelectionAnchorFirst)
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
     WebFrame* frame = webView->mainFrame();
 
+    webView->setPageScaleFactorLimits(1, 1);
     webView->setInitialFocus(false);
-    webView->setEditableSelectionOffsets(4, 10);
+    frame->setEditableSelectionOffsets(4, 10);
     EXPECT_TRUE(webView->isSelectionAnchorFirst());
     WebRect anchor;
     WebRect focus;
@@ -797,27 +858,16 @@ TEST_F(WebViewTest, HistoryResetScrollAndScaleState)
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
 
     // Make the page scale and scroll with the given paremeters.
-    webViewImpl->setPageScaleFactor(2.0f, WebPoint(116, 84));
-    EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
-    EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
-    EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
-    webViewImpl->page()->mainFrame()->loader().saveDocumentAndScrollState();
-
-    // Confirm that restoring the page state restores the parameters.
-    webViewImpl->setPageScaleFactor(1.5f, WebPoint(16, 24));
-    EXPECT_EQ(1.5f, webViewImpl->pageScaleFactor());
-    EXPECT_EQ(16, webViewImpl->mainFrame()->scrollOffset().width);
-    EXPECT_EQ(24, webViewImpl->mainFrame()->scrollOffset().height);
-    // WebViewImpl::setPageScaleFactor is performing user scrolls, which will set the
-    // wasScrolledByUser flag on the main frame, and prevent restoreScrollPositionAndViewState
-    // from restoring the scrolling position.
-    webViewImpl->page()->mainFrame()->view()->setWasScrolledByUser(false);
-    webViewImpl->page()->mainFrame()->loader().setLoadType(WebCore::FrameLoadTypeBackForward);
-    webViewImpl->page()->mainFrame()->loader().restoreScrollPositionAndViewState();
+    webViewImpl->setPageScaleFactor(2.0f);
+    webViewImpl->setMainFrameScrollOffset(WebPoint(116, 84));
     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
-    webViewImpl->page()->mainFrame()->loader().saveDocumentAndScrollState();
+    LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
+    mainFrameLocal->loader().saveScrollState();
+    EXPECT_EQ(2.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
+    EXPECT_EQ(116, mainFrameLocal->loader().currentItem()->scrollPoint().x());
+    EXPECT_EQ(84, mainFrameLocal->loader().currentItem()->scrollPoint().y());
 
     // Confirm that resetting the page state resets the saved scroll position.
     // The HistoryController treats a page scale factor of 0.0f as special and avoids
@@ -826,13 +876,44 @@ TEST_F(WebViewTest, HistoryResetScrollAndScaleState)
     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
-    webViewImpl->page()->mainFrame()->loader().restoreScrollPositionAndViewState();
-    EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
+    EXPECT_EQ(0.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
+    EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().x());
+    EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().y());
+}
+
+TEST_F(WebViewTest, BackForwardRestoreScroll)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("back_forward_restore_scroll.html"));
+    WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "back_forward_restore_scroll.html");
+    webViewImpl->resize(WebSize(640, 480));
+    webViewImpl->layout();
+
+    // Emulate a user scroll
+    webViewImpl->setMainFrameScrollOffset(WebPoint(0, 900));
+    LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
+    RefPtrWillBePersistent<HistoryItem> item1 = mainFrameLocal->loader().currentItem();
+
+    // Click an anchor
+    mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#a"))));
+    RefPtrWillBePersistent<HistoryItem> item2 = mainFrameLocal->loader().currentItem();
+
+    // Go back, then forward, then back again.
+    mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
+    mainFrameLocal->loader().loadHistoryItem(item2.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
+    mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
+
+    // Click a different anchor
+    mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#b"))));
+    RefPtrWillBePersistent<HistoryItem> item3 = mainFrameLocal->loader().currentItem();
+
+    // Go back, then forward. The scroll position should be properly set on the forward navigation.
+    mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
+    mainFrameLocal->loader().loadHistoryItem(item3.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
-    EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
+    EXPECT_GT(webViewImpl->mainFrame()->scrollOffset().height, 2000);
 }
 
-class EnterFullscreenWebViewClient : public WebViewClient {
+class EnterFullscreenWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     // WebViewClient methods
     virtual bool enterFullScreen() { return true; }
@@ -845,21 +926,20 @@ TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
     EnterFullscreenWebViewClient client;
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, 0, &client);
-    webViewImpl->settings()->setFullScreenEnabled(true);
     webViewImpl->resize(WebSize(640, 480));
     webViewImpl->layout();
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
 
     // Make the page scale and scroll with the given paremeters.
-    webViewImpl->setPageScaleFactor(2.0f, WebPoint(116, 84));
+    webViewImpl->setPageScaleFactor(2.0f);
+    webViewImpl->setMainFrameScrollOffset(WebPoint(116, 84));
     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
 
-    RefPtr<WebCore::Element> element = static_cast<PassRefPtr<WebCore::Element> >(webViewImpl->mainFrame()->document().body());
+    RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element> >(webViewImpl->mainFrame()->document().body());
     webViewImpl->enterFullScreenForElement(element.get());
-    webViewImpl->willEnterFullScreen();
     webViewImpl->didEnterFullScreen();
 
     // Page scale factor must be 1.0 during fullscreen for elements to be sized
@@ -867,11 +947,10 @@ TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
 
     // Make sure fullscreen nesting doesn't disrupt scroll/scale saving.
-    RefPtr<WebCore::Element> otherElement = static_cast<PassRefPtr<WebCore::Element> >(webViewImpl->mainFrame()->document().head());
+    RefPtrWillBeRawPtr<Element> otherElement = static_cast<PassRefPtrWillBeRawPtr<Element> >(webViewImpl->mainFrame()->document().head());
     webViewImpl->enterFullScreenForElement(otherElement.get());
 
     // Confirm that exiting fullscreen restores the parameters.
-    webViewImpl->willExitFullScreen();
     webViewImpl->didExitFullScreen();
     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
@@ -880,22 +959,115 @@ TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
 }
 
-class ContentDetectorClient : public WebViewClient {
+class PrintWebViewClient : public FrameTestHelpers::TestWebViewClient {
+public:
+    PrintWebViewClient()
+        : m_printCalled(false)
+    {
+    }
+
+    // WebViewClient methods
+    virtual void printPage(WebLocalFrame*) override
+    {
+        m_printCalled = true;
+    }
+
+    bool printCalled() const { return m_printCalled; }
+
+private:
+    bool m_printCalled;
+};
+
+
+TEST_F(WebViewTest, PrintWithXHRInFlight)
+{
+    PrintWebViewClient client;
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("print_with_xhr_inflight.html"));
+    WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "print_with_xhr_inflight.html", true, 0, &client);
+
+    ASSERT_EQ(FrameStateComplete, toLocalFrame(webViewImpl->page()->mainFrame())->loader().state());
+    EXPECT_TRUE(client.printCalled());
+    m_webViewHelper.reset();
+}
+
+class DropTask : public WebThread::Task {
+public:
+    explicit DropTask(WebView* webView) : m_webView(webView)
+    {
+    }
+
+    virtual void run() override
+    {
+        const WebPoint clientPoint(0, 0);
+        const WebPoint screenPoint(0, 0);
+        m_webView->dragTargetDrop(clientPoint, screenPoint, 0);
+    }
+
+private:
+    WebView* const m_webView;
+};
+static void DragAndDropURL(WebViewImpl* webView, const std::string& url)
+{
+    WebDragData dragData;
+    dragData.initialize();
+
+    WebDragData::Item item;
+    item.storageType = WebDragData::Item::StorageTypeString;
+    item.stringType = "text/uri-list";
+    item.stringData = WebString::fromUTF8(url);
+    dragData.addItem(item);
+
+    const WebPoint clientPoint(0, 0);
+    const WebPoint screenPoint(0, 0);
+    webView->dragTargetDragEnter(dragData, clientPoint, screenPoint, WebDragOperationCopy, 0);
+    Platform::current()->currentThread()->postTask(new DropTask(webView));
+    FrameTestHelpers::pumpPendingRequestsDoNotUse(webView->mainFrame());
+}
+
+TEST_F(WebViewTest, DragDropURL)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "foo.html");
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "bar.html");
+
+    const std::string fooUrl = m_baseURL + "foo.html";
+    const std::string barUrl = m_baseURL + "bar.html";
+
+    WebViewImpl* webView = m_webViewHelper.initializeAndLoad(fooUrl);
+
+    ASSERT_TRUE(webView);
+
+    // Drag and drop barUrl and verify that we've navigated to it.
+    DragAndDropURL(webView, barUrl);
+    EXPECT_EQ(barUrl, webView->mainFrame()->document().url().string().utf8());
+
+    // Drag and drop fooUrl and verify that we've navigated back to it.
+    DragAndDropURL(webView, fooUrl);
+    EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
+
+    // Disable navigation on drag-and-drop.
+    webView->settingsImpl()->setNavigateOnDragDrop(false);
+
+    // Attempt to drag and drop to barUrl and verify that no navigation has occurred.
+    DragAndDropURL(webView, barUrl);
+    EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
+}
+
+class ContentDetectorClient : public FrameTestHelpers::TestWebViewClient {
 public:
     ContentDetectorClient() { reset(); }
 
-    virtual WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) OVERRIDE
+    virtual WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) override
     {
         m_contentDetectionRequested = true;
         return m_contentDetectionResult;
     }
 
-    virtual void scheduleContentIntent(const WebURL& url) OVERRIDE
+    virtual void scheduleContentIntent(const WebURL& url) override
     {
         m_scheduledIntentURL = url;
     }
 
-    virtual void cancelScheduledContentIntents() OVERRIDE
+    virtual void cancelScheduledContentIntents() override
     {
         m_pendingIntentsCancelled = true;
     }
@@ -923,12 +1095,12 @@ private:
 static bool tapElementById(WebView* webView, WebInputEvent::Type type, const WebString& id)
 {
     ASSERT(webView);
-    RefPtr<WebCore::Element> element = static_cast<PassRefPtr<WebCore::Element> >(webView->mainFrame()->document().getElementById(id));
+    RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element> >(webView->mainFrame()->document().getElementById(id));
     if (!element)
         return false;
 
     element->scrollIntoViewIfNeeded();
-    WebCore::IntPoint center = element->screenRect().center();
+    IntPoint center = element->screenRect().center();
 
     WebGestureEvent event;
     event.type = type;
@@ -1028,34 +1200,37 @@ TEST_F(WebViewTest, LongPressSelection)
 
     WebString target = WebString::fromUTF8("target");
     WebString onselectstartfalse = WebString::fromUTF8("onselectstartfalse");
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
 
     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, onselectstartfalse));
     EXPECT_EQ("", std::string(frame->selectionAsText().utf8().data()));
     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
     EXPECT_EQ("testword", std::string(frame->selectionAsText().utf8().data()));
 }
-#endif
 
-TEST_F(WebViewTest, SelectionOnDisabledInput)
+TEST_F(WebViewTest, BlinkCaretOnTypingAfterLongPress)
 {
-    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_disabled.html"));
-    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "selection_disabled.html", true);
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("blink_caret_on_typing_after_long_press.html"));
+
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "blink_caret_on_typing_after_long_press.html", true);
     webView->resize(WebSize(640, 480));
     webView->layout();
     runPendingTasks();
 
-    std::string testWord = "This text should be selected.";
+    WebString target = WebString::fromUTF8("target");
+    WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webView->mainFrame());
 
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
-    EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
+    EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
+    EXPECT_TRUE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
 
-    size_t location;
-    size_t length;
-    EXPECT_TRUE(toWebViewImpl(webView)->caretOrSelectionRange(&location, &length));
-    EXPECT_EQ(location, 0UL);
-    EXPECT_EQ(length, testWord.length());
+    WebKeyboardEvent keyEvent;
+    keyEvent.type = WebInputEvent::RawKeyDown;
+    webView->handleInputEvent(keyEvent);
+    keyEvent.type = WebInputEvent::KeyUp;
+    webView->handleInputEvent(keyEvent);
+    EXPECT_FALSE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
 }
+#endif
 
 TEST_F(WebViewTest, SelectionOnReadOnlyInput)
 {
@@ -1067,7 +1242,7 @@ TEST_F(WebViewTest, SelectionOnReadOnlyInput)
 
     std::string testWord = "This text should be selected.";
 
-    WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
 
     size_t location;
@@ -1077,23 +1252,53 @@ TEST_F(WebViewTest, SelectionOnReadOnlyInput)
     EXPECT_EQ(length, testWord.length());
 }
 
+static void configueCompositingWebView(WebSettings* settings)
+{
+    settings->setAcceleratedCompositingEnabled(true);
+    settings->setPreferCompositingToLCDTextEnabled(true);
+}
+
+TEST_F(WebViewTest, ShowPressOnTransformedLink)
+{
+    OwnPtr<FrameTestHelpers::TestWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FrameTestHelpers::TestWebViewClient());
+    FrameTestHelpers::WebViewHelper webViewHelper;
+    WebViewImpl* webViewImpl = webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
+
+    int pageWidth = 640;
+    int pageHeight = 480;
+    webViewImpl->resize(WebSize(pageWidth, pageHeight));
+
+    WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
+    FrameTestHelpers::loadHTMLString(webViewImpl->mainFrame(), "<a href='http://www.test.com' style='position: absolute; left: 20px; top: 20px; width: 200px; transform:translateZ(0);'>A link to highlight</a>", baseURL);
+
+    WebGestureEvent event;
+    event.type = WebInputEvent::GestureShowPress;
+    event.x = 20;
+    event.y = 20;
+
+    // Just make sure we don't hit any asserts.
+    webViewImpl->handleInputEvent(event);
+}
+
 class MockAutofillClient : public WebAutofillClient {
 public:
     MockAutofillClient()
         : m_ignoreTextChanges(false)
         , m_textChangesWhileIgnored(0)
-        , m_textChangesWhileNotIgnored(0) { }
+        , m_textChangesWhileNotIgnored(0)
+        , m_userGestureNotificationsCount(0) { }
 
     virtual ~MockAutofillClient() { }
 
-    virtual void setIgnoreTextChanges(bool ignore) OVERRIDE { m_ignoreTextChanges = ignore; }
-    virtual void textFieldDidChange(const WebInputElement&) OVERRIDE
+    virtual void setIgnoreTextChanges(bool ignore) override { m_ignoreTextChanges = ignore; }
+    virtual void textFieldDidChange(const WebFormControlElement&) override
     {
         if (m_ignoreTextChanges)
             ++m_textChangesWhileIgnored;
         else
             ++m_textChangesWhileNotIgnored;
     }
+    virtual void firstUserGestureObserved() override { ++m_userGestureNotificationsCount; }
 
     void clearChangeCounts()
     {
@@ -1103,11 +1308,13 @@ public:
 
     int textChangesWhileIgnored() { return m_textChangesWhileIgnored; }
     int textChangesWhileNotIgnored() { return m_textChangesWhileNotIgnored; }
+    int getUserGestureNotificationsCount() { return m_userGestureNotificationsCount; }
 
 private:
     bool m_ignoreTextChanges;
     int m_textChangesWhileIgnored;
     int m_textChangesWhileNotIgnored;
+    int m_userGestureNotificationsCount;
 };
 
 
@@ -1121,8 +1328,9 @@ TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange)
 
     // Set up a composition that needs to be committed.
     WebVector<WebCompositionUnderline> emptyUnderlines;
-    webView->setEditableSelectionOffsets(4, 10);
-    webView->setCompositionFromExistingText(8, 12, emptyUnderlines);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setEditableSelectionOffsets(4, 10);
+    frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ(4, info.selectionStart);
     EXPECT_EQ(10, info.selectionEnd);
@@ -1178,7 +1386,8 @@ TEST_F(WebViewTest, SetCompositionFromExistingTextTriggersAutofillTextChange)
     WebVector<WebCompositionUnderline> emptyUnderlines;
 
     client.clearChangeCounts();
-    webView->setCompositionFromExistingText(8, 12, emptyUnderlines);
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
 
     WebTextInputInfo info = webView->textInputInfo();
     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
@@ -1214,26 +1423,7 @@ TEST_F(WebViewTest, ShadowRoot)
     }
 }
 
-TEST_F(WebViewTest, HelperPlugin)
-{
-    HelperPluginCreatingWebViewClient client;
-    WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
-
-    WebFrameImpl* frame = toWebFrameImpl(webViewImpl->mainFrame());
-    client.setWebFrameClient(frame->client());
-
-    OwnPtr<WebHelperPlugin> helperPlugin = adoptPtr(webViewImpl->createHelperPlugin("dummy-plugin-type", frame->document()));
-    EXPECT_TRUE(helperPlugin);
-    EXPECT_EQ(0, helperPlugin->getPlugin()); // Invalid plugin type means no plugin.
-
-    helperPlugin.clear();
-    runPendingTasks();
-
-    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
-}
-
-
-class ViewCreatingWebViewClient : public WebViewClient {
+class ViewCreatingWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     ViewCreatingWebViewClient()
         : m_didFocusCalled(false)
@@ -1241,13 +1431,13 @@ public:
     }
 
     // WebViewClient methods
-    virtual WebView* createView(WebFrame*, const WebURLRequest&, const WebWindowFeatures&, const WebString& name, WebNavigationPolicy, bool) OVERRIDE
+    virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&, const WebString& name, WebNavigationPolicy, bool) override
     {
         return m_webViewHelper.initialize(true, 0, 0);
     }
 
     // WebWidgetClient methods
-    virtual void didFocus() OVERRIDE
+    virtual void didFocus() override
     {
         m_didFocusCalled = true;
     }
@@ -1266,22 +1456,22 @@ TEST_F(WebViewTest, FocusExistingFrameOnNavigate)
     FrameTestHelpers::WebViewHelper m_webViewHelper;
     WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
     webViewImpl->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
-    WebFrameImpl* frame = toWebFrameImpl(webViewImpl->mainFrame());
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
     frame->setName("_start");
 
     // Make a request that will open a new window
     WebURLRequest webURLRequest;
     webURLRequest.initialize();
-    WebCore::FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
-    webViewImpl->page()->mainFrame()->loader().load(request);
+    FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
+    toLocalFrame(webViewImpl->page()->mainFrame())->loader().load(request);
     ASSERT_TRUE(client.createdWebView());
     EXPECT_FALSE(client.didFocusCalled());
 
     // Make a request from the new window that will navigate the original window. The original window should be focused.
     WebURLRequest webURLRequestWithTargetStart;
     webURLRequestWithTargetStart.initialize();
-    WebCore::FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
-    toWebViewImpl(client.createdWebView())->page()->mainFrame()->loader().load(requestWithTargetStart);
+    FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
+    toLocalFrame(toWebViewImpl(client.createdWebView())->page()->mainFrame())->loader().load(requestWithTargetStart);
     EXPECT_TRUE(client.didFocusCalled());
 
     m_webViewHelper.reset(); // Remove dependency on locally scoped client.
@@ -1314,12 +1504,12 @@ TEST_F(WebViewTest, DispatchesDomFocusOutDomFocusInOnViewToggleFocus)
 }
 
 #if !ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-static void openDateTimeChooser(WebView* webView, WebCore::HTMLInputElement* inputElement)
+static void openDateTimeChooser(WebView* webView, HTMLInputElement* inputElement)
 {
     inputElement->focus();
 
     WebKeyboardEvent keyEvent;
-    keyEvent.windowsKeyCode = WebCore::VKEY_SPACE;
+    keyEvent.windowsKeyCode = VKEY_SPACE;
     keyEvent.type = WebInputEvent::RawKeyDown;
     keyEvent.setKeyIdentifierFromWindowsKeyCode();
     webView->handleInputEvent(keyEvent);
@@ -1335,9 +1525,9 @@ TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
     URLTestHelpers::registerMockedURLLoad(toKURL(url), "date_time_chooser.html");
     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
 
-    WebCore::Document* document = webViewImpl->mainFrameImpl()->frame()->document();
+    Document* document = webViewImpl->mainFrameImpl()->frame()->document();
 
-    WebCore::HTMLInputElement* inputElement;
+    HTMLInputElement* inputElement;
 
     inputElement = toHTMLInputElement(document->getElementById("date"));
     openDateTimeChooser(webViewImpl, inputElement);
@@ -1393,6 +1583,10 @@ TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
     client.clearChooserCompletion();
     EXPECT_STREQ("", inputElement->value().utf8().data());
+
+    // Clear the WebViewClient from the webViewHelper to avoid use-after-free in the
+    // WebViewHelper destructor.
+    m_webViewHelper.reset();
 }
 #endif
 
@@ -1412,21 +1606,59 @@ TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle)
 
 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");
+    webView->setPageScaleFactorLimits(1, 1);
     webView->resize(WebSize(500, 500));
     webView->layout();
-    WebRect cropRect(300, 125, 100, 50);
+    WebRect cropRect(300, 125, 152, 50);
+    webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
+    EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str());
+    EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str());
+}
 
-    // FIXME: We should test the structure of the data we get back.
-    EXPECT_FALSE(webView->getSmartClipData(cropRect).isEmpty());
+TEST_F(WebViewTest, SmartClipReturnsEmptyStringsWhenUserSelectIsNone)
+{
+    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_user_select_none.html"));
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip_user_select_none.html");
+    webView->setPageScaleFactorLimits(1, 1);
+    webView->resize(WebSize(500, 500));
+    webView->layout();
+    WebRect cropRect(0, 0, 100, 100);
+    webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
+    EXPECT_STREQ("", clipText.utf8().c_str());
+    EXPECT_STREQ("", clipHtml.utf8().c_str());
 }
 
 class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient {
 public:
     CreateChildCounterFrameClient() : m_count(0) { }
-    virtual WebFrame* createChildFrame(WebFrame* parent, const WebString& frameName) OVERRIDE;
+    virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) override;
 
     int count() const { return m_count; }
 
@@ -1434,7 +1666,7 @@ private:
     int m_count;
 };
 
-WebFrame* CreateChildCounterFrameClient::createChildFrame(WebFrame* parent, const WebString& frameName)
+WebFrame* CreateChildCounterFrameClient::createChildFrame(WebLocalFrame* parent, const WebString& frameName)
 {
     ++m_count;
     return TestWebFrameClient::createChildFrame(parent, frameName);
@@ -1454,7 +1686,7 @@ TEST_F(WebViewTest, AddFrameInCloseURLUnload)
     CreateChildCounterFrameClient frameClient;
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
-    m_webViewHelper.webViewImpl()->dispatchUnloadEvent();
+    m_webViewHelper.webViewImpl()->mainFrame()->dispatchUnloadEvent();
     EXPECT_EQ(0, frameClient.count());
     m_webViewHelper.reset();
 }
@@ -1480,10 +1712,10 @@ TEST_F(WebViewTest, AddFrameInChildInNavigateUnload)
     m_webViewHelper.reset();
 }
 
-class TouchEventHandlerWebViewClient : public WebViewClient {
+class TouchEventHandlerWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     // WebWidgetClient methods
-    virtual void hasTouchEventHandlers(bool state) OVERRIDE
+    virtual void hasTouchEventHandlers(bool state) override
     {
         m_hasTouchEventHandlerCount[state]++;
     }
@@ -1504,15 +1736,17 @@ private:
     int m_hasTouchEventHandlerCount[2];
 };
 
-// This test verifies that WebWidgetClient::hasTouchEventHandlers is called accordingly for various
-// calls to Document::did{Add|Remove|Clear}TouchEventHandler. Verifying that those calls are made
-// correctly is the job of LayoutTests/fast/events/touch/touch-handler-count.html.
+// This test verifies that WebWidgetClient::hasTouchEventHandlers is called
+// accordingly for various calls to EventHandlerRegistry::did{Add|Remove|
+// RemoveAll}EventHandler(..., TouchEvent). Verifying that those calls are made
+// correctly is the job of LayoutTests/fast/events/event-handler-count.html.
 TEST_F(WebViewTest, HasTouchEventHandlers)
 {
     TouchEventHandlerWebViewClient client;
     std::string url = m_baseURL + "has_touch_event_handlers.html";
     URLTestHelpers::registerMockedURLLoad(toKURL(url), "has_touch_event_handlers.html");
     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
+    const EventHandlerRegistry::EventHandlerClass touchEvent = EventHandlerRegistry::TouchEvent;
 
     // The page is initialized with at least one no-handlers call.
     // In practice we get two such calls because WebViewHelper::initializeAndLoad first
@@ -1522,103 +1756,450 @@ TEST_F(WebViewTest, HasTouchEventHandlers)
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding the first document handler results in a has-handlers call.
-    WebCore::Document* document = webViewImpl->mainFrameImpl()->frame()->document();
-    document->didAddTouchEventHandler(document);
+    Document* document = webViewImpl->mainFrameImpl()->frame()->document();
+    EventHandlerRegistry* registry = &document->frameHost()->eventHandlerRegistry();
+    registry->didAddEventHandler(*document, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding another handler has no effect.
-    document->didAddTouchEventHandler(document);
+    registry->didAddEventHandler(*document, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Removing the duplicate handler has no effect.
-    document->didRemoveTouchEventHandler(document);
+    registry->didRemoveEventHandler(*document, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Removing the final handler results in a no-handlers call.
-    document->didRemoveTouchEventHandler(document);
+    registry->didRemoveEventHandler(*document, touchEvent);
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding a handler on a div results in a has-handlers call.
-    WebCore::Element* parentDiv = document->getElementById("parentdiv");
+    Element* parentDiv = document->getElementById("parentdiv");
     ASSERT(parentDiv);
-    document->didAddTouchEventHandler(parentDiv);
+    registry->didAddEventHandler(*parentDiv, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding a duplicate handler on the div, clearing all document handlers
     // (of which there are none) and removing the extra handler on the div
     // all have no effect.
-    document->didAddTouchEventHandler(parentDiv);
-    document->didClearTouchEventHandlers(document);
-    document->didRemoveTouchEventHandler(parentDiv);
+    registry->didAddEventHandler(*parentDiv, touchEvent);
+    registry->didRemoveAllEventHandlers(*document);
+    registry->didRemoveEventHandler(*parentDiv, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Removing the final handler on the div results in a no-handlers call.
-    document->didRemoveTouchEventHandler(parentDiv);
+    registry->didRemoveEventHandler(*parentDiv, touchEvent);
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding two handlers then clearing them in a single call results in a
     // has-handlers then no-handlers call.
-    document->didAddTouchEventHandler(parentDiv);
+    registry->didAddEventHandler(*parentDiv, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
-    document->didAddTouchEventHandler(parentDiv);
+    registry->didAddEventHandler(*parentDiv, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
-    document->didClearTouchEventHandlers(parentDiv);
+    registry->didRemoveAllEventHandlers(*parentDiv);
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding a handler inside of a child iframe results in a has-handlers call.
-    WebCore::Element* childFrame = document->getElementById("childframe");
+    Element* childFrame = document->getElementById("childframe");
     ASSERT(childFrame);
-    WebCore::Document* childDocument = toHTMLIFrameElement(childFrame)->contentDocument();
-    WebCore::Element* childDiv = childDocument->getElementById("childdiv");
+    Document* childDocument = toHTMLIFrameElement(childFrame)->contentDocument();
+    Element* childDiv = childDocument->getElementById("childdiv");
     ASSERT(childDiv);
-    childDocument->didAddTouchEventHandler(childDiv);
+    registry->didAddEventHandler(*childDiv, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding and clearing handlers in the parent doc or elsewhere in the child doc
     // has no impact.
-    document->didAddTouchEventHandler(document);
-    document->didAddTouchEventHandler(childFrame);
-    childDocument->didAddTouchEventHandler(childDocument);
-    document->didClearTouchEventHandlers(document);
-    document->didClearTouchEventHandlers(childFrame);
-    childDocument->didClearTouchEventHandlers(childDocument);
+    registry->didAddEventHandler(*document, touchEvent);
+    registry->didAddEventHandler(*childFrame, touchEvent);
+    registry->didAddEventHandler(*childDocument, touchEvent);
+    registry->didRemoveAllEventHandlers(*document);
+    registry->didRemoveAllEventHandlers(*childFrame);
+    registry->didRemoveAllEventHandlers(*childDocument);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Removing the final handler inside the child frame results in a no-handlers call.
-    childDocument->didRemoveTouchEventHandler(childDiv);
+    registry->didRemoveAllEventHandlers(*childDiv);
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding a handler inside the child frame results in a has-handlers call.
-    childDocument->didAddTouchEventHandler(childDocument);
+    registry->didAddEventHandler(*childDocument, touchEvent);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Adding a handler in the parent document and removing the one in the frame
     // has no effect.
-    document->didAddTouchEventHandler(childFrame);
-    childDocument->didRemoveTouchEventHandler(childDocument);
-    childDocument->didClearTouchEventHandlers(childDocument);
-    document->didClearTouchEventHandlers(document);
+    registry->didAddEventHandler(*childFrame, touchEvent);
+    registry->didRemoveEventHandler(*childDocument, touchEvent);
+    registry->didRemoveAllEventHandlers(*childDocument);
+    registry->didRemoveAllEventHandlers(*document);
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
 
     // Now removing the handler in the parent document results in a no-handlers call.
-    document->didRemoveTouchEventHandler(childFrame);
+    registry->didRemoveEventHandler(*childFrame, touchEvent);
     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
+
+    // Free the webView before the TouchEventHandlerWebViewClient gets freed.
+    m_webViewHelper.reset();
 }
 
+// This test checks that deleting nodes which have only non-JS-registered touch
+// handlers also removes them from the event handler registry. Note that this
+// is different from detaching and re-attaching the same node, which is covered
+// by layout tests under fast/events/.
+TEST_F(WebViewTest, DeleteElementWithRegisteredHandler)
+{
+    std::string url = m_baseURL + "simple_div.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "simple_div.html");
+    WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true);
+
+    RefPtrWillBePersistent<Document> document = webViewImpl->mainFrameImpl()->frame()->document();
+    Element* div = document->getElementById("div");
+    EventHandlerRegistry& registry = document->frameHost()->eventHandlerRegistry();
+
+    registry.didAddEventHandler(*div, EventHandlerRegistry::ScrollEvent);
+    EXPECT_TRUE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
+
+    TrackExceptionState exceptionState;
+    div->remove(exceptionState);
+#if ENABLE(OILPAN)
+    // For oilpan we have to force a GC to ensure the event handlers have been removed when
+    // checking below. We do a precise GC (collectAllGarbage does not scan the stack)
+    // to ensure the div element dies. This is also why the Document is in a Persistent
+    // since we want that to stay around.
+    Heap::collectAllGarbage();
+#endif
+    EXPECT_FALSE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
+}
+
+static WebRect ExpectedRootBounds(Document* document, float scaleFactor)
+{
+    Element* element = document->getElementById("root");
+    if (!element)
+        element = document->getElementById("target");
+    if (element->hasTagName(HTMLNames::iframeTag))
+        return ExpectedRootBounds(toHTMLIFrameElement(element)->contentDocument(), scaleFactor);
+
+    IntRect boundingBox;
+    if (element->hasTagName(HTMLNames::htmlTag))
+        boundingBox = IntRect(IntPoint(0, 0), document->frame()->view()->contentsSize());
+    else
+        boundingBox = element->pixelSnappedBoundingBox();
+    boundingBox = document->frame()->view()->contentsToWindow(boundingBox);
+    boundingBox.scale(scaleFactor);
+    return boundingBox;
+}
+
+void WebViewTest::testSelectionRootBounds(const char* htmlFile, float pageScaleFactor)
+{
+    std::string url = m_baseURL + htmlFile;
+
+    WebView* webView = m_webViewHelper.initializeAndLoad(url, true);
+    webView->resize(WebSize(640, 480));
+    webView->setPageScaleFactor(pageScaleFactor);
+    webView->layout();
+    runPendingTasks();
+
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
+    HTMLDocument* document = toHTMLDocument(frame->frame()->document());
+
+    WebRect expectedRootBounds = ExpectedRootBounds(document, webView->pageScaleFactor());
+    WebRect actualRootBounds;
+    webView->getSelectionRootBounds(actualRootBounds);
+    ASSERT_EQ(expectedRootBounds, actualRootBounds);
+
+    WebRect anchor, focus;
+    webView->selectionBounds(anchor, focus);
+    IntRect expectedIntRect = expectedRootBounds;
+    ASSERT_TRUE(expectedIntRect.contains(anchor));
+    // The "overflow" tests have the focus boundary outside of the element box.
+    ASSERT_EQ(url.find("overflow") == std::string::npos, expectedIntRect.contains(focus));
+}
+
+TEST_F(WebViewTest, GetSelectionRootBounds)
+{
+    // Register all the pages we will be using.
+    registerMockedHttpURLLoad("select_range_basic.html");
+    registerMockedHttpURLLoad("select_range_div_editable.html");
+    registerMockedHttpURLLoad("select_range_scroll.html");
+    registerMockedHttpURLLoad("select_range_span_editable.html");
+    registerMockedHttpURLLoad("select_range_input.html");
+    registerMockedHttpURLLoad("select_range_input_overflow.html");
+    registerMockedHttpURLLoad("select_range_textarea.html");
+    registerMockedHttpURLLoad("select_range_textarea_overflow.html");
+    registerMockedHttpURLLoad("select_range_iframe.html");
+    registerMockedHttpURLLoad("select_range_iframe_div_editable.html");
+    registerMockedHttpURLLoad("select_range_iframe_scroll.html");
+    registerMockedHttpURLLoad("select_range_iframe_span_editable.html");
+    registerMockedHttpURLLoad("select_range_iframe_input.html");
+    registerMockedHttpURLLoad("select_range_iframe_input_overflow.html");
+    registerMockedHttpURLLoad("select_range_iframe_textarea.html");
+    registerMockedHttpURLLoad("select_range_iframe_textarea_overflow.html");
+
+    // Test with simple pages.
+    testSelectionRootBounds("select_range_basic.html", 1.0f);
+    testSelectionRootBounds("select_range_div_editable.html", 1.0f);
+    testSelectionRootBounds("select_range_scroll.html", 1.0f);
+    testSelectionRootBounds("select_range_span_editable.html", 1.0f);
+    testSelectionRootBounds("select_range_input.html", 1.0f);
+    testSelectionRootBounds("select_range_input_overflow.html", 1.0f);
+    testSelectionRootBounds("select_range_textarea.html", 1.0f);
+    testSelectionRootBounds("select_range_textarea_overflow.html", 1.0f);
+
+    // Test with the same pages as above in iframes.
+    testSelectionRootBounds("select_range_iframe.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_div_editable.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_scroll.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_span_editable.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_input.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_input_overflow.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_textarea.html", 1.0f);
+    testSelectionRootBounds("select_range_iframe_textarea_overflow.html", 1.0f);
+
+    // Basic page with scale factor.
+    testSelectionRootBounds("select_range_basic.html", 0.0f);
+    testSelectionRootBounds("select_range_basic.html", 0.1f);
+    testSelectionRootBounds("select_range_basic.html", 1.5f);
+    testSelectionRootBounds("select_range_basic.html", 2.0f);
+}
+
+TEST_F(WebViewTest, GetSelectionRootBoundsBrokenHeight)
+{
+    WebSize contentSize = WebSize(640, 480);
+
+    registerMockedHttpURLLoad("select_range_basic_broken_height.html");
+
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "select_range_basic_broken_height.html", true);
+    webView->resize(contentSize);
+    webView->setPageScaleFactor(1.0f, WebPoint(0, 0));
+    webView->layout();
+    runPendingTasks();
+
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
+
+    WebRect expectedRootBounds = WebRect(0, 0, contentSize.width, contentSize.height);
+    WebRect actualRootBounds;
+    webView->getSelectionRootBounds(actualRootBounds);
+    ASSERT_EQ(expectedRootBounds, actualRootBounds);
+}
+
+class NonUserInputTextUpdateWebViewClient : public FrameTestHelpers::TestWebViewClient {
+public:
+    NonUserInputTextUpdateWebViewClient() : m_textIsUpdated(false) { }
+
+    // WebWidgetClient methods
+    virtual void didUpdateTextOfFocusedElementByNonUserInput() override
+    {
+        m_textIsUpdated = true;
+    }
+
+    void reset()
+    {
+        m_textIsUpdated = false;
+    }
+
+    bool textIsUpdated() const
+    {
+        return m_textIsUpdated;
+    }
+
+private:
+    int m_textIsUpdated;
+};
+
+// This test verifies that WebWidgetClient::didUpdateTextOfFocusedElementByNonUserInput is
+// called iff value of a focused element is modified via script.
+TEST_F(WebViewTest, NonUserInputTextUpdate)
+{
+    NonUserInputTextUpdateWebViewClient client;
+    std::string url = m_baseURL + "non_user_input_text_update.html";
+    URLTestHelpers::registerMockedURLLoad(toKURL(url), "non_user_input_text_update.html");
+    WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
+    webViewImpl->setInitialFocus(false);
+
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
+    HTMLDocument* document = toHTMLDocument(frame->frame()->document());
+
+    // (A) <input>
+    // (A.1) Focused and value is changed by script.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+
+    HTMLInputElement* inputElement = toHTMLInputElement(document->getElementById("input"));
+    document->setFocusedElement(inputElement);
+    webViewImpl->setFocus(true);
+    EXPECT_EQ(document->focusedElement(), static_cast<Element*>(inputElement));
+
+    // Emulate value change from script.
+    inputElement->setValue("testA");
+    EXPECT_TRUE(client.textIsUpdated());
+    WebTextInputInfo info = webViewImpl->textInputInfo();
+    EXPECT_EQ("testA", std::string(info.value.utf8().data()));
+
+    // (A.2) Focused and user input modifies value.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+
+    WebVector<WebCompositionUnderline> emptyUnderlines;
+    webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
+    webViewImpl->confirmComposition(WebWidget::KeepSelection);
+    EXPECT_FALSE(client.textIsUpdated());
+    info = webViewImpl->textInputInfo();
+    EXPECT_EQ("testA2", std::string(info.value.utf8().data()));
+
+    // (A.3) Unfocused and value is changed by script.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+    document->setFocusedElement(nullptr);
+    webViewImpl->setFocus(false);
+    EXPECT_NE(document->focusedElement(), static_cast<Element*>(inputElement));
+    inputElement->setValue("testA3");
+    EXPECT_FALSE(client.textIsUpdated());
+
+    // (B) <textarea>
+    // (B.1) Focused and value is changed by script.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+    HTMLTextAreaElement* textAreaElement = toHTMLTextAreaElement(document->getElementById("textarea"));
+    document->setFocusedElement(textAreaElement);
+    webViewImpl->setFocus(true);
+    EXPECT_EQ(document->focusedElement(), static_cast<Element*>(textAreaElement));
+    textAreaElement->setValue("testB");
+    EXPECT_TRUE(client.textIsUpdated());
+    info = webViewImpl->textInputInfo();
+    EXPECT_EQ("testB", std::string(info.value.utf8().data()));
+
+    // (B.2) Focused and user input modifies value.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+    webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
+    webViewImpl->confirmComposition(WebWidget::KeepSelection);
+    info = webViewImpl->textInputInfo();
+    EXPECT_EQ("testB2", std::string(info.value.utf8().data()));
+
+    // (B.3) Unfocused and value is changed by script.
+    client.reset();
+    EXPECT_FALSE(client.textIsUpdated());
+    document->setFocusedElement(nullptr);
+    webViewImpl->setFocus(false);
+    EXPECT_NE(document->focusedElement(), static_cast<Element*>(textAreaElement));
+    inputElement->setValue("testB3");
+    EXPECT_FALSE(client.textIsUpdated());
+
+    // Free the webView before freeing the NonUserInputTextUpdateWebViewClient.
+    m_webViewHelper.reset();
+}
+
+// Check that the WebAutofillClient is correctly notified about first user
+// gestures after load, following various input events.
+TEST_F(WebViewTest, FirstUserGestureObservedKeyEvent)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
+    MockAutofillClient client;
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
+    webView->setAutofillClient(&client);
+    webView->setInitialFocus(false);
+
+    EXPECT_EQ(0, client.getUserGestureNotificationsCount());
+
+    WebKeyboardEvent keyEvent;
+    keyEvent.windowsKeyCode = VKEY_SPACE;
+    keyEvent.type = WebInputEvent::RawKeyDown;
+    keyEvent.setKeyIdentifierFromWindowsKeyCode();
+    webView->handleInputEvent(keyEvent);
+    keyEvent.type = WebInputEvent::KeyUp;
+    webView->handleInputEvent(keyEvent);
+
+    EXPECT_EQ(1, client.getUserGestureNotificationsCount());
+    webView->setAutofillClient(0);
+}
+
+TEST_F(WebViewTest, FirstUserGestureObservedMouseEvent)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
+    MockAutofillClient client;
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
+    webView->setAutofillClient(&client);
+    webView->setInitialFocus(false);
+
+    EXPECT_EQ(0, client.getUserGestureNotificationsCount());
+
+    WebMouseEvent mouseEvent;
+    mouseEvent.button = WebMouseEvent::ButtonLeft;
+    mouseEvent.x = 1;
+    mouseEvent.y = 1;
+    mouseEvent.clickCount = 1;
+    mouseEvent.type = WebInputEvent::MouseDown;
+    webView->handleInputEvent(mouseEvent);
+    mouseEvent.type = WebInputEvent::MouseUp;
+    webView->handleInputEvent(mouseEvent);
+
+    EXPECT_EQ(1, client.getUserGestureNotificationsCount());
+    webView->setAutofillClient(0);
+}
+
+TEST_F(WebViewTest, FirstUserGestureObservedGestureTap)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
+    MockAutofillClient client;
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
+    webView->setAutofillClient(&client);
+    webView->setInitialFocus(false);
+
+    EXPECT_EQ(0, client.getUserGestureNotificationsCount());
+
+    EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
+
+    EXPECT_EQ(1, client.getUserGestureNotificationsCount());
+    webView->setAutofillClient(0);
+}
+
+TEST_F(WebViewTest, CompareSelectAllToContentAsText)
+{
+    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
+    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
+
+    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
+    frame->executeScript(WebScriptSource(WebString::fromUTF8("document.execCommand('SelectAll', false, null)")));
+    std::string actual = frame->selectionAsText().utf8();
+
+    const int kMaxOutputCharacters = 1024;
+    std::string expected = frame->contentAsText(kMaxOutputCharacters).utf8();
+    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);
+
+    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