Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / WebViewTest.cpp
1 /*
2  * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "public/web/WebView.h"
33
34 #include "core/dom/Document.h"
35 #include "core/dom/Element.h"
36 #include "core/editing/FrameSelection.h"
37 #include "core/frame/EventHandlerRegistry.h"
38 #include "core/frame/FrameView.h"
39 #include "core/frame/LocalFrame.h"
40 #include "core/frame/Settings.h"
41 #include "core/html/HTMLDocument.h"
42 #include "core/html/HTMLIFrameElement.h"
43 #include "core/html/HTMLInputElement.h"
44 #include "core/html/HTMLTextAreaElement.h"
45 #include "core/loader/FrameLoadRequest.h"
46 #include "core/page/Chrome.h"
47 #include "core/page/Page.h"
48 #include "core/paint/LayerPainter.h"
49 #include "core/rendering/RenderLayer.h"
50 #include "core/rendering/RenderView.h"
51 #include "core/testing/URLTestHelpers.h"
52 #include "platform/KeyboardCodes.h"
53 #include "platform/geometry/IntSize.h"
54 #include "platform/graphics/Color.h"
55 #include "public/platform/Platform.h"
56 #include "public/platform/WebClipboard.h"
57 #include "public/platform/WebDragData.h"
58 #include "public/platform/WebSize.h"
59 #include "public/platform/WebThread.h"
60 #include "public/platform/WebUnitTestSupport.h"
61 #include "public/web/WebAutofillClient.h"
62 #include "public/web/WebContentDetectionResult.h"
63 #include "public/web/WebDateTimeChooserCompletion.h"
64 #include "public/web/WebDocument.h"
65 #include "public/web/WebDragOperation.h"
66 #include "public/web/WebElement.h"
67 #include "public/web/WebFrame.h"
68 #include "public/web/WebFrameClient.h"
69 #include "public/web/WebHitTestResult.h"
70 #include "public/web/WebInputEvent.h"
71 #include "public/web/WebScriptSource.h"
72 #include "public/web/WebSettings.h"
73 #include "public/web/WebViewClient.h"
74 #include "public/web/WebWidget.h"
75 #include "public/web/WebWidgetClient.h"
76 #include "third_party/skia/include/core/SkBitmap.h"
77 #include "third_party/skia/include/core/SkBitmapDevice.h"
78 #include "third_party/skia/include/core/SkCanvas.h"
79 #include "web/WebLocalFrameImpl.h"
80 #include "web/WebSettingsImpl.h"
81 #include "web/WebViewImpl.h"
82 #include "web/tests/FrameTestHelpers.h"
83 #include <gtest/gtest.h>
84
85 using namespace blink;
86 using blink::FrameTestHelpers::loadFrame;
87 using blink::FrameTestHelpers::runPendingTasks;
88 using blink::URLTestHelpers::toKURL;
89
90 namespace {
91
92 enum HorizontalScrollbarState {
93     NoHorizontalScrollbar,
94     VisibleHorizontalScrollbar,
95 };
96
97 enum VerticalScrollbarState {
98     NoVerticalScrollbar,
99     VisibleVerticalScrollbar,
100 };
101
102 class TestData {
103 public:
104     void setWebView(WebView* webView) { m_webView = toWebViewImpl(webView); }
105     void setSize(const WebSize& newSize) { m_size = newSize; }
106     HorizontalScrollbarState horizontalScrollbarState() const
107     {
108         return m_webView->hasHorizontalScrollbar() ? VisibleHorizontalScrollbar: NoHorizontalScrollbar;
109     }
110     VerticalScrollbarState verticalScrollbarState() const
111     {
112         return m_webView->hasVerticalScrollbar() ? VisibleVerticalScrollbar : NoVerticalScrollbar;
113     }
114     int width() const { return m_size.width; }
115     int height() const { return m_size.height; }
116
117 private:
118     WebSize m_size;
119     WebViewImpl* m_webView;
120 };
121
122 class AutoResizeWebViewClient : public FrameTestHelpers::TestWebViewClient {
123 public:
124     // WebViewClient methods
125     virtual void didAutoResize(const WebSize& newSize) { m_testData.setSize(newSize); }
126
127     // Local methods
128     TestData& testData() { return m_testData; }
129
130 private:
131     TestData m_testData;
132 };
133
134 class SaveImageFromDataURLWebViewClient : public FrameTestHelpers::TestWebViewClient {
135 public:
136     // WebViewClient methods
137     virtual void saveImageFromDataURL(const WebString& dataURL) { m_dataURL = dataURL; }
138
139     // Local methods
140     const WebString& result() const { return m_dataURL; }
141     void reset() { m_dataURL = WebString(); }
142
143 private:
144     WebString m_dataURL;
145 };
146
147 class TapHandlingWebViewClient : public FrameTestHelpers::TestWebViewClient {
148 public:
149     // WebViewClient methods
150     virtual void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled)
151     {
152         if (event.type == WebInputEvent::GestureTap) {
153             m_tapX = event.x;
154             m_tapY = event.y;
155         } else if (event.type == WebInputEvent::GestureLongPress) {
156             m_longpressX = event.x;
157             m_longpressY = event.y;
158         }
159     }
160
161     // Local methods
162     void reset()
163     {
164         m_tapX = -1;
165         m_tapY = -1;
166         m_longpressX = -1;
167         m_longpressY = -1;
168     }
169     int tapX() { return m_tapX; }
170     int tapY() { return m_tapY; }
171     int longpressX() { return m_longpressX; }
172     int longpressY() { return m_longpressY; }
173
174 private:
175     int m_tapX;
176     int m_tapY;
177     int m_longpressX;
178     int m_longpressY;
179 };
180
181 class DateTimeChooserWebViewClient : public FrameTestHelpers::TestWebViewClient {
182 public:
183     WebDateTimeChooserCompletion* chooserCompletion()
184     {
185         return m_chooserCompletion;
186     }
187
188     void clearChooserCompletion()
189     {
190         m_chooserCompletion = 0;
191     }
192
193     // WebViewClient methods
194     virtual bool openDateTimeChooser(const WebDateTimeChooserParams&, WebDateTimeChooserCompletion* chooser_completion) override
195     {
196         m_chooserCompletion = chooser_completion;
197         return true;
198     }
199
200 private:
201     WebDateTimeChooserCompletion* m_chooserCompletion;
202
203 };
204
205 class WebViewTest : public testing::Test {
206 public:
207     WebViewTest()
208         : m_baseURL("http://www.test.com/")
209     {
210     }
211
212     virtual void TearDown()
213     {
214         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
215     }
216
217 protected:
218     void registerMockedHttpURLLoad(const std::string& fileName)
219     {
220         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
221     }
222
223     void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
224                         const std::string& pageWidth, const std::string& pageHeight,
225                         int expectedWidth, int expectedHeight,
226                         HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState);
227
228     void testTextInputType(WebTextInputType expectedType, const std::string& htmlFile);
229     void testInputMode(const WebString& expectedInputMode, const std::string& htmlFile);
230     void testSelectionRootBounds(const char* htmlFile, float pageScaleFactor);
231
232     std::string m_baseURL;
233     FrameTestHelpers::WebViewHelper m_webViewHelper;
234 };
235
236 TEST_F(WebViewTest, SaveImageAt)
237 {
238     SaveImageFromDataURLWebViewClient client;
239
240     std::string url = m_baseURL + "image-with-data-url.html";
241     URLTestHelpers::registerMockedURLLoad(toKURL(url), "image-with-data-url.html");
242     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
243     webView->resize(WebSize(400, 400));
244
245     client.reset();
246     webView->saveImageAt(WebPoint(1, 1));
247     EXPECT_EQ(WebString::fromUTF8("data:image/gif;base64"
248         ",R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), client.result());
249
250     client.reset();
251     webView->saveImageAt(WebPoint(1, 2));
252     EXPECT_EQ(WebString(), client.result());
253
254     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
255 };
256
257 TEST_F(WebViewTest, CopyImageAt)
258 {
259     std::string url = m_baseURL + "canvas-copy-image.html";
260     URLTestHelpers::registerMockedURLLoad(toKURL(url), "canvas-copy-image.html");
261     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
262     webView->resize(WebSize(400, 400));
263     webView->copyImageAt(WebPoint(50, 50));
264
265     WebData data = Platform::current()->clipboard()->readImage(WebClipboard::Buffer());
266     WebImage image = WebImage::fromData(data, WebSize());
267
268     SkAutoLockPixels autoLock(image.getSkBitmap());
269     EXPECT_EQ(SkColorSetARGB(255, 255, 0, 0), image.getSkBitmap().getColor(0, 0));
270 };
271
272 TEST_F(WebViewTest, SetBaseBackgroundColor)
273 {
274     const WebColor kWhite    = 0xFFFFFFFF;
275     const WebColor kBlue     = 0xFF0000FF;
276     const WebColor kDarkCyan = 0xFF227788;
277     const WebColor kTranslucentPutty = 0x80BFB196;
278     const WebColor kTransparent = 0x00000000;
279
280     WebViewImpl* webView = m_webViewHelper.initialize();
281     EXPECT_EQ(kWhite, webView->backgroundColor());
282
283     webView->setBaseBackgroundColor(kBlue);
284     EXPECT_EQ(kBlue, webView->backgroundColor());
285
286     WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
287     FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:#227788}</style></head></html>", baseURL);
288     EXPECT_EQ(kDarkCyan, webView->backgroundColor());
289
290     FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:rgba(255,0,0,0.5)}</style></head></html>", baseURL);
291     // Expected: red (50% alpha) blended atop base of kBlue.
292     EXPECT_EQ(0xFF7F0080, webView->backgroundColor());
293
294     webView->setBaseBackgroundColor(kTranslucentPutty);
295     // Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha.
296     EXPECT_EQ(0xBFE93B32, webView->backgroundColor());
297
298     webView->setBaseBackgroundColor(kTransparent);
299     FrameTestHelpers::loadHTMLString(webView->mainFrame(), "<html><head><style>body {background-color:transparent}</style></head></html>", baseURL);
300     // Expected: transparent on top of kTransparent will still be transparent.
301     EXPECT_EQ(kTransparent, webView->backgroundColor());
302
303     LocalFrame* frame = webView->mainFrameImpl()->frame();
304
305     // Creating a new frame view with the background color having 0 alpha.
306     frame->createView(IntSize(1024, 768), Color::transparent, true);
307     EXPECT_EQ(kTransparent, frame->view()->baseBackgroundColor());
308
309     Color kTransparentRed(100, 0, 0, 0);
310     frame->createView(IntSize(1024, 768), kTransparentRed, true);
311     EXPECT_EQ(kTransparentRed, frame->view()->baseBackgroundColor());
312 }
313
314 TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame)
315 {
316     const WebColor kBlue = 0xFF0000FF;
317     FrameTestHelpers::TestWebViewClient webViewClient;
318     WebView* webView = WebViewImpl::create(&webViewClient);
319     EXPECT_NE(kBlue, webView->backgroundColor());
320     // webView does not have a frame yet, but we should still be able to set the background color.
321     webView->setBaseBackgroundColor(kBlue);
322     EXPECT_EQ(kBlue, webView->backgroundColor());
323     WebLocalFrameImpl* frame = WebLocalFrameImpl::create(0);
324     webView->setMainFrame(frame);
325     webView->close();
326     frame->close();
327 }
328
329 TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
330 {
331     const WebColor kAlphaRed = 0x80FF0000;
332     const WebColor kAlphaGreen = 0x8000FF00;
333     const int kWidth = 100;
334     const int kHeight = 100;
335
336     WebView* webView = m_webViewHelper.initialize();
337
338     // Set WebView background to green with alpha.
339     webView->setBaseBackgroundColor(kAlphaGreen);
340     webView->settings()->setShouldClearDocumentBackground(false);
341     webView->resize(WebSize(kWidth, kHeight));
342     webView->layout();
343
344     // Set canvas background to red with alpha.
345     SkBitmap bitmap;
346     bitmap.allocN32Pixels(kWidth, kHeight);
347     SkCanvas canvas(bitmap);
348     canvas.clear(kAlphaRed);
349
350     GraphicsContext context(&canvas);
351
352     // Paint the root of the main frame in the way that CompositedLayerMapping would.
353     FrameView* view = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
354     RenderLayer* rootLayer = view->renderView()->layer();
355     IntRect paintRect(0, 0, kWidth, kHeight);
356     LayerPaintingInfo paintingInfo(rootLayer, paintRect, PaintBehaviorNormal, LayoutSize());
357     LayerPainter(*rootLayer).paintLayerContents(&context, paintingInfo, PaintLayerPaintingCompositingAllPhases);
358
359     // The result should be a blend of red and green.
360     SkColor color = bitmap.getColor(kWidth / 2, kHeight / 2);
361     EXPECT_TRUE(redChannel(color));
362     EXPECT_TRUE(greenChannel(color));
363 }
364
365 TEST_F(WebViewTest, FocusIsInactive)
366 {
367     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
368     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
369
370     webView->setFocus(true);
371     webView->setIsActive(true);
372     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
373     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
374
375     HTMLDocument* document = toHTMLDocument(frame->frame()->document());
376     EXPECT_TRUE(document->hasFocus());
377     webView->setFocus(false);
378     webView->setIsActive(false);
379     EXPECT_FALSE(document->hasFocus());
380     webView->setFocus(true);
381     webView->setIsActive(true);
382     EXPECT_TRUE(document->hasFocus());
383     webView->setFocus(true);
384     webView->setIsActive(false);
385     EXPECT_FALSE(document->hasFocus());
386     webView->setFocus(false);
387     webView->setIsActive(true);
388     EXPECT_FALSE(document->hasFocus());
389 }
390
391 TEST_F(WebViewTest, ActiveState)
392 {
393     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
394     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
395
396     ASSERT_TRUE(webView);
397
398     webView->setIsActive(true);
399     EXPECT_TRUE(webView->isActive());
400
401     webView->setIsActive(false);
402     EXPECT_FALSE(webView->isActive());
403
404     webView->setIsActive(true);
405     EXPECT_TRUE(webView->isActive());
406 }
407
408 TEST_F(WebViewTest, HitTestResultAtWithPageScale)
409 {
410     std::string url = m_baseURL + "specify_size.html?" + "50px" + ":" + "50px";
411     URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
412     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
413     webView->resize(WebSize(100, 100));
414     WebPoint hitPoint(75, 75);
415
416     // Image is at top left quandrant, so should not hit it.
417     WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
418     ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
419     EXPECT_FALSE(negativeResult.node().to<WebElement>().hasHTMLTagName("img"));
420     negativeResult.reset();
421
422     // Scale page up 2x so image should occupy the whole viewport.
423     webView->setPageScaleFactor(2.0f);
424     WebHitTestResult positiveResult = webView->hitTestResultAt(hitPoint);
425     ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
426     EXPECT_TRUE(positiveResult.node().to<WebElement>().hasHTMLTagName("img"));
427     positiveResult.reset();
428 }
429
430 void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
431                                  const std::string& pageWidth, const std::string& pageHeight,
432                                  int expectedWidth, int expectedHeight,
433                                  HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState)
434 {
435     AutoResizeWebViewClient client;
436     std::string url = m_baseURL + "specify_size.html?" + pageWidth + ":" + pageHeight;
437     URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
438     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
439     client.testData().setWebView(webView);
440
441     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
442     FrameView* frameView = frame->frame()->view();
443     frameView->layout();
444     EXPECT_FALSE(frameView->layoutPending());
445     EXPECT_FALSE(frameView->needsLayout());
446
447     webView->enableAutoResizeMode(minAutoResize, maxAutoResize);
448     EXPECT_TRUE(frameView->layoutPending());
449     EXPECT_TRUE(frameView->needsLayout());
450     frameView->layout();
451
452     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
453
454     EXPECT_EQ(expectedWidth, client.testData().width());
455     EXPECT_EQ(expectedHeight, client.testData().height());
456     EXPECT_EQ(expectedHorizontalState, client.testData().horizontalScrollbarState());
457     EXPECT_EQ(expectedVerticalState, client.testData().verticalScrollbarState());
458
459     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
460 }
461
462 TEST_F(WebViewTest, AutoResizeMinimumSize)
463 {
464     WebSize minAutoResize(91, 56);
465     WebSize maxAutoResize(403, 302);
466     std::string pageWidth = "91px";
467     std::string pageHeight = "56px";
468     int expectedWidth = 91;
469     int expectedHeight = 56;
470     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
471                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
472 }
473
474 TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth)
475 {
476     WebSize minAutoResize(90, 95);
477     WebSize maxAutoResize(90, 100);
478     std::string pageWidth = "60px";
479     std::string pageHeight = "200px";
480     int expectedWidth = 90;
481     int expectedHeight = 100;
482     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
483                    expectedWidth, expectedHeight, NoHorizontalScrollbar, VisibleVerticalScrollbar);
484 }
485
486 TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
487 {
488     WebSize minAutoResize(90, 100);
489     WebSize maxAutoResize(200, 100);
490     std::string pageWidth = "300px";
491     std::string pageHeight = "80px";
492     int expectedWidth = 200;
493     int expectedHeight = 100;
494     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
495                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, NoVerticalScrollbar);
496 }
497
498 // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
499 // It seems we can run three AutoResize tests, then the next one breaks.
500 TEST_F(WebViewTest, AutoResizeInBetweenSizes)
501 {
502     WebSize minAutoResize(90, 95);
503     WebSize maxAutoResize(200, 300);
504     std::string pageWidth = "100px";
505     std::string pageHeight = "200px";
506     int expectedWidth = 100;
507     int expectedHeight = 200;
508     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
509                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
510 }
511
512 TEST_F(WebViewTest, AutoResizeOverflowSizes)
513 {
514     WebSize minAutoResize(90, 95);
515     WebSize maxAutoResize(200, 300);
516     std::string pageWidth = "300px";
517     std::string pageHeight = "400px";
518     int expectedWidth = 200;
519     int expectedHeight = 300;
520     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
521                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
522 }
523
524 TEST_F(WebViewTest, AutoResizeMaxSize)
525 {
526     WebSize minAutoResize(90, 95);
527     WebSize maxAutoResize(200, 300);
528     std::string pageWidth = "200px";
529     std::string pageHeight = "300px";
530     int expectedWidth = 200;
531     int expectedHeight = 300;
532     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
533                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
534 }
535
536 void WebViewTest::testTextInputType(WebTextInputType expectedType, const std::string& htmlFile)
537 {
538     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
539     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
540     webView->setInitialFocus(false);
541     EXPECT_EQ(expectedType, webView->textInputInfo().type);
542 }
543
544 TEST_F(WebViewTest, TextInputType)
545 {
546     testTextInputType(WebTextInputTypeText, "input_field_default.html");
547     testTextInputType(WebTextInputTypePassword, "input_field_password.html");
548     testTextInputType(WebTextInputTypeEmail, "input_field_email.html");
549     testTextInputType(WebTextInputTypeSearch, "input_field_search.html");
550     testTextInputType(WebTextInputTypeNumber, "input_field_number.html");
551     testTextInputType(WebTextInputTypeTelephone, "input_field_tel.html");
552     testTextInputType(WebTextInputTypeURL, "input_field_url.html");
553 }
554
555 void WebViewTest::testInputMode(const WebString& expectedInputMode, const std::string& htmlFile)
556 {
557     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
558     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
559     webView->setInitialFocus(false);
560     EXPECT_EQ(expectedInputMode, webView->textInputInfo().inputMode);
561 }
562
563 TEST_F(WebViewTest, InputMode)
564 {
565     testInputMode(WebString(), "input_mode_default.html");
566     testInputMode(WebString("unknown"), "input_mode_default_unknown.html");
567     testInputMode(WebString("verbatim"), "input_mode_default_verbatim.html");
568     testInputMode(WebString("verbatim"), "input_mode_type_text_verbatim.html");
569     testInputMode(WebString("verbatim"), "input_mode_type_search_verbatim.html");
570     testInputMode(WebString(), "input_mode_type_url_verbatim.html");
571     testInputMode(WebString("verbatim"), "input_mode_textarea_verbatim.html");
572 }
573
574 TEST_F(WebViewTest, TextInputInfoWithReplacedElements)
575 {
576     std::string url = m_baseURL + "div_with_image.html";
577     URLTestHelpers::registerMockedURLLoad(toKURL(url), "div_with_image.html");
578     WebView* webView = m_webViewHelper.initializeAndLoad(url);
579     webView->setInitialFocus(false);
580     WebTextInputInfo info = webView->textInputInfo();
581
582     EXPECT_EQ("foo\xef\xbf\xbc", info.value.utf8());
583 }
584
585 TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
586 {
587     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
588     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
589     webView->setInitialFocus(false);
590     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
591     frame->setEditableSelectionOffsets(5, 13);
592     EXPECT_EQ("56789abc", frame->selectionAsText());
593     WebTextInputInfo info = webView->textInputInfo();
594     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
595     EXPECT_EQ(5, info.selectionStart);
596     EXPECT_EQ(13, info.selectionEnd);
597     EXPECT_EQ(-1, info.compositionStart);
598     EXPECT_EQ(-1, info.compositionEnd);
599
600     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_populated.html"));
601     webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_editable_populated.html");
602     webView->setInitialFocus(false);
603     frame = toWebLocalFrameImpl(webView->mainFrame());
604     frame->setEditableSelectionOffsets(8, 19);
605     EXPECT_EQ("89abcdefghi", frame->selectionAsText());
606     info = webView->textInputInfo();
607     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
608     EXPECT_EQ(8, info.selectionStart);
609     EXPECT_EQ(19, info.selectionEnd);
610     EXPECT_EQ(-1, info.compositionStart);
611     EXPECT_EQ(-1, info.compositionEnd);
612 }
613
614 TEST_F(WebViewTest, ConfirmCompositionCursorPositionChange)
615 {
616     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
617     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
618     webView->setInitialFocus(false);
619
620     // Set up a composition that needs to be committed.
621     std::string compositionText("hello");
622
623     WebVector<WebCompositionUnderline> emptyUnderlines;
624     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
625
626     WebTextInputInfo info = webView->textInputInfo();
627     EXPECT_EQ("hello", std::string(info.value.utf8().data()));
628     EXPECT_EQ(3, info.selectionStart);
629     EXPECT_EQ(3, info.selectionEnd);
630     EXPECT_EQ(0, info.compositionStart);
631     EXPECT_EQ(5, info.compositionEnd);
632
633     webView->confirmComposition(WebWidget::KeepSelection);
634     info = webView->textInputInfo();
635     EXPECT_EQ(3, info.selectionStart);
636     EXPECT_EQ(3, info.selectionEnd);
637     EXPECT_EQ(-1, info.compositionStart);
638     EXPECT_EQ(-1, info.compositionEnd);
639
640     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
641     info = webView->textInputInfo();
642     EXPECT_EQ("helhellolo", std::string(info.value.utf8().data()));
643     EXPECT_EQ(6, info.selectionStart);
644     EXPECT_EQ(6, info.selectionEnd);
645     EXPECT_EQ(3, info.compositionStart);
646     EXPECT_EQ(8, info.compositionEnd);
647
648     webView->confirmComposition(WebWidget::DoNotKeepSelection);
649     info = webView->textInputInfo();
650     EXPECT_EQ(8, info.selectionStart);
651     EXPECT_EQ(8, info.selectionEnd);
652     EXPECT_EQ(-1, info.compositionStart);
653     EXPECT_EQ(-1, info.compositionEnd);
654 }
655
656 TEST_F(WebViewTest, InsertNewLinePlacementAfterConfirmComposition)
657 {
658     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
659     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
660     webView->setInitialFocus(false);
661
662     WebVector<WebCompositionUnderline> emptyUnderlines;
663
664     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
665     frame->setEditableSelectionOffsets(4, 4);
666     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
667
668     WebTextInputInfo info = webView->textInputInfo();
669     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
670     EXPECT_EQ(4, info.selectionStart);
671     EXPECT_EQ(4, info.selectionEnd);
672     EXPECT_EQ(8, info.compositionStart);
673     EXPECT_EQ(12, info.compositionEnd);
674
675     webView->confirmComposition(WebWidget::KeepSelection);
676     info = webView->textInputInfo();
677     EXPECT_EQ(4, info.selectionStart);
678     EXPECT_EQ(4, info.selectionEnd);
679     EXPECT_EQ(-1, info.compositionStart);
680     EXPECT_EQ(-1, info.compositionEnd);
681
682     std::string compositionText("\n");
683     webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
684     info = webView->textInputInfo();
685     EXPECT_EQ(5, info.selectionStart);
686     EXPECT_EQ(5, info.selectionEnd);
687     EXPECT_EQ(-1, info.compositionStart);
688     EXPECT_EQ(-1, info.compositionEnd);
689     EXPECT_EQ("0123\n456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
690 }
691
692 TEST_F(WebViewTest, ExtendSelectionAndDelete)
693 {
694     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
695     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
696     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
697     webView->setInitialFocus(false);
698     frame->setEditableSelectionOffsets(10, 10);
699     frame->extendSelectionAndDelete(5, 8);
700     WebTextInputInfo info = webView->textInputInfo();
701     EXPECT_EQ("01234ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
702     EXPECT_EQ(5, info.selectionStart);
703     EXPECT_EQ(5, info.selectionEnd);
704     frame->extendSelectionAndDelete(10, 0);
705     info = webView->textInputInfo();
706     EXPECT_EQ("ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
707 }
708
709 TEST_F(WebViewTest, SetCompositionFromExistingText)
710 {
711     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
712     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
713     webView->setInitialFocus(false);
714     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
715     underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
716     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
717     frame->setEditableSelectionOffsets(4, 10);
718     frame->setCompositionFromExistingText(8, 12, underlines);
719     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
720     EXPECT_EQ(8u, underlineResults[0].startOffset);
721     EXPECT_EQ(12u, underlineResults[0].endOffset);
722     WebTextInputInfo info = webView->textInputInfo();
723     EXPECT_EQ(4, info.selectionStart);
724     EXPECT_EQ(10, info.selectionEnd);
725     EXPECT_EQ(8, info.compositionStart);
726     EXPECT_EQ(12, info.compositionEnd);
727     WebVector<WebCompositionUnderline> emptyUnderlines;
728     frame->setCompositionFromExistingText(0, 0, emptyUnderlines);
729     info = webView->textInputInfo();
730     EXPECT_EQ(4, info.selectionStart);
731     EXPECT_EQ(10, info.selectionEnd);
732     EXPECT_EQ(-1, info.compositionStart);
733     EXPECT_EQ(-1, info.compositionEnd);
734 }
735
736 TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea)
737 {
738     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
739     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
740     webView->setInitialFocus(false);
741     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
742     underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0);
743     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
744     frame->setEditableSelectionOffsets(27, 27);
745     std::string newLineText("\n");
746     webView->confirmComposition(WebString::fromUTF8(newLineText.c_str()));
747     WebTextInputInfo info = webView->textInputInfo();
748     EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
749
750     frame->setEditableSelectionOffsets(31, 31);
751     frame->setCompositionFromExistingText(30, 34, underlines);
752     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
753     EXPECT_EQ(2u, underlineResults[0].startOffset);
754     EXPECT_EQ(6u, underlineResults[0].endOffset);
755     info = webView->textInputInfo();
756     EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
757     EXPECT_EQ(31, info.selectionStart);
758     EXPECT_EQ(31, info.selectionEnd);
759     EXPECT_EQ(30, info.compositionStart);
760     EXPECT_EQ(34, info.compositionEnd);
761
762     std::string compositionText("yolo");
763     webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
764     info = webView->textInputInfo();
765     EXPECT_EQ("0123456789abcdefghijklmnopq\nrsyoloxyz", std::string(info.value.utf8().data()));
766     EXPECT_EQ(34, info.selectionStart);
767     EXPECT_EQ(34, info.selectionEnd);
768     EXPECT_EQ(-1, info.compositionStart);
769     EXPECT_EQ(-1, info.compositionEnd);
770 }
771
772 TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
773 {
774     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
775     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
776     webView->setInitialFocus(false);
777
778     std::string compositionTextFirst("hello ");
779     std::string compositionTextSecond("world");
780     WebVector<WebCompositionUnderline> emptyUnderlines;
781
782     webView->confirmComposition(WebString::fromUTF8(compositionTextFirst.c_str()));
783     webView->setComposition(WebString::fromUTF8(compositionTextSecond.c_str()), emptyUnderlines, 5, 5);
784
785     WebTextInputInfo info = webView->textInputInfo();
786     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
787     EXPECT_EQ(11, info.selectionStart);
788     EXPECT_EQ(11, info.selectionEnd);
789     EXPECT_EQ(6, info.compositionStart);
790     EXPECT_EQ(11, info.compositionEnd);
791
792     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
793     frame->setEditableSelectionOffsets(6, 6);
794     info = webView->textInputInfo();
795     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
796     EXPECT_EQ(6, info.selectionStart);
797     EXPECT_EQ(6, info.selectionEnd);
798     EXPECT_EQ(6, info.compositionStart);
799     EXPECT_EQ(11, info.compositionEnd);
800
801     frame->setEditableSelectionOffsets(8, 8);
802     info = webView->textInputInfo();
803     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
804     EXPECT_EQ(8, info.selectionStart);
805     EXPECT_EQ(8, info.selectionEnd);
806     EXPECT_EQ(6, info.compositionStart);
807     EXPECT_EQ(11, info.compositionEnd);
808
809     frame->setEditableSelectionOffsets(11, 11);
810     info = webView->textInputInfo();
811     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
812     EXPECT_EQ(11, info.selectionStart);
813     EXPECT_EQ(11, info.selectionEnd);
814     EXPECT_EQ(6, info.compositionStart);
815     EXPECT_EQ(11, info.compositionEnd);
816
817     frame->setEditableSelectionOffsets(6, 11);
818     info = webView->textInputInfo();
819     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
820     EXPECT_EQ(6, info.selectionStart);
821     EXPECT_EQ(11, info.selectionEnd);
822     EXPECT_EQ(6, info.compositionStart);
823     EXPECT_EQ(11, info.compositionEnd);
824
825     frame->setEditableSelectionOffsets(2, 2);
826     info = webView->textInputInfo();
827     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
828     EXPECT_EQ(2, info.selectionStart);
829     EXPECT_EQ(2, info.selectionEnd);
830     EXPECT_EQ(-1, info.compositionStart);
831     EXPECT_EQ(-1, info.compositionEnd);
832 }
833
834 TEST_F(WebViewTest, IsSelectionAnchorFirst)
835 {
836     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
837     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
838     WebFrame* frame = webView->mainFrame();
839
840     webView->setPageScaleFactorLimits(1, 1);
841     webView->setInitialFocus(false);
842     frame->setEditableSelectionOffsets(4, 10);
843     EXPECT_TRUE(webView->isSelectionAnchorFirst());
844     WebRect anchor;
845     WebRect focus;
846     webView->selectionBounds(anchor, focus);
847     frame->selectRange(WebPoint(focus.x, focus.y), WebPoint(anchor.x, anchor.y));
848     EXPECT_FALSE(webView->isSelectionAnchorFirst());
849 }
850
851 TEST_F(WebViewTest, HistoryResetScrollAndScaleState)
852 {
853     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
854     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html");
855     webViewImpl->resize(WebSize(640, 480));
856     webViewImpl->layout();
857     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
858     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
859
860     // Make the page scale and scroll with the given paremeters.
861     webViewImpl->setPageScaleFactor(2.0f);
862     webViewImpl->setMainFrameScrollOffset(WebPoint(116, 84));
863     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
864     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
865     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
866     LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
867     mainFrameLocal->loader().saveScrollState();
868     EXPECT_EQ(2.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
869     EXPECT_EQ(116, mainFrameLocal->loader().currentItem()->scrollPoint().x());
870     EXPECT_EQ(84, mainFrameLocal->loader().currentItem()->scrollPoint().y());
871
872     // Confirm that resetting the page state resets the saved scroll position.
873     // The HistoryController treats a page scale factor of 0.0f as special and avoids
874     // restoring it to the WebView.
875     webViewImpl->resetScrollAndScaleState();
876     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
877     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
878     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
879     EXPECT_EQ(0.0f, mainFrameLocal->loader().currentItem()->pageScaleFactor());
880     EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().x());
881     EXPECT_EQ(0, mainFrameLocal->loader().currentItem()->scrollPoint().y());
882 }
883
884 TEST_F(WebViewTest, BackForwardRestoreScroll)
885 {
886     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("back_forward_restore_scroll.html"));
887     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "back_forward_restore_scroll.html");
888     webViewImpl->resize(WebSize(640, 480));
889     webViewImpl->layout();
890
891     // Emulate a user scroll
892     webViewImpl->setMainFrameScrollOffset(WebPoint(0, 900));
893     LocalFrame* mainFrameLocal = toLocalFrame(webViewImpl->page()->mainFrame());
894     RefPtrWillBePersistent<HistoryItem> item1 = mainFrameLocal->loader().currentItem();
895
896     // Click an anchor
897     mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#a"))));
898     RefPtrWillBePersistent<HistoryItem> item2 = mainFrameLocal->loader().currentItem();
899
900     // Go back, then forward, then back again.
901     mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
902     mainFrameLocal->loader().loadHistoryItem(item2.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
903     mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
904
905     // Click a different anchor
906     mainFrameLocal->loader().load(FrameLoadRequest(mainFrameLocal->document(), ResourceRequest(mainFrameLocal->document()->completeURL("#b"))));
907     RefPtrWillBePersistent<HistoryItem> item3 = mainFrameLocal->loader().currentItem();
908
909     // Go back, then forward. The scroll position should be properly set on the forward navigation.
910     mainFrameLocal->loader().loadHistoryItem(item1.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
911     mainFrameLocal->loader().loadHistoryItem(item3.get(), FrameLoadTypeBackForward, HistorySameDocumentLoad);
912     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
913     EXPECT_GT(webViewImpl->mainFrame()->scrollOffset().height, 2000);
914 }
915
916 class EnterFullscreenWebViewClient : public FrameTestHelpers::TestWebViewClient {
917 public:
918     // WebViewClient methods
919     virtual bool enterFullScreen() { return true; }
920     virtual void exitFullScreen() { }
921 };
922
923
924 TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
925 {
926     EnterFullscreenWebViewClient client;
927     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
928     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, 0, &client);
929     webViewImpl->resize(WebSize(640, 480));
930     webViewImpl->layout();
931     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
932     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
933
934     // Make the page scale and scroll with the given paremeters.
935     webViewImpl->setPageScaleFactor(2.0f);
936     webViewImpl->setMainFrameScrollOffset(WebPoint(116, 84));
937     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
938     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
939     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
940
941     RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element> >(webViewImpl->mainFrame()->document().body());
942     webViewImpl->enterFullScreenForElement(element.get());
943     webViewImpl->didEnterFullScreen();
944
945     // Page scale factor must be 1.0 during fullscreen for elements to be sized
946     // properly.
947     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
948
949     // Make sure fullscreen nesting doesn't disrupt scroll/scale saving.
950     RefPtrWillBeRawPtr<Element> otherElement = static_cast<PassRefPtrWillBeRawPtr<Element> >(webViewImpl->mainFrame()->document().head());
951     webViewImpl->enterFullScreenForElement(otherElement.get());
952
953     // Confirm that exiting fullscreen restores the parameters.
954     webViewImpl->didExitFullScreen();
955     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
956     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
957     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
958
959     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
960 }
961
962 class PrintWebViewClient : public FrameTestHelpers::TestWebViewClient {
963 public:
964     PrintWebViewClient()
965         : m_printCalled(false)
966     {
967     }
968
969     // WebViewClient methods
970     virtual void printPage(WebLocalFrame*) override
971     {
972         m_printCalled = true;
973     }
974
975     bool printCalled() const { return m_printCalled; }
976
977 private:
978     bool m_printCalled;
979 };
980
981
982 TEST_F(WebViewTest, PrintWithXHRInFlight)
983 {
984     PrintWebViewClient client;
985     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("print_with_xhr_inflight.html"));
986     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "print_with_xhr_inflight.html", true, 0, &client);
987
988     ASSERT_EQ(FrameStateComplete, toLocalFrame(webViewImpl->page()->mainFrame())->loader().state());
989     EXPECT_TRUE(client.printCalled());
990     m_webViewHelper.reset();
991 }
992
993 class DropTask : public WebThread::Task {
994 public:
995     explicit DropTask(WebView* webView) : m_webView(webView)
996     {
997     }
998
999     virtual void run() override
1000     {
1001         const WebPoint clientPoint(0, 0);
1002         const WebPoint screenPoint(0, 0);
1003         m_webView->dragTargetDrop(clientPoint, screenPoint, 0);
1004     }
1005
1006 private:
1007     WebView* const m_webView;
1008 };
1009 static void DragAndDropURL(WebViewImpl* webView, const std::string& url)
1010 {
1011     WebDragData dragData;
1012     dragData.initialize();
1013
1014     WebDragData::Item item;
1015     item.storageType = WebDragData::Item::StorageTypeString;
1016     item.stringType = "text/uri-list";
1017     item.stringData = WebString::fromUTF8(url);
1018     dragData.addItem(item);
1019
1020     const WebPoint clientPoint(0, 0);
1021     const WebPoint screenPoint(0, 0);
1022     webView->dragTargetDragEnter(dragData, clientPoint, screenPoint, WebDragOperationCopy, 0);
1023     Platform::current()->currentThread()->postTask(new DropTask(webView));
1024     FrameTestHelpers::pumpPendingRequestsDoNotUse(webView->mainFrame());
1025 }
1026
1027 TEST_F(WebViewTest, DragDropURL)
1028 {
1029     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "foo.html");
1030     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "bar.html");
1031
1032     const std::string fooUrl = m_baseURL + "foo.html";
1033     const std::string barUrl = m_baseURL + "bar.html";
1034
1035     WebViewImpl* webView = m_webViewHelper.initializeAndLoad(fooUrl);
1036
1037     ASSERT_TRUE(webView);
1038
1039     // Drag and drop barUrl and verify that we've navigated to it.
1040     DragAndDropURL(webView, barUrl);
1041     EXPECT_EQ(barUrl, webView->mainFrame()->document().url().string().utf8());
1042
1043     // Drag and drop fooUrl and verify that we've navigated back to it.
1044     DragAndDropURL(webView, fooUrl);
1045     EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
1046
1047     // Disable navigation on drag-and-drop.
1048     webView->settingsImpl()->setNavigateOnDragDrop(false);
1049
1050     // Attempt to drag and drop to barUrl and verify that no navigation has occurred.
1051     DragAndDropURL(webView, barUrl);
1052     EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
1053 }
1054
1055 class ContentDetectorClient : public FrameTestHelpers::TestWebViewClient {
1056 public:
1057     ContentDetectorClient() { reset(); }
1058
1059     virtual WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) override
1060     {
1061         m_contentDetectionRequested = true;
1062         return m_contentDetectionResult;
1063     }
1064
1065     virtual void scheduleContentIntent(const WebURL& url) override
1066     {
1067         m_scheduledIntentURL = url;
1068     }
1069
1070     virtual void cancelScheduledContentIntents() override
1071     {
1072         m_pendingIntentsCancelled = true;
1073     }
1074
1075     void reset()
1076     {
1077         m_contentDetectionRequested = false;
1078         m_pendingIntentsCancelled = false;
1079         m_scheduledIntentURL = WebURL();
1080         m_contentDetectionResult = WebContentDetectionResult();
1081     }
1082
1083     bool contentDetectionRequested() const { return m_contentDetectionRequested; }
1084     bool pendingIntentsCancelled() const { return m_pendingIntentsCancelled; }
1085     const WebURL& scheduledIntentURL() const { return m_scheduledIntentURL; }
1086     void setContentDetectionResult(const WebContentDetectionResult& result) { m_contentDetectionResult = result; }
1087
1088 private:
1089     bool m_contentDetectionRequested;
1090     bool m_pendingIntentsCancelled;
1091     WebURL m_scheduledIntentURL;
1092     WebContentDetectionResult m_contentDetectionResult;
1093 };
1094
1095 static bool tapElementById(WebView* webView, WebInputEvent::Type type, const WebString& id)
1096 {
1097     ASSERT(webView);
1098     RefPtrWillBeRawPtr<Element> element = static_cast<PassRefPtrWillBeRawPtr<Element> >(webView->mainFrame()->document().getElementById(id));
1099     if (!element)
1100         return false;
1101
1102     element->scrollIntoViewIfNeeded();
1103     IntPoint center = element->screenRect().center();
1104
1105     WebGestureEvent event;
1106     event.type = type;
1107     event.x = center.x();
1108     event.y = center.y();
1109
1110     webView->handleInputEvent(event);
1111     runPendingTasks();
1112     return true;
1113 }
1114
1115 TEST_F(WebViewTest, DetectContentAroundPosition)
1116 {
1117     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_listeners.html"));
1118
1119     ContentDetectorClient client;
1120     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_listeners.html", true, 0, &client);
1121     webView->resize(WebSize(500, 300));
1122     webView->layout();
1123     runPendingTasks();
1124
1125     WebString clickListener = WebString::fromUTF8("clickListener");
1126     WebString touchstartListener = WebString::fromUTF8("touchstartListener");
1127     WebString mousedownListener = WebString::fromUTF8("mousedownListener");
1128     WebString noListener = WebString::fromUTF8("noListener");
1129     WebString link = WebString::fromUTF8("link");
1130
1131     // Ensure content detection is not requested for nodes listening to click,
1132     // mouse or touch events when we do simple taps.
1133     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, clickListener));
1134     EXPECT_FALSE(client.contentDetectionRequested());
1135     client.reset();
1136
1137     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, touchstartListener));
1138     EXPECT_FALSE(client.contentDetectionRequested());
1139     client.reset();
1140
1141     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, mousedownListener));
1142     EXPECT_FALSE(client.contentDetectionRequested());
1143     client.reset();
1144
1145     // Content detection should work normally without these event listeners.
1146     // The click listener in the body should be ignored as a special case.
1147     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
1148     EXPECT_TRUE(client.contentDetectionRequested());
1149     EXPECT_FALSE(client.scheduledIntentURL().isValid());
1150
1151     WebURL intentURL = toKURL(m_baseURL);
1152     client.setContentDetectionResult(WebContentDetectionResult(WebRange(), WebString(), intentURL));
1153     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
1154     EXPECT_TRUE(client.scheduledIntentURL() == intentURL);
1155
1156     // Tapping elsewhere should cancel the scheduled intent.
1157     WebGestureEvent event;
1158     event.type = WebInputEvent::GestureTap;
1159     webView->handleInputEvent(event);
1160     runPendingTasks();
1161     EXPECT_TRUE(client.pendingIntentsCancelled());
1162
1163     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1164 }
1165
1166 TEST_F(WebViewTest, ClientTapHandling)
1167 {
1168     TapHandlingWebViewClient client;
1169     client.reset();
1170     WebView* webView = m_webViewHelper.initializeAndLoad("about:blank", true, 0, &client);
1171     WebGestureEvent event;
1172     event.type = WebInputEvent::GestureTap;
1173     event.x = 3;
1174     event.y = 8;
1175     webView->handleInputEvent(event);
1176     runPendingTasks();
1177     EXPECT_EQ(3, client.tapX());
1178     EXPECT_EQ(8, client.tapY());
1179     client.reset();
1180     event.type = WebInputEvent::GestureLongPress;
1181     event.x = 25;
1182     event.y = 7;
1183     webView->handleInputEvent(event);
1184     runPendingTasks();
1185     EXPECT_EQ(25, client.longpressX());
1186     EXPECT_EQ(7, client.longpressY());
1187
1188     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1189 }
1190
1191 #if OS(ANDROID)
1192 TEST_F(WebViewTest, LongPressSelection)
1193 {
1194     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
1195
1196     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
1197     webView->resize(WebSize(500, 300));
1198     webView->layout();
1199     runPendingTasks();
1200
1201     WebString target = WebString::fromUTF8("target");
1202     WebString onselectstartfalse = WebString::fromUTF8("onselectstartfalse");
1203     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1204
1205     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, onselectstartfalse));
1206     EXPECT_EQ("", std::string(frame->selectionAsText().utf8().data()));
1207     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
1208     EXPECT_EQ("testword", std::string(frame->selectionAsText().utf8().data()));
1209 }
1210
1211 TEST_F(WebViewTest, BlinkCaretOnTypingAfterLongPress)
1212 {
1213     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("blink_caret_on_typing_after_long_press.html"));
1214
1215     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "blink_caret_on_typing_after_long_press.html", true);
1216     webView->resize(WebSize(640, 480));
1217     webView->layout();
1218     runPendingTasks();
1219
1220     WebString target = WebString::fromUTF8("target");
1221     WebLocalFrameImpl* mainFrame = toWebLocalFrameImpl(webView->mainFrame());
1222
1223     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
1224     EXPECT_TRUE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
1225
1226     WebKeyboardEvent keyEvent;
1227     keyEvent.type = WebInputEvent::RawKeyDown;
1228     webView->handleInputEvent(keyEvent);
1229     keyEvent.type = WebInputEvent::KeyUp;
1230     webView->handleInputEvent(keyEvent);
1231     EXPECT_FALSE(mainFrame->frame()->selection().isCaretBlinkingSuspended());
1232 }
1233 #endif
1234
1235 TEST_F(WebViewTest, SelectionOnReadOnlyInput)
1236 {
1237     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_readonly.html"));
1238     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "selection_readonly.html", true);
1239     webView->resize(WebSize(640, 480));
1240     webView->layout();
1241     runPendingTasks();
1242
1243     std::string testWord = "This text should be selected.";
1244
1245     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1246     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
1247
1248     size_t location;
1249     size_t length;
1250     EXPECT_TRUE(toWebViewImpl(webView)->caretOrSelectionRange(&location, &length));
1251     EXPECT_EQ(location, 0UL);
1252     EXPECT_EQ(length, testWord.length());
1253 }
1254
1255 static void configueCompositingWebView(WebSettings* settings)
1256 {
1257     settings->setAcceleratedCompositingEnabled(true);
1258     settings->setPreferCompositingToLCDTextEnabled(true);
1259 }
1260
1261 TEST_F(WebViewTest, ShowPressOnTransformedLink)
1262 {
1263     OwnPtr<FrameTestHelpers::TestWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FrameTestHelpers::TestWebViewClient());
1264     FrameTestHelpers::WebViewHelper webViewHelper;
1265     WebViewImpl* webViewImpl = webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
1266
1267     int pageWidth = 640;
1268     int pageHeight = 480;
1269     webViewImpl->resize(WebSize(pageWidth, pageHeight));
1270
1271     WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
1272     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);
1273
1274     WebGestureEvent event;
1275     event.type = WebInputEvent::GestureShowPress;
1276     event.x = 20;
1277     event.y = 20;
1278
1279     // Just make sure we don't hit any asserts.
1280     webViewImpl->handleInputEvent(event);
1281 }
1282
1283 class MockAutofillClient : public WebAutofillClient {
1284 public:
1285     MockAutofillClient()
1286         : m_ignoreTextChanges(false)
1287         , m_textChangesWhileIgnored(0)
1288         , m_textChangesWhileNotIgnored(0)
1289         , m_userGestureNotificationsCount(0) { }
1290
1291     virtual ~MockAutofillClient() { }
1292
1293     virtual void setIgnoreTextChanges(bool ignore) override { m_ignoreTextChanges = ignore; }
1294     virtual void textFieldDidChange(const WebFormControlElement&) override
1295     {
1296         if (m_ignoreTextChanges)
1297             ++m_textChangesWhileIgnored;
1298         else
1299             ++m_textChangesWhileNotIgnored;
1300     }
1301     virtual void firstUserGestureObserved() override { ++m_userGestureNotificationsCount; }
1302
1303     void clearChangeCounts()
1304     {
1305         m_textChangesWhileIgnored = 0;
1306         m_textChangesWhileNotIgnored = 0;
1307     }
1308
1309     int textChangesWhileIgnored() { return m_textChangesWhileIgnored; }
1310     int textChangesWhileNotIgnored() { return m_textChangesWhileNotIgnored; }
1311     int getUserGestureNotificationsCount() { return m_userGestureNotificationsCount; }
1312
1313 private:
1314     bool m_ignoreTextChanges;
1315     int m_textChangesWhileIgnored;
1316     int m_textChangesWhileNotIgnored;
1317     int m_userGestureNotificationsCount;
1318 };
1319
1320
1321 TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange)
1322 {
1323     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1324     MockAutofillClient client;
1325     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1326     webView->setAutofillClient(&client);
1327     webView->setInitialFocus(false);
1328
1329     // Set up a composition that needs to be committed.
1330     WebVector<WebCompositionUnderline> emptyUnderlines;
1331     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1332     frame->setEditableSelectionOffsets(4, 10);
1333     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1334     WebTextInputInfo info = webView->textInputInfo();
1335     EXPECT_EQ(4, info.selectionStart);
1336     EXPECT_EQ(10, info.selectionEnd);
1337     EXPECT_EQ(8, info.compositionStart);
1338     EXPECT_EQ(12, info.compositionEnd);
1339
1340     // Clear the focus and track that the subsequent composition commit does not trigger a
1341     // text changed notification for autofill.
1342     client.clearChangeCounts();
1343     webView->setFocus(false);
1344     EXPECT_EQ(1, client.textChangesWhileIgnored());
1345     EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1346
1347     webView->setAutofillClient(0);
1348 }
1349
1350 TEST_F(WebViewTest, ConfirmCompositionTriggersAutofillTextChange)
1351 {
1352     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1353     MockAutofillClient client;
1354     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1355     webView->setAutofillClient(&client);
1356     webView->setInitialFocus(false);
1357
1358     // Set up a composition that needs to be committed.
1359     std::string compositionText("testingtext");
1360
1361     WebVector<WebCompositionUnderline> emptyUnderlines;
1362     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 0, compositionText.length());
1363
1364     WebTextInputInfo info = webView->textInputInfo();
1365     EXPECT_EQ(0, info.selectionStart);
1366     EXPECT_EQ((int) compositionText.length(), info.selectionEnd);
1367     EXPECT_EQ(0, info.compositionStart);
1368     EXPECT_EQ((int) compositionText.length(), info.compositionEnd);
1369
1370     client.clearChangeCounts();
1371     webView->confirmComposition();
1372     EXPECT_EQ(0, client.textChangesWhileIgnored());
1373     EXPECT_EQ(1, client.textChangesWhileNotIgnored());
1374
1375     webView->setAutofillClient(0);
1376 }
1377
1378 TEST_F(WebViewTest, SetCompositionFromExistingTextTriggersAutofillTextChange)
1379 {
1380     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1381     MockAutofillClient client;
1382     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html", true);
1383     webView->setAutofillClient(&client);
1384     webView->setInitialFocus(false);
1385
1386     WebVector<WebCompositionUnderline> emptyUnderlines;
1387
1388     client.clearChangeCounts();
1389     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1390     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1391
1392     WebTextInputInfo info = webView->textInputInfo();
1393     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
1394     EXPECT_EQ(8, info.compositionStart);
1395     EXPECT_EQ(12, info.compositionEnd);
1396
1397     EXPECT_EQ(0, client.textChangesWhileIgnored());
1398     EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1399
1400     WebDocument document = webView->mainFrame()->document();
1401     EXPECT_EQ(WebString::fromUTF8("none"),  document.getElementById("inputEvent").firstChild().nodeValue());
1402
1403     webView->setAutofillClient(0);
1404 }
1405
1406 TEST_F(WebViewTest, ShadowRoot)
1407 {
1408     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("shadow_dom_test.html"));
1409     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "shadow_dom_test.html", true);
1410
1411     WebDocument document = webViewImpl->mainFrame()->document();
1412     {
1413         WebElement elementWithShadowRoot = document.getElementById("shadowroot");
1414         EXPECT_FALSE(elementWithShadowRoot.isNull());
1415         WebNode shadowRoot = elementWithShadowRoot.shadowRoot();
1416         EXPECT_FALSE(shadowRoot.isNull());
1417     }
1418     {
1419         WebElement elementWithoutShadowRoot = document.getElementById("noshadowroot");
1420         EXPECT_FALSE(elementWithoutShadowRoot.isNull());
1421         WebNode shadowRoot = elementWithoutShadowRoot.shadowRoot();
1422         EXPECT_TRUE(shadowRoot.isNull());
1423     }
1424 }
1425
1426 class ViewCreatingWebViewClient : public FrameTestHelpers::TestWebViewClient {
1427 public:
1428     ViewCreatingWebViewClient()
1429         : m_didFocusCalled(false)
1430     {
1431     }
1432
1433     // WebViewClient methods
1434     virtual WebView* createView(WebLocalFrame*, const WebURLRequest&, const WebWindowFeatures&, const WebString& name, WebNavigationPolicy, bool) override
1435     {
1436         return m_webViewHelper.initialize(true, 0, 0);
1437     }
1438
1439     // WebWidgetClient methods
1440     virtual void didFocus() override
1441     {
1442         m_didFocusCalled = true;
1443     }
1444
1445     bool didFocusCalled() const { return m_didFocusCalled; }
1446     WebView* createdWebView() const { return m_webViewHelper.webView(); }
1447
1448 private:
1449     FrameTestHelpers::WebViewHelper m_webViewHelper;
1450     bool m_didFocusCalled;
1451 };
1452
1453 TEST_F(WebViewTest, FocusExistingFrameOnNavigate)
1454 {
1455     ViewCreatingWebViewClient client;
1456     FrameTestHelpers::WebViewHelper m_webViewHelper;
1457     WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
1458     webViewImpl->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
1459     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
1460     frame->setName("_start");
1461
1462     // Make a request that will open a new window
1463     WebURLRequest webURLRequest;
1464     webURLRequest.initialize();
1465     FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
1466     toLocalFrame(webViewImpl->page()->mainFrame())->loader().load(request);
1467     ASSERT_TRUE(client.createdWebView());
1468     EXPECT_FALSE(client.didFocusCalled());
1469
1470     // Make a request from the new window that will navigate the original window. The original window should be focused.
1471     WebURLRequest webURLRequestWithTargetStart;
1472     webURLRequestWithTargetStart.initialize();
1473     FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
1474     toLocalFrame(toWebViewImpl(client.createdWebView())->page()->mainFrame())->loader().load(requestWithTargetStart);
1475     EXPECT_TRUE(client.didFocusCalled());
1476
1477     m_webViewHelper.reset(); // Remove dependency on locally scoped client.
1478 }
1479
1480 TEST_F(WebViewTest, DispatchesFocusOutFocusInOnViewToggleFocus)
1481 {
1482     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focusout_focusin_events.html");
1483     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focusout_focusin_events.html", true, 0);
1484
1485     webView->setFocus(true);
1486     webView->setFocus(false);
1487     webView->setFocus(true);
1488
1489     WebElement element = webView->mainFrame()->document().getElementById("message");
1490     EXPECT_STREQ("focusoutfocusin", element.innerText().utf8().data());
1491 }
1492
1493 TEST_F(WebViewTest, DispatchesDomFocusOutDomFocusInOnViewToggleFocus)
1494 {
1495     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "domfocusout_domfocusin_events.html");
1496     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "domfocusout_domfocusin_events.html", true, 0);
1497
1498     webView->setFocus(true);
1499     webView->setFocus(false);
1500     webView->setFocus(true);
1501
1502     WebElement element = webView->mainFrame()->document().getElementById("message");
1503     EXPECT_STREQ("DOMFocusOutDOMFocusIn", element.innerText().utf8().data());
1504 }
1505
1506 #if !ENABLE(INPUT_MULTIPLE_FIELDS_UI)
1507 static void openDateTimeChooser(WebView* webView, HTMLInputElement* inputElement)
1508 {
1509     inputElement->focus();
1510
1511     WebKeyboardEvent keyEvent;
1512     keyEvent.windowsKeyCode = VKEY_SPACE;
1513     keyEvent.type = WebInputEvent::RawKeyDown;
1514     keyEvent.setKeyIdentifierFromWindowsKeyCode();
1515     webView->handleInputEvent(keyEvent);
1516
1517     keyEvent.type = WebInputEvent::KeyUp;
1518     webView->handleInputEvent(keyEvent);
1519 }
1520
1521 TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
1522 {
1523     DateTimeChooserWebViewClient client;
1524     std::string url = m_baseURL + "date_time_chooser.html";
1525     URLTestHelpers::registerMockedURLLoad(toKURL(url), "date_time_chooser.html");
1526     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
1527
1528     Document* document = webViewImpl->mainFrameImpl()->frame()->document();
1529
1530     HTMLInputElement* inputElement;
1531
1532     inputElement = toHTMLInputElement(document->getElementById("date"));
1533     openDateTimeChooser(webViewImpl, inputElement);
1534     client.chooserCompletion()->didChooseValue(0);
1535     client.clearChooserCompletion();
1536     EXPECT_STREQ("1970-01-01", inputElement->value().utf8().data());
1537
1538     openDateTimeChooser(webViewImpl, inputElement);
1539     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1540     client.clearChooserCompletion();
1541     EXPECT_STREQ("", inputElement->value().utf8().data());
1542
1543     inputElement = toHTMLInputElement(document->getElementById("datetimelocal"));
1544     openDateTimeChooser(webViewImpl, inputElement);
1545     client.chooserCompletion()->didChooseValue(0);
1546     client.clearChooserCompletion();
1547     EXPECT_STREQ("1970-01-01T00:00", inputElement->value().utf8().data());
1548
1549     openDateTimeChooser(webViewImpl, inputElement);
1550     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1551     client.clearChooserCompletion();
1552     EXPECT_STREQ("", inputElement->value().utf8().data());
1553
1554     inputElement = toHTMLInputElement(document->getElementById("month"));
1555     openDateTimeChooser(webViewImpl, inputElement);
1556     client.chooserCompletion()->didChooseValue(0);
1557     client.clearChooserCompletion();
1558     EXPECT_STREQ("1970-01", inputElement->value().utf8().data());
1559
1560     openDateTimeChooser(webViewImpl, inputElement);
1561     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1562     client.clearChooserCompletion();
1563     EXPECT_STREQ("", inputElement->value().utf8().data());
1564
1565     inputElement = toHTMLInputElement(document->getElementById("time"));
1566     openDateTimeChooser(webViewImpl, inputElement);
1567     client.chooserCompletion()->didChooseValue(0);
1568     client.clearChooserCompletion();
1569     EXPECT_STREQ("00:00", inputElement->value().utf8().data());
1570
1571     openDateTimeChooser(webViewImpl, inputElement);
1572     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1573     client.clearChooserCompletion();
1574     EXPECT_STREQ("", inputElement->value().utf8().data());
1575
1576     inputElement = toHTMLInputElement(document->getElementById("week"));
1577     openDateTimeChooser(webViewImpl, inputElement);
1578     client.chooserCompletion()->didChooseValue(0);
1579     client.clearChooserCompletion();
1580     EXPECT_STREQ("1970-W01", inputElement->value().utf8().data());
1581
1582     openDateTimeChooser(webViewImpl, inputElement);
1583     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1584     client.clearChooserCompletion();
1585     EXPECT_STREQ("", inputElement->value().utf8().data());
1586
1587     // Clear the WebViewClient from the webViewHelper to avoid use-after-free in the
1588     // WebViewHelper destructor.
1589     m_webViewHelper.reset();
1590 }
1591 #endif
1592
1593 TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle)
1594 {
1595     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focus_blur_events.html");
1596     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focus_blur_events.html", true, 0);
1597
1598     webView->setFocus(true);
1599     webView->setFocus(false);
1600     webView->setFocus(true);
1601
1602     WebElement element = webView->mainFrame()->document().getElementById("message");
1603     // Expect not to see duplication of events.
1604     EXPECT_STREQ("blurfocus", element.innerText().utf8().data());
1605 }
1606
1607 TEST_F(WebViewTest, SmartClipData)
1608 {
1609     static const char* kExpectedClipText = "\nPrice 10,000,000won";
1610     static const char* kExpectedClipHtml =
1611         "<div id=\"div4\" style=\"padding: 10px; margin: 10px; border: 2px "
1612         "solid rgb(135, 206, 235); float: left; width: 190px; height: 30px; "
1613         "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
1614         "normal; font-variant: normal; font-weight: normal; letter-spacing: "
1615         "normal; line-height: normal; orphans: auto; text-align: start; "
1616         "text-indent: 0px; text-transform: none; white-space: normal; widows: "
1617         "auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">Air "
1618         "conditioner</div><div id=\"div5\" style=\"padding: 10px; margin: "
1619         "10px; border: 2px solid rgb(135, 206, 235); float: left; width: "
1620         "190px; height: 30px; color: rgb(0, 0, 0); font-family: myahem; "
1621         "font-size: 8px; font-style: normal; font-variant: normal; "
1622         "font-weight: normal; letter-spacing: normal; line-height: normal; "
1623         "orphans: auto; text-align: start; text-indent: 0px; text-transform: "
1624         "none; white-space: normal; widows: auto; word-spacing: 0px; "
1625         "-webkit-text-stroke-width: 0px;\">Price 10,000,000won</div>";
1626     WebString clipText;
1627     WebString clipHtml;
1628     WebRect clipRect;
1629     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
1630     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html"));
1631     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html");
1632     webView->setPageScaleFactorLimits(1, 1);
1633     webView->resize(WebSize(500, 500));
1634     webView->layout();
1635     WebRect cropRect(300, 125, 152, 50);
1636     webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
1637     EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str());
1638     EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str());
1639 }
1640
1641 TEST_F(WebViewTest, SmartClipReturnsEmptyStringsWhenUserSelectIsNone)
1642 {
1643     WebString clipText;
1644     WebString clipHtml;
1645     WebRect clipRect;
1646     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
1647     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip_user_select_none.html"));
1648     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip_user_select_none.html");
1649     webView->setPageScaleFactorLimits(1, 1);
1650     webView->resize(WebSize(500, 500));
1651     webView->layout();
1652     WebRect cropRect(0, 0, 100, 100);
1653     webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect);
1654     EXPECT_STREQ("", clipText.utf8().c_str());
1655     EXPECT_STREQ("", clipHtml.utf8().c_str());
1656 }
1657
1658 class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient {
1659 public:
1660     CreateChildCounterFrameClient() : m_count(0) { }
1661     virtual WebFrame* createChildFrame(WebLocalFrame* parent, const WebString& frameName) override;
1662
1663     int count() const { return m_count; }
1664
1665 private:
1666     int m_count;
1667 };
1668
1669 WebFrame* CreateChildCounterFrameClient::createChildFrame(WebLocalFrame* parent, const WebString& frameName)
1670 {
1671     ++m_count;
1672     return TestWebFrameClient::createChildFrame(parent, frameName);
1673 }
1674
1675 TEST_F(WebViewTest, AddFrameInCloseUnload)
1676 {
1677     CreateChildCounterFrameClient frameClient;
1678     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1679     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1680     m_webViewHelper.reset();
1681     EXPECT_EQ(0, frameClient.count());
1682 }
1683
1684 TEST_F(WebViewTest, AddFrameInCloseURLUnload)
1685 {
1686     CreateChildCounterFrameClient frameClient;
1687     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1688     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1689     m_webViewHelper.webViewImpl()->mainFrame()->dispatchUnloadEvent();
1690     EXPECT_EQ(0, frameClient.count());
1691     m_webViewHelper.reset();
1692 }
1693
1694 TEST_F(WebViewTest, AddFrameInNavigateUnload)
1695 {
1696     CreateChildCounterFrameClient frameClient;
1697     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1698     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1699     FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
1700     EXPECT_EQ(0, frameClient.count());
1701     m_webViewHelper.reset();
1702 }
1703
1704 TEST_F(WebViewTest, AddFrameInChildInNavigateUnload)
1705 {
1706     CreateChildCounterFrameClient frameClient;
1707     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload_wrapper.html"));
1708     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1709     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload_wrapper.html", true, &frameClient);
1710     FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
1711     EXPECT_EQ(1, frameClient.count());
1712     m_webViewHelper.reset();
1713 }
1714
1715 class TouchEventHandlerWebViewClient : public FrameTestHelpers::TestWebViewClient {
1716 public:
1717     // WebWidgetClient methods
1718     virtual void hasTouchEventHandlers(bool state) override
1719     {
1720         m_hasTouchEventHandlerCount[state]++;
1721     }
1722
1723     // Local methods
1724     TouchEventHandlerWebViewClient() : m_hasTouchEventHandlerCount()
1725     {
1726     }
1727
1728     int getAndResetHasTouchEventHandlerCallCount(bool state)
1729     {
1730         int value = m_hasTouchEventHandlerCount[state];
1731         m_hasTouchEventHandlerCount[state] = 0;
1732         return value;
1733     }
1734
1735 private:
1736     int m_hasTouchEventHandlerCount[2];
1737 };
1738
1739 // This test verifies that WebWidgetClient::hasTouchEventHandlers is called
1740 // accordingly for various calls to EventHandlerRegistry::did{Add|Remove|
1741 // RemoveAll}EventHandler(..., TouchEvent). Verifying that those calls are made
1742 // correctly is the job of LayoutTests/fast/events/event-handler-count.html.
1743 TEST_F(WebViewTest, HasTouchEventHandlers)
1744 {
1745     TouchEventHandlerWebViewClient client;
1746     std::string url = m_baseURL + "has_touch_event_handlers.html";
1747     URLTestHelpers::registerMockedURLLoad(toKURL(url), "has_touch_event_handlers.html");
1748     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
1749     const EventHandlerRegistry::EventHandlerClass touchEvent = EventHandlerRegistry::TouchEvent;
1750
1751     // The page is initialized with at least one no-handlers call.
1752     // In practice we get two such calls because WebViewHelper::initializeAndLoad first
1753     // initializes and empty frame, and then loads a document into it, so there are two
1754     // FrameLoader::commitProvisionalLoad calls.
1755     EXPECT_GE(client.getAndResetHasTouchEventHandlerCallCount(false), 1);
1756     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1757
1758     // Adding the first document handler results in a has-handlers call.
1759     Document* document = webViewImpl->mainFrameImpl()->frame()->document();
1760     EventHandlerRegistry* registry = &document->frameHost()->eventHandlerRegistry();
1761     registry->didAddEventHandler(*document, touchEvent);
1762     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1763     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1764
1765     // Adding another handler has no effect.
1766     registry->didAddEventHandler(*document, touchEvent);
1767     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1768     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1769
1770     // Removing the duplicate handler has no effect.
1771     registry->didRemoveEventHandler(*document, touchEvent);
1772     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1773     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1774
1775     // Removing the final handler results in a no-handlers call.
1776     registry->didRemoveEventHandler(*document, touchEvent);
1777     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1778     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1779
1780     // Adding a handler on a div results in a has-handlers call.
1781     Element* parentDiv = document->getElementById("parentdiv");
1782     ASSERT(parentDiv);
1783     registry->didAddEventHandler(*parentDiv, touchEvent);
1784     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1785     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1786
1787     // Adding a duplicate handler on the div, clearing all document handlers
1788     // (of which there are none) and removing the extra handler on the div
1789     // all have no effect.
1790     registry->didAddEventHandler(*parentDiv, touchEvent);
1791     registry->didRemoveAllEventHandlers(*document);
1792     registry->didRemoveEventHandler(*parentDiv, touchEvent);
1793     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1794     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1795
1796     // Removing the final handler on the div results in a no-handlers call.
1797     registry->didRemoveEventHandler(*parentDiv, touchEvent);
1798     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1799     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1800
1801     // Adding two handlers then clearing them in a single call results in a
1802     // has-handlers then no-handlers call.
1803     registry->didAddEventHandler(*parentDiv, touchEvent);
1804     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1805     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1806     registry->didAddEventHandler(*parentDiv, touchEvent);
1807     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1808     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1809     registry->didRemoveAllEventHandlers(*parentDiv);
1810     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1811     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1812
1813     // Adding a handler inside of a child iframe results in a has-handlers call.
1814     Element* childFrame = document->getElementById("childframe");
1815     ASSERT(childFrame);
1816     Document* childDocument = toHTMLIFrameElement(childFrame)->contentDocument();
1817     Element* childDiv = childDocument->getElementById("childdiv");
1818     ASSERT(childDiv);
1819     registry->didAddEventHandler(*childDiv, touchEvent);
1820     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1821     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1822
1823     // Adding and clearing handlers in the parent doc or elsewhere in the child doc
1824     // has no impact.
1825     registry->didAddEventHandler(*document, touchEvent);
1826     registry->didAddEventHandler(*childFrame, touchEvent);
1827     registry->didAddEventHandler(*childDocument, touchEvent);
1828     registry->didRemoveAllEventHandlers(*document);
1829     registry->didRemoveAllEventHandlers(*childFrame);
1830     registry->didRemoveAllEventHandlers(*childDocument);
1831     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1832     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1833
1834     // Removing the final handler inside the child frame results in a no-handlers call.
1835     registry->didRemoveAllEventHandlers(*childDiv);
1836     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1837     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1838
1839     // Adding a handler inside the child frame results in a has-handlers call.
1840     registry->didAddEventHandler(*childDocument, touchEvent);
1841     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1842     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1843
1844     // Adding a handler in the parent document and removing the one in the frame
1845     // has no effect.
1846     registry->didAddEventHandler(*childFrame, touchEvent);
1847     registry->didRemoveEventHandler(*childDocument, touchEvent);
1848     registry->didRemoveAllEventHandlers(*childDocument);
1849     registry->didRemoveAllEventHandlers(*document);
1850     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1851     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1852
1853     // Now removing the handler in the parent document results in a no-handlers call.
1854     registry->didRemoveEventHandler(*childFrame, touchEvent);
1855     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1856     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1857
1858     // Free the webView before the TouchEventHandlerWebViewClient gets freed.
1859     m_webViewHelper.reset();
1860 }
1861
1862 // This test checks that deleting nodes which have only non-JS-registered touch
1863 // handlers also removes them from the event handler registry. Note that this
1864 // is different from detaching and re-attaching the same node, which is covered
1865 // by layout tests under fast/events/.
1866 TEST_F(WebViewTest, DeleteElementWithRegisteredHandler)
1867 {
1868     std::string url = m_baseURL + "simple_div.html";
1869     URLTestHelpers::registerMockedURLLoad(toKURL(url), "simple_div.html");
1870     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true);
1871
1872     RefPtrWillBePersistent<Document> document = webViewImpl->mainFrameImpl()->frame()->document();
1873     Element* div = document->getElementById("div");
1874     EventHandlerRegistry& registry = document->frameHost()->eventHandlerRegistry();
1875
1876     registry.didAddEventHandler(*div, EventHandlerRegistry::ScrollEvent);
1877     EXPECT_TRUE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
1878
1879     TrackExceptionState exceptionState;
1880     div->remove(exceptionState);
1881 #if ENABLE(OILPAN)
1882     // For oilpan we have to force a GC to ensure the event handlers have been removed when
1883     // checking below. We do a precise GC (collectAllGarbage does not scan the stack)
1884     // to ensure the div element dies. This is also why the Document is in a Persistent
1885     // since we want that to stay around.
1886     Heap::collectAllGarbage();
1887 #endif
1888     EXPECT_FALSE(registry.hasEventHandlers(EventHandlerRegistry::ScrollEvent));
1889 }
1890
1891 static WebRect ExpectedRootBounds(Document* document, float scaleFactor)
1892 {
1893     Element* element = document->getElementById("root");
1894     if (!element)
1895         element = document->getElementById("target");
1896     if (element->hasTagName(HTMLNames::iframeTag))
1897         return ExpectedRootBounds(toHTMLIFrameElement(element)->contentDocument(), scaleFactor);
1898
1899     IntRect boundingBox;
1900     if (element->hasTagName(HTMLNames::htmlTag))
1901         boundingBox = IntRect(IntPoint(0, 0), document->frame()->view()->contentsSize());
1902     else
1903         boundingBox = element->pixelSnappedBoundingBox();
1904     boundingBox = document->frame()->view()->contentsToWindow(boundingBox);
1905     boundingBox.scale(scaleFactor);
1906     return boundingBox;
1907 }
1908
1909 void WebViewTest::testSelectionRootBounds(const char* htmlFile, float pageScaleFactor)
1910 {
1911     std::string url = m_baseURL + htmlFile;
1912
1913     WebView* webView = m_webViewHelper.initializeAndLoad(url, true);
1914     webView->resize(WebSize(640, 480));
1915     webView->setPageScaleFactor(pageScaleFactor);
1916     webView->layout();
1917     runPendingTasks();
1918
1919     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1920     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
1921     HTMLDocument* document = toHTMLDocument(frame->frame()->document());
1922
1923     WebRect expectedRootBounds = ExpectedRootBounds(document, webView->pageScaleFactor());
1924     WebRect actualRootBounds;
1925     webView->getSelectionRootBounds(actualRootBounds);
1926     ASSERT_EQ(expectedRootBounds, actualRootBounds);
1927
1928     WebRect anchor, focus;
1929     webView->selectionBounds(anchor, focus);
1930     IntRect expectedIntRect = expectedRootBounds;
1931     ASSERT_TRUE(expectedIntRect.contains(anchor));
1932     // The "overflow" tests have the focus boundary outside of the element box.
1933     ASSERT_EQ(url.find("overflow") == std::string::npos, expectedIntRect.contains(focus));
1934 }
1935
1936 TEST_F(WebViewTest, GetSelectionRootBounds)
1937 {
1938     // Register all the pages we will be using.
1939     registerMockedHttpURLLoad("select_range_basic.html");
1940     registerMockedHttpURLLoad("select_range_div_editable.html");
1941     registerMockedHttpURLLoad("select_range_scroll.html");
1942     registerMockedHttpURLLoad("select_range_span_editable.html");
1943     registerMockedHttpURLLoad("select_range_input.html");
1944     registerMockedHttpURLLoad("select_range_input_overflow.html");
1945     registerMockedHttpURLLoad("select_range_textarea.html");
1946     registerMockedHttpURLLoad("select_range_textarea_overflow.html");
1947     registerMockedHttpURLLoad("select_range_iframe.html");
1948     registerMockedHttpURLLoad("select_range_iframe_div_editable.html");
1949     registerMockedHttpURLLoad("select_range_iframe_scroll.html");
1950     registerMockedHttpURLLoad("select_range_iframe_span_editable.html");
1951     registerMockedHttpURLLoad("select_range_iframe_input.html");
1952     registerMockedHttpURLLoad("select_range_iframe_input_overflow.html");
1953     registerMockedHttpURLLoad("select_range_iframe_textarea.html");
1954     registerMockedHttpURLLoad("select_range_iframe_textarea_overflow.html");
1955
1956     // Test with simple pages.
1957     testSelectionRootBounds("select_range_basic.html", 1.0f);
1958     testSelectionRootBounds("select_range_div_editable.html", 1.0f);
1959     testSelectionRootBounds("select_range_scroll.html", 1.0f);
1960     testSelectionRootBounds("select_range_span_editable.html", 1.0f);
1961     testSelectionRootBounds("select_range_input.html", 1.0f);
1962     testSelectionRootBounds("select_range_input_overflow.html", 1.0f);
1963     testSelectionRootBounds("select_range_textarea.html", 1.0f);
1964     testSelectionRootBounds("select_range_textarea_overflow.html", 1.0f);
1965
1966     // Test with the same pages as above in iframes.
1967     testSelectionRootBounds("select_range_iframe.html", 1.0f);
1968     testSelectionRootBounds("select_range_iframe_div_editable.html", 1.0f);
1969     testSelectionRootBounds("select_range_iframe_scroll.html", 1.0f);
1970     testSelectionRootBounds("select_range_iframe_span_editable.html", 1.0f);
1971     testSelectionRootBounds("select_range_iframe_input.html", 1.0f);
1972     testSelectionRootBounds("select_range_iframe_input_overflow.html", 1.0f);
1973     testSelectionRootBounds("select_range_iframe_textarea.html", 1.0f);
1974     testSelectionRootBounds("select_range_iframe_textarea_overflow.html", 1.0f);
1975
1976     // Basic page with scale factor.
1977     testSelectionRootBounds("select_range_basic.html", 0.0f);
1978     testSelectionRootBounds("select_range_basic.html", 0.1f);
1979     testSelectionRootBounds("select_range_basic.html", 1.5f);
1980     testSelectionRootBounds("select_range_basic.html", 2.0f);
1981 }
1982
1983 TEST_F(WebViewTest, GetSelectionRootBoundsBrokenHeight)
1984 {
1985     WebSize contentSize = WebSize(640, 480);
1986
1987     registerMockedHttpURLLoad("select_range_basic_broken_height.html");
1988
1989     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "select_range_basic_broken_height.html", true);
1990     webView->resize(contentSize);
1991     webView->setPageScaleFactor(1.0f, WebPoint(0, 0));
1992     webView->layout();
1993     runPendingTasks();
1994
1995     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
1996     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
1997
1998     WebRect expectedRootBounds = WebRect(0, 0, contentSize.width, contentSize.height);
1999     WebRect actualRootBounds;
2000     webView->getSelectionRootBounds(actualRootBounds);
2001     ASSERT_EQ(expectedRootBounds, actualRootBounds);
2002 }
2003
2004 class NonUserInputTextUpdateWebViewClient : public FrameTestHelpers::TestWebViewClient {
2005 public:
2006     NonUserInputTextUpdateWebViewClient() : m_textIsUpdated(false) { }
2007
2008     // WebWidgetClient methods
2009     virtual void didUpdateTextOfFocusedElementByNonUserInput() override
2010     {
2011         m_textIsUpdated = true;
2012     }
2013
2014     void reset()
2015     {
2016         m_textIsUpdated = false;
2017     }
2018
2019     bool textIsUpdated() const
2020     {
2021         return m_textIsUpdated;
2022     }
2023
2024 private:
2025     int m_textIsUpdated;
2026 };
2027
2028 // This test verifies that WebWidgetClient::didUpdateTextOfFocusedElementByNonUserInput is
2029 // called iff value of a focused element is modified via script.
2030 TEST_F(WebViewTest, NonUserInputTextUpdate)
2031 {
2032     NonUserInputTextUpdateWebViewClient client;
2033     std::string url = m_baseURL + "non_user_input_text_update.html";
2034     URLTestHelpers::registerMockedURLLoad(toKURL(url), "non_user_input_text_update.html");
2035     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
2036     webViewImpl->setInitialFocus(false);
2037
2038     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewImpl->mainFrame());
2039     HTMLDocument* document = toHTMLDocument(frame->frame()->document());
2040
2041     // (A) <input>
2042     // (A.1) Focused and value is changed by script.
2043     client.reset();
2044     EXPECT_FALSE(client.textIsUpdated());
2045
2046     HTMLInputElement* inputElement = toHTMLInputElement(document->getElementById("input"));
2047     document->setFocusedElement(inputElement);
2048     webViewImpl->setFocus(true);
2049     EXPECT_EQ(document->focusedElement(), static_cast<Element*>(inputElement));
2050
2051     // Emulate value change from script.
2052     inputElement->setValue("testA");
2053     EXPECT_TRUE(client.textIsUpdated());
2054     WebTextInputInfo info = webViewImpl->textInputInfo();
2055     EXPECT_EQ("testA", std::string(info.value.utf8().data()));
2056
2057     // (A.2) Focused and user input modifies value.
2058     client.reset();
2059     EXPECT_FALSE(client.textIsUpdated());
2060
2061     WebVector<WebCompositionUnderline> emptyUnderlines;
2062     webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
2063     webViewImpl->confirmComposition(WebWidget::KeepSelection);
2064     EXPECT_FALSE(client.textIsUpdated());
2065     info = webViewImpl->textInputInfo();
2066     EXPECT_EQ("testA2", std::string(info.value.utf8().data()));
2067
2068     // (A.3) Unfocused and value is changed by script.
2069     client.reset();
2070     EXPECT_FALSE(client.textIsUpdated());
2071     document->setFocusedElement(nullptr);
2072     webViewImpl->setFocus(false);
2073     EXPECT_NE(document->focusedElement(), static_cast<Element*>(inputElement));
2074     inputElement->setValue("testA3");
2075     EXPECT_FALSE(client.textIsUpdated());
2076
2077     // (B) <textarea>
2078     // (B.1) Focused and value is changed by script.
2079     client.reset();
2080     EXPECT_FALSE(client.textIsUpdated());
2081     HTMLTextAreaElement* textAreaElement = toHTMLTextAreaElement(document->getElementById("textarea"));
2082     document->setFocusedElement(textAreaElement);
2083     webViewImpl->setFocus(true);
2084     EXPECT_EQ(document->focusedElement(), static_cast<Element*>(textAreaElement));
2085     textAreaElement->setValue("testB");
2086     EXPECT_TRUE(client.textIsUpdated());
2087     info = webViewImpl->textInputInfo();
2088     EXPECT_EQ("testB", std::string(info.value.utf8().data()));
2089
2090     // (B.2) Focused and user input modifies value.
2091     client.reset();
2092     EXPECT_FALSE(client.textIsUpdated());
2093     webViewImpl->setComposition(WebString::fromUTF8("2"), emptyUnderlines, 1, 1);
2094     webViewImpl->confirmComposition(WebWidget::KeepSelection);
2095     info = webViewImpl->textInputInfo();
2096     EXPECT_EQ("testB2", std::string(info.value.utf8().data()));
2097
2098     // (B.3) Unfocused and value is changed by script.
2099     client.reset();
2100     EXPECT_FALSE(client.textIsUpdated());
2101     document->setFocusedElement(nullptr);
2102     webViewImpl->setFocus(false);
2103     EXPECT_NE(document->focusedElement(), static_cast<Element*>(textAreaElement));
2104     inputElement->setValue("testB3");
2105     EXPECT_FALSE(client.textIsUpdated());
2106
2107     // Free the webView before freeing the NonUserInputTextUpdateWebViewClient.
2108     m_webViewHelper.reset();
2109 }
2110
2111 // Check that the WebAutofillClient is correctly notified about first user
2112 // gestures after load, following various input events.
2113 TEST_F(WebViewTest, FirstUserGestureObservedKeyEvent)
2114 {
2115     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
2116     MockAutofillClient client;
2117     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
2118     webView->setAutofillClient(&client);
2119     webView->setInitialFocus(false);
2120
2121     EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2122
2123     WebKeyboardEvent keyEvent;
2124     keyEvent.windowsKeyCode = VKEY_SPACE;
2125     keyEvent.type = WebInputEvent::RawKeyDown;
2126     keyEvent.setKeyIdentifierFromWindowsKeyCode();
2127     webView->handleInputEvent(keyEvent);
2128     keyEvent.type = WebInputEvent::KeyUp;
2129     webView->handleInputEvent(keyEvent);
2130
2131     EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2132     webView->setAutofillClient(0);
2133 }
2134
2135 TEST_F(WebViewTest, FirstUserGestureObservedMouseEvent)
2136 {
2137     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("form.html"));
2138     MockAutofillClient client;
2139     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "form.html", true);
2140     webView->setAutofillClient(&client);
2141     webView->setInitialFocus(false);
2142
2143     EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2144
2145     WebMouseEvent mouseEvent;
2146     mouseEvent.button = WebMouseEvent::ButtonLeft;
2147     mouseEvent.x = 1;
2148     mouseEvent.y = 1;
2149     mouseEvent.clickCount = 1;
2150     mouseEvent.type = WebInputEvent::MouseDown;
2151     webView->handleInputEvent(mouseEvent);
2152     mouseEvent.type = WebInputEvent::MouseUp;
2153     webView->handleInputEvent(mouseEvent);
2154
2155     EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2156     webView->setAutofillClient(0);
2157 }
2158
2159 TEST_F(WebViewTest, FirstUserGestureObservedGestureTap)
2160 {
2161     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
2162     MockAutofillClient client;
2163     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
2164     webView->setAutofillClient(&client);
2165     webView->setInitialFocus(false);
2166
2167     EXPECT_EQ(0, client.getUserGestureNotificationsCount());
2168
2169     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, WebString::fromUTF8("target")));
2170
2171     EXPECT_EQ(1, client.getUserGestureNotificationsCount());
2172     webView->setAutofillClient(0);
2173 }
2174
2175 TEST_F(WebViewTest, CompareSelectAllToContentAsText)
2176 {
2177     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
2178     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
2179
2180     WebLocalFrameImpl* frame = toWebLocalFrameImpl(webView->mainFrame());
2181     frame->executeScript(WebScriptSource(WebString::fromUTF8("document.execCommand('SelectAll', false, null)")));
2182     std::string actual = frame->selectionAsText().utf8();
2183
2184     const int kMaxOutputCharacters = 1024;
2185     std::string expected = frame->contentAsText(kMaxOutputCharacters).utf8();
2186     EXPECT_EQ(expected, actual);
2187 }
2188
2189 TEST_F(WebViewTest, AutoResizeSubtreeLayout)
2190 {
2191     std::string url = m_baseURL + "subtree-layout.html";
2192     URLTestHelpers::registerMockedURLLoad(toKURL(url), "subtree-layout.html");
2193     WebView* webView = m_webViewHelper.initialize(true);
2194
2195     webView->enableAutoResizeMode(WebSize(200, 200), WebSize(200, 200));
2196     loadFrame(webView->mainFrame(), url);
2197
2198     FrameView* frameView = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
2199
2200     // Auto-resizing used to ASSERT(needsLayout()) in RenderBlockFlow::layout. This EXPECT is
2201     // merely a dummy. The real test is that we don't trigger asserts in debug builds.
2202     EXPECT_FALSE(frameView->needsLayout());
2203 };
2204
2205 } // namespace