22b1aaa065fd5bf8998b1421dd9eb36cf8b4cfd3
[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 "WebView.h"
33
34 #include <gtest/gtest.h>
35 #include "FrameTestHelpers.h"
36 #include "URLTestHelpers.h"
37 #include "WebAutofillClient.h"
38 #include "WebContentDetectionResult.h"
39 #include "WebDateTimeChooserCompletion.h"
40 #include "WebDocument.h"
41 #include "WebElement.h"
42 #include "WebFrame.h"
43 #include "WebFrameClient.h"
44 #include "WebFrameImpl.h"
45 #include "WebHitTestResult.h"
46 #include "WebInputEvent.h"
47 #include "WebSettings.h"
48 #include "WebSettingsImpl.h"
49 #include "WebViewClient.h"
50 #include "WebViewImpl.h"
51 #include "WebWidget.h"
52 #include "core/dom/Document.h"
53 #include "core/dom/Element.h"
54 #include "core/html/HTMLDocument.h"
55 #include "core/html/HTMLIFrameElement.h"
56 #include "core/html/HTMLInputElement.h"
57 #include "core/loader/FrameLoadRequest.h"
58 #include "core/frame/FrameView.h"
59 #include "core/page/Chrome.h"
60 #include "core/frame/Settings.h"
61 #include "platform/KeyboardCodes.h"
62 #include "platform/graphics/Color.h"
63 #include "public/platform/Platform.h"
64 #include "public/platform/WebDragData.h"
65 #include "public/platform/WebSize.h"
66 #include "public/platform/WebThread.h"
67 #include "public/platform/WebUnitTestSupport.h"
68 #include "public/web/WebDragOperation.h"
69 #include "public/web/WebWidgetClient.h"
70 #include "third_party/skia/include/core/SkBitmap.h"
71 #include "third_party/skia/include/core/SkBitmapDevice.h"
72 #include "third_party/skia/include/core/SkCanvas.h"
73
74 using namespace blink;
75 using blink::FrameTestHelpers::runPendingTasks;
76 using blink::URLTestHelpers::toKURL;
77
78 namespace {
79
80 enum HorizontalScrollbarState {
81     NoHorizontalScrollbar,
82     VisibleHorizontalScrollbar,
83 };
84
85 enum VerticalScrollbarState {
86     NoVerticalScrollbar,
87     VisibleVerticalScrollbar,
88 };
89
90 class TestData {
91 public:
92     void setWebView(WebView* webView) { m_webView = toWebViewImpl(webView); }
93     void setSize(const WebSize& newSize) { m_size = newSize; }
94     HorizontalScrollbarState horizontalScrollbarState() const
95     {
96         return m_webView->hasHorizontalScrollbar() ? VisibleHorizontalScrollbar: NoHorizontalScrollbar;
97     }
98     VerticalScrollbarState verticalScrollbarState() const
99     {
100         return m_webView->hasVerticalScrollbar() ? VisibleVerticalScrollbar : NoVerticalScrollbar;
101     }
102     int width() const { return m_size.width; }
103     int height() const { return m_size.height; }
104
105 private:
106     WebSize m_size;
107     WebViewImpl* m_webView;
108 };
109
110 class AutoResizeWebViewClient : public WebViewClient {
111 public:
112     // WebViewClient methods
113     virtual void didAutoResize(const WebSize& newSize) { m_testData.setSize(newSize); }
114
115     // Local methods
116     TestData& testData() { return m_testData; }
117
118 private:
119     TestData m_testData;
120 };
121
122 class TapHandlingWebViewClient : public WebViewClient {
123 public:
124     // WebViewClient methods
125     virtual void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled)
126     {
127         if (event.type == WebInputEvent::GestureTap) {
128             m_tapX = event.x;
129             m_tapY = event.y;
130         } else if (event.type == WebInputEvent::GestureLongPress) {
131             m_longpressX = event.x;
132             m_longpressY = event.y;
133         }
134     }
135
136     // Local methods
137     void reset()
138     {
139         m_tapX = -1;
140         m_tapY = -1;
141         m_longpressX = -1;
142         m_longpressY = -1;
143     }
144     int tapX() { return m_tapX; }
145     int tapY() { return m_tapY; }
146     int longpressX() { return m_longpressX; }
147     int longpressY() { return m_longpressY; }
148
149 private:
150     int m_tapX;
151     int m_tapY;
152     int m_longpressX;
153     int m_longpressY;
154 };
155
156 class FakeCompositingWebViewClient : public WebViewClient {
157 public:
158     virtual ~FakeCompositingWebViewClient()
159     {
160     }
161
162     virtual void initializeLayerTreeView() OVERRIDE
163     {
164         m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting(WebUnitTestSupport::TestViewTypeUnitTest));
165         ASSERT(m_layerTreeView);
166     }
167
168     virtual WebLayerTreeView* layerTreeView() OVERRIDE
169     {
170         return m_layerTreeView.get();
171     }
172
173 private:
174     OwnPtr<WebLayerTreeView> m_layerTreeView;
175 };
176
177 class DateTimeChooserWebViewClient : public WebViewClient {
178 public:
179     WebDateTimeChooserCompletion* chooserCompletion()
180     {
181         return m_chooserCompletion;
182     }
183
184     void clearChooserCompletion()
185     {
186         m_chooserCompletion = 0;
187     }
188
189     // WebViewClient methods
190     virtual bool openDateTimeChooser(const WebDateTimeChooserParams&, WebDateTimeChooserCompletion* chooser_completion) OVERRIDE
191     {
192         m_chooserCompletion = chooser_completion;
193         return true;
194     }
195
196 private:
197     WebDateTimeChooserCompletion* m_chooserCompletion;
198
199 };
200
201 class WebViewTest : public testing::Test {
202 public:
203     WebViewTest()
204         : m_baseURL("http://www.test.com/")
205     {
206     }
207
208     virtual void TearDown()
209     {
210         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
211     }
212
213 protected:
214     void registerMockedHttpURLLoad(const std::string& fileName)
215     {
216         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
217     }
218
219     void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
220                         const std::string& pageWidth, const std::string& pageHeight,
221                         int expectedWidth, int expectedHeight,
222                         HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState);
223
224     void testTextInputType(WebTextInputType expectedType, const std::string& htmlFile);
225     void testInputMode(const WebString& expectedInputMode, const std::string& htmlFile);
226     void testSelectionRootBounds(const char* htmlFile, float pageScaleFactor);
227
228     std::string m_baseURL;
229     FrameTestHelpers::WebViewHelper m_webViewHelper;
230 };
231
232 TEST_F(WebViewTest, SetBaseBackgroundColor)
233 {
234     const WebColor kWhite    = 0xFFFFFFFF;
235     const WebColor kBlue     = 0xFF0000FF;
236     const WebColor kDarkCyan = 0xFF227788;
237     const WebColor kTranslucentPutty = 0x80BFB196;
238
239     WebView* webView = m_webViewHelper.initialize();
240     EXPECT_EQ(kWhite, webView->backgroundColor());
241
242     webView->setBaseBackgroundColor(kBlue);
243     EXPECT_EQ(kBlue, webView->backgroundColor());
244
245     WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
246     webView->mainFrame()->loadHTMLString(
247         "<html><head><style>body {background-color:#227788}</style></head></html>", baseURL);
248     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
249     EXPECT_EQ(kDarkCyan, webView->backgroundColor());
250
251     webView->mainFrame()->loadHTMLString(
252         "<html><head><style>body {background-color:rgba(255,0,0,0.5)}</style></head></html>", baseURL);
253     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
254     // Expected: red (50% alpha) blended atop base of kBlue.
255     EXPECT_EQ(0xFF7F0080, webView->backgroundColor());
256
257     webView->setBaseBackgroundColor(kTranslucentPutty);
258     // Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha.
259     EXPECT_EQ(0xBFE93B32, webView->backgroundColor());
260 }
261
262 TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame)
263 {
264     const WebColor kBlue = 0xFF0000FF;
265     WebView* webView = WebViewImpl::create(0);
266     EXPECT_NE(kBlue, webView->backgroundColor());
267     // webView does not have a frame yet, but we should still be able to set the background color.
268     webView->setBaseBackgroundColor(kBlue);
269     EXPECT_EQ(kBlue, webView->backgroundColor());
270 }
271
272 TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent)
273 {
274     const WebColor kAlphaRed = 0x80FF0000;
275     const WebColor kAlphaGreen = 0x8000FF00;
276     const int kWidth = 100;
277     const int kHeight = 100;
278
279     // Set WebView background to green with alpha.
280     WebView* webView = m_webViewHelper.initialize();
281     webView->setBaseBackgroundColor(kAlphaGreen);
282     webView->settings()->setShouldClearDocumentBackground(false);
283     webView->resize(WebSize(kWidth, kHeight));
284     webView->layout();
285
286     // Set canvas background to red with alpha.
287     SkBitmap bitmap;
288     ASSERT_TRUE(bitmap.allocN32Pixels(kWidth, kHeight));
289     SkCanvas canvas(bitmap);
290     canvas.clear(kAlphaRed);
291     webView->paint(&canvas, WebRect(0, 0, kWidth, kHeight));
292
293     // The result should be a blend of red and green.
294     SkColor color = bitmap.getColor(kWidth / 2, kHeight / 2);
295     EXPECT_TRUE(WebCore::redChannel(color));
296     EXPECT_TRUE(WebCore::greenChannel(color));
297 }
298
299 TEST_F(WebViewTest, FocusIsInactive)
300 {
301     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
302     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
303
304     webView->setFocus(true);
305     webView->setIsActive(true);
306     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
307     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
308
309     WebCore::HTMLDocument* document = WebCore::toHTMLDocument(frame->frame()->document());
310     EXPECT_TRUE(document->hasFocus());
311     webView->setFocus(false);
312     webView->setIsActive(false);
313     EXPECT_FALSE(document->hasFocus());
314     webView->setFocus(true);
315     webView->setIsActive(true);
316     EXPECT_TRUE(document->hasFocus());
317     webView->setFocus(true);
318     webView->setIsActive(false);
319     EXPECT_FALSE(document->hasFocus());
320     webView->setFocus(false);
321     webView->setIsActive(true);
322     EXPECT_FALSE(document->hasFocus());
323 }
324
325 TEST_F(WebViewTest, ActiveState)
326 {
327     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
328     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "visible_iframe.html");
329
330     ASSERT_TRUE(webView);
331
332     webView->setIsActive(true);
333     EXPECT_TRUE(webView->isActive());
334
335     webView->setIsActive(false);
336     EXPECT_FALSE(webView->isActive());
337
338     webView->setIsActive(true);
339     EXPECT_TRUE(webView->isActive());
340 }
341
342 TEST_F(WebViewTest, HitTestResultAtWithPageScale)
343 {
344     std::string url = m_baseURL + "specify_size.html?" + "50px" + ":" + "50px";
345     URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
346     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0);
347     webView->resize(WebSize(100, 100));
348     WebPoint hitPoint(75, 75);
349
350     // Image is at top left quandrant, so should not hit it.
351     WebHitTestResult negativeResult = webView->hitTestResultAt(hitPoint);
352     ASSERT_EQ(WebNode::ElementNode, negativeResult.node().nodeType());
353     EXPECT_FALSE(negativeResult.node().to<WebElement>().hasTagName("img"));
354     negativeResult.reset();
355
356     // Scale page up 2x so image should occupy the whole viewport.
357     webView->setPageScaleFactor(2.0f, WebPoint(0, 0));
358     WebHitTestResult positiveResult = webView->hitTestResultAt(hitPoint);
359     ASSERT_EQ(WebNode::ElementNode, positiveResult.node().nodeType());
360     EXPECT_TRUE(positiveResult.node().to<WebElement>().hasTagName("img"));
361     positiveResult.reset();
362 }
363
364 void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
365                                  const std::string& pageWidth, const std::string& pageHeight,
366                                  int expectedWidth, int expectedHeight,
367                                  HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState)
368 {
369     AutoResizeWebViewClient client;
370     std::string url = m_baseURL + "specify_size.html?" + pageWidth + ":" + pageHeight;
371     URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
372     WebView* webView = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
373     client.testData().setWebView(webView);
374
375     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
376     WebCore::FrameView* frameView = frame->frame()->view();
377     frameView->layout();
378     EXPECT_FALSE(frameView->layoutPending());
379     EXPECT_FALSE(frameView->needsLayout());
380
381     webView->enableAutoResizeMode(minAutoResize, maxAutoResize);
382     EXPECT_TRUE(frameView->layoutPending());
383     EXPECT_TRUE(frameView->needsLayout());
384     frameView->layout();
385
386     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
387
388     EXPECT_EQ(expectedWidth, client.testData().width());
389     EXPECT_EQ(expectedHeight, client.testData().height());
390     EXPECT_EQ(expectedHorizontalState, client.testData().horizontalScrollbarState());
391     EXPECT_EQ(expectedVerticalState, client.testData().verticalScrollbarState());
392
393     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
394 }
395
396 TEST_F(WebViewTest, DISABLED_AutoResizeMinimumSize)
397 {
398     WebSize minAutoResize(91, 56);
399     WebSize maxAutoResize(403, 302);
400     std::string pageWidth = "91px";
401     std::string pageHeight = "56px";
402     int expectedWidth = 91;
403     int expectedHeight = 56;
404     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
405                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
406 }
407
408 TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth)
409 {
410     WebSize minAutoResize(90, 95);
411     WebSize maxAutoResize(90, 100);
412     std::string pageWidth = "60px";
413     std::string pageHeight = "200px";
414     int expectedWidth = 90;
415     int expectedHeight = 100;
416     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
417                    expectedWidth, expectedHeight, NoHorizontalScrollbar, VisibleVerticalScrollbar);
418 }
419
420 TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
421 {
422     WebSize minAutoResize(90, 100);
423     WebSize maxAutoResize(200, 100);
424     std::string pageWidth = "300px";
425     std::string pageHeight = "80px";
426     int expectedWidth = 200;
427     int expectedHeight = 100;
428     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
429                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, NoVerticalScrollbar);
430 }
431
432 // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
433 // It seems we can run three AutoResize tests, then the next one breaks.
434 TEST_F(WebViewTest, DISABLED_AutoResizeInBetweenSizes)
435 {
436     WebSize minAutoResize(90, 95);
437     WebSize maxAutoResize(200, 300);
438     std::string pageWidth = "100px";
439     std::string pageHeight = "200px";
440     int expectedWidth = 100;
441     int expectedHeight = 200;
442     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
443                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
444 }
445
446 TEST_F(WebViewTest, DISABLED_AutoResizeOverflowSizes)
447 {
448     WebSize minAutoResize(90, 95);
449     WebSize maxAutoResize(200, 300);
450     std::string pageWidth = "300px";
451     std::string pageHeight = "400px";
452     int expectedWidth = 200;
453     int expectedHeight = 300;
454     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
455                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
456 }
457
458 TEST_F(WebViewTest, DISABLED_AutoResizeMaxSize)
459 {
460     WebSize minAutoResize(90, 95);
461     WebSize maxAutoResize(200, 300);
462     std::string pageWidth = "200px";
463     std::string pageHeight = "300px";
464     int expectedWidth = 200;
465     int expectedHeight = 300;
466     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
467                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
468 }
469
470 void WebViewTest::testTextInputType(WebTextInputType expectedType, const std::string& htmlFile)
471 {
472     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
473     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
474     webView->setInitialFocus(false);
475     EXPECT_EQ(expectedType, webView->textInputInfo().type);
476 }
477
478 TEST_F(WebViewTest, TextInputType)
479 {
480     testTextInputType(WebTextInputTypeText, "input_field_default.html");
481     testTextInputType(WebTextInputTypePassword, "input_field_password.html");
482     testTextInputType(WebTextInputTypeEmail, "input_field_email.html");
483     testTextInputType(WebTextInputTypeSearch, "input_field_search.html");
484     testTextInputType(WebTextInputTypeNumber, "input_field_number.html");
485     testTextInputType(WebTextInputTypeTelephone, "input_field_tel.html");
486     testTextInputType(WebTextInputTypeURL, "input_field_url.html");
487 }
488
489 void WebViewTest::testInputMode(const WebString& expectedInputMode, const std::string& htmlFile)
490 {
491     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
492     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
493     webView->setInitialFocus(false);
494     EXPECT_EQ(expectedInputMode, webView->textInputInfo().inputMode);
495 }
496
497 TEST_F(WebViewTest, InputMode)
498 {
499     testInputMode(WebString(), "input_mode_default.html");
500     testInputMode(WebString("unknown"), "input_mode_default_unknown.html");
501     testInputMode(WebString("verbatim"), "input_mode_default_verbatim.html");
502     testInputMode(WebString("verbatim"), "input_mode_type_text_verbatim.html");
503     testInputMode(WebString("verbatim"), "input_mode_type_search_verbatim.html");
504     testInputMode(WebString(), "input_mode_type_url_verbatim.html");
505     testInputMode(WebString("verbatim"), "input_mode_textarea_verbatim.html");
506 }
507
508 TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
509 {
510     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
511     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
512     webView->setInitialFocus(false);
513     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
514     frame->setEditableSelectionOffsets(5, 13);
515     EXPECT_EQ("56789abc", frame->selectionAsText());
516     WebTextInputInfo info = webView->textInputInfo();
517     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
518     EXPECT_EQ(5, info.selectionStart);
519     EXPECT_EQ(13, info.selectionEnd);
520     EXPECT_EQ(-1, info.compositionStart);
521     EXPECT_EQ(-1, info.compositionEnd);
522
523     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_populated.html"));
524     webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_editable_populated.html");
525     webView->setInitialFocus(false);
526     frame = toWebFrameImpl(webView->mainFrame());
527     frame->setEditableSelectionOffsets(8, 19);
528     EXPECT_EQ("89abcdefghi", frame->selectionAsText());
529     info = webView->textInputInfo();
530     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
531     EXPECT_EQ(8, info.selectionStart);
532     EXPECT_EQ(19, info.selectionEnd);
533     EXPECT_EQ(-1, info.compositionStart);
534     EXPECT_EQ(-1, info.compositionEnd);
535 }
536
537 TEST_F(WebViewTest, ConfirmCompositionCursorPositionChange)
538 {
539     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
540     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
541     webView->setInitialFocus(false);
542
543     // Set up a composition that needs to be committed.
544     std::string compositionText("hello");
545
546     WebVector<WebCompositionUnderline> emptyUnderlines;
547     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
548
549     WebTextInputInfo info = webView->textInputInfo();
550     EXPECT_EQ("hello", std::string(info.value.utf8().data()));
551     EXPECT_EQ(3, info.selectionStart);
552     EXPECT_EQ(3, info.selectionEnd);
553     EXPECT_EQ(0, info.compositionStart);
554     EXPECT_EQ(5, info.compositionEnd);
555
556     webView->confirmComposition(WebWidget::KeepSelection);
557     info = webView->textInputInfo();
558     EXPECT_EQ(3, info.selectionStart);
559     EXPECT_EQ(3, info.selectionEnd);
560     EXPECT_EQ(-1, info.compositionStart);
561     EXPECT_EQ(-1, info.compositionEnd);
562
563     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 3, 3);
564     info = webView->textInputInfo();
565     EXPECT_EQ("helhellolo", std::string(info.value.utf8().data()));
566     EXPECT_EQ(6, info.selectionStart);
567     EXPECT_EQ(6, info.selectionEnd);
568     EXPECT_EQ(3, info.compositionStart);
569     EXPECT_EQ(8, info.compositionEnd);
570
571     webView->confirmComposition(WebWidget::DoNotKeepSelection);
572     info = webView->textInputInfo();
573     EXPECT_EQ(8, info.selectionStart);
574     EXPECT_EQ(8, info.selectionEnd);
575     EXPECT_EQ(-1, info.compositionStart);
576     EXPECT_EQ(-1, info.compositionEnd);
577 }
578
579 TEST_F(WebViewTest, InsertNewLinePlacementAfterConfirmComposition)
580 {
581     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
582     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
583     webView->setInitialFocus(false);
584
585     WebVector<WebCompositionUnderline> emptyUnderlines;
586
587     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
588     frame->setEditableSelectionOffsets(4, 4);
589     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
590
591     WebTextInputInfo info = webView->textInputInfo();
592     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
593     EXPECT_EQ(4, info.selectionStart);
594     EXPECT_EQ(4, info.selectionEnd);
595     EXPECT_EQ(8, info.compositionStart);
596     EXPECT_EQ(12, info.compositionEnd);
597
598     webView->confirmComposition(WebWidget::KeepSelection);
599     info = webView->textInputInfo();
600     EXPECT_EQ(4, info.selectionStart);
601     EXPECT_EQ(4, info.selectionEnd);
602     EXPECT_EQ(-1, info.compositionStart);
603     EXPECT_EQ(-1, info.compositionEnd);
604
605     std::string compositionText("\n");
606     webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
607     info = webView->textInputInfo();
608     EXPECT_EQ(5, info.selectionStart);
609     EXPECT_EQ(5, info.selectionEnd);
610     EXPECT_EQ(-1, info.compositionStart);
611     EXPECT_EQ(-1, info.compositionEnd);
612     EXPECT_EQ("0123\n456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
613 }
614
615 TEST_F(WebViewTest, ExtendSelectionAndDelete)
616 {
617     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
618     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
619     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
620     webView->setInitialFocus(false);
621     frame->setEditableSelectionOffsets(10, 10);
622     frame->extendSelectionAndDelete(5, 8);
623     WebTextInputInfo info = webView->textInputInfo();
624     EXPECT_EQ("01234ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
625     EXPECT_EQ(5, info.selectionStart);
626     EXPECT_EQ(5, info.selectionEnd);
627     frame->extendSelectionAndDelete(10, 0);
628     info = webView->textInputInfo();
629     EXPECT_EQ("ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
630 }
631
632 TEST_F(WebViewTest, SetCompositionFromExistingText)
633 {
634     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
635     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
636     webView->setInitialFocus(false);
637     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
638     underlines[0] = blink::WebCompositionUnderline(0, 4, 0, false);
639     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
640     frame->setEditableSelectionOffsets(4, 10);
641     frame->setCompositionFromExistingText(8, 12, underlines);
642     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
643     EXPECT_EQ(8u, underlineResults[0].startOffset);
644     EXPECT_EQ(12u, underlineResults[0].endOffset);
645     WebTextInputInfo info = webView->textInputInfo();
646     EXPECT_EQ(4, info.selectionStart);
647     EXPECT_EQ(10, info.selectionEnd);
648     EXPECT_EQ(8, info.compositionStart);
649     EXPECT_EQ(12, info.compositionEnd);
650     WebVector<WebCompositionUnderline> emptyUnderlines;
651     frame->setCompositionFromExistingText(0, 0, emptyUnderlines);
652     info = webView->textInputInfo();
653     EXPECT_EQ(4, info.selectionStart);
654     EXPECT_EQ(10, info.selectionEnd);
655     EXPECT_EQ(-1, info.compositionStart);
656     EXPECT_EQ(-1, info.compositionEnd);
657 }
658
659 TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea)
660 {
661     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("text_area_populated.html"));
662     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "text_area_populated.html");
663     webView->setInitialFocus(false);
664     WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1));
665     underlines[0] = blink::WebCompositionUnderline(0, 4, 0, false);
666     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
667     frame->setEditableSelectionOffsets(27, 27);
668     std::string newLineText("\n");
669     webView->confirmComposition(WebString::fromUTF8(newLineText.c_str()));
670     WebTextInputInfo info = webView->textInputInfo();
671     EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
672
673     frame->setEditableSelectionOffsets(31, 31);
674     frame->setCompositionFromExistingText(30, 34, underlines);
675     WebVector<WebCompositionUnderline> underlineResults = toWebViewImpl(webView)->compositionUnderlines();
676     EXPECT_EQ(2u, underlineResults[0].startOffset);
677     EXPECT_EQ(6u, underlineResults[0].endOffset);
678     info = webView->textInputInfo();
679     EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.utf8().data()));
680     EXPECT_EQ(31, info.selectionStart);
681     EXPECT_EQ(31, info.selectionEnd);
682     EXPECT_EQ(30, info.compositionStart);
683     EXPECT_EQ(34, info.compositionEnd);
684
685     std::string compositionText("yolo");
686     webView->confirmComposition(WebString::fromUTF8(compositionText.c_str()));
687     info = webView->textInputInfo();
688     EXPECT_EQ("0123456789abcdefghijklmnopq\nrsyoloxyz", std::string(info.value.utf8().data()));
689     EXPECT_EQ(34, info.selectionStart);
690     EXPECT_EQ(34, info.selectionEnd);
691     EXPECT_EQ(-1, info.compositionStart);
692     EXPECT_EQ(-1, info.compositionEnd);
693 }
694
695 TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition)
696 {
697     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
698     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
699     webView->setInitialFocus(false);
700
701     std::string compositionTextFirst("hello ");
702     std::string compositionTextSecond("world");
703     WebVector<WebCompositionUnderline> emptyUnderlines;
704
705     webView->confirmComposition(WebString::fromUTF8(compositionTextFirst.c_str()));
706     webView->setComposition(WebString::fromUTF8(compositionTextSecond.c_str()), emptyUnderlines, 5, 5);
707
708     WebTextInputInfo info = webView->textInputInfo();
709     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
710     EXPECT_EQ(11, info.selectionStart);
711     EXPECT_EQ(11, info.selectionEnd);
712     EXPECT_EQ(6, info.compositionStart);
713     EXPECT_EQ(11, info.compositionEnd);
714
715     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
716     frame->setEditableSelectionOffsets(6, 6);
717     info = webView->textInputInfo();
718     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
719     EXPECT_EQ(6, info.selectionStart);
720     EXPECT_EQ(6, info.selectionEnd);
721     EXPECT_EQ(6, info.compositionStart);
722     EXPECT_EQ(11, info.compositionEnd);
723
724     frame->setEditableSelectionOffsets(8, 8);
725     info = webView->textInputInfo();
726     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
727     EXPECT_EQ(8, info.selectionStart);
728     EXPECT_EQ(8, info.selectionEnd);
729     EXPECT_EQ(6, info.compositionStart);
730     EXPECT_EQ(11, info.compositionEnd);
731
732     frame->setEditableSelectionOffsets(11, 11);
733     info = webView->textInputInfo();
734     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
735     EXPECT_EQ(11, info.selectionStart);
736     EXPECT_EQ(11, info.selectionEnd);
737     EXPECT_EQ(6, info.compositionStart);
738     EXPECT_EQ(11, info.compositionEnd);
739
740     frame->setEditableSelectionOffsets(6, 11);
741     info = webView->textInputInfo();
742     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
743     EXPECT_EQ(6, info.selectionStart);
744     EXPECT_EQ(11, info.selectionEnd);
745     EXPECT_EQ(6, info.compositionStart);
746     EXPECT_EQ(11, info.compositionEnd);
747
748     frame->setEditableSelectionOffsets(2, 2);
749     info = webView->textInputInfo();
750     EXPECT_EQ("hello world", std::string(info.value.utf8().data()));
751     EXPECT_EQ(2, info.selectionStart);
752     EXPECT_EQ(2, info.selectionEnd);
753     EXPECT_EQ(-1, info.compositionStart);
754     EXPECT_EQ(-1, info.compositionEnd);
755 }
756
757 TEST_F(WebViewTest, IsSelectionAnchorFirst)
758 {
759     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
760     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
761     WebFrame* frame = webView->mainFrame();
762
763     webView->setInitialFocus(false);
764     frame->setEditableSelectionOffsets(4, 10);
765     EXPECT_TRUE(webView->isSelectionAnchorFirst());
766     WebRect anchor;
767     WebRect focus;
768     webView->selectionBounds(anchor, focus);
769     frame->selectRange(WebPoint(focus.x, focus.y), WebPoint(anchor.x, anchor.y));
770     EXPECT_FALSE(webView->isSelectionAnchorFirst());
771 }
772
773 TEST_F(WebViewTest, HistoryResetScrollAndScaleState)
774 {
775     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
776     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html");
777     webViewImpl->resize(WebSize(640, 480));
778     webViewImpl->layout();
779     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
780     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
781
782     // Make the page scale and scroll with the given paremeters.
783     webViewImpl->setPageScaleFactor(2.0f, WebPoint(116, 84));
784     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
785     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
786     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
787     webViewImpl->page()->mainFrame()->loader().saveScrollState();
788     EXPECT_EQ(2.0f, webViewImpl->page()->mainFrame()->loader().currentItem()->pageScaleFactor());
789     EXPECT_EQ(116, webViewImpl->page()->mainFrame()->loader().currentItem()->scrollPoint().x());
790     EXPECT_EQ(84, webViewImpl->page()->mainFrame()->loader().currentItem()->scrollPoint().y());
791
792     // Confirm that resetting the page state resets the saved scroll position.
793     // The HistoryController treats a page scale factor of 0.0f as special and avoids
794     // restoring it to the WebView.
795     webViewImpl->resetScrollAndScaleState();
796     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
797     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
798     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
799     EXPECT_EQ(0.0f, webViewImpl->page()->mainFrame()->loader().currentItem()->pageScaleFactor());
800     EXPECT_EQ(0, webViewImpl->page()->mainFrame()->loader().currentItem()->scrollPoint().x());
801     EXPECT_EQ(0, webViewImpl->page()->mainFrame()->loader().currentItem()->scrollPoint().y());
802 }
803
804 class EnterFullscreenWebViewClient : public WebViewClient {
805 public:
806     // WebViewClient methods
807     virtual bool enterFullScreen() { return true; }
808     virtual void exitFullScreen() { }
809 };
810
811
812 TEST_F(WebViewTest, EnterFullscreenResetScrollAndScaleState)
813 {
814     EnterFullscreenWebViewClient client;
815     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
816     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, 0, &client);
817     webViewImpl->settings()->setFullScreenEnabled(true);
818     webViewImpl->resize(WebSize(640, 480));
819     webViewImpl->layout();
820     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
821     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
822
823     // Make the page scale and scroll with the given paremeters.
824     webViewImpl->setPageScaleFactor(2.0f, WebPoint(116, 84));
825     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
826     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
827     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
828
829     RefPtr<WebCore::Element> element = static_cast<PassRefPtr<WebCore::Element> >(webViewImpl->mainFrame()->document().body());
830     webViewImpl->enterFullScreenForElement(element.get());
831     webViewImpl->willEnterFullScreen();
832     webViewImpl->didEnterFullScreen();
833
834     // Page scale factor must be 1.0 during fullscreen for elements to be sized
835     // properly.
836     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
837
838     // Make sure fullscreen nesting doesn't disrupt scroll/scale saving.
839     RefPtr<WebCore::Element> otherElement = static_cast<PassRefPtr<WebCore::Element> >(webViewImpl->mainFrame()->document().head());
840     webViewImpl->enterFullScreenForElement(otherElement.get());
841
842     // Confirm that exiting fullscreen restores the parameters.
843     webViewImpl->willExitFullScreen();
844     webViewImpl->didExitFullScreen();
845     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
846     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
847     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
848
849     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
850 }
851
852 static void DragAndDropURL(WebViewImpl* webView, const std::string& url)
853 {
854     blink::WebDragData dragData;
855     dragData.initialize();
856
857     WebDragData::Item item;
858     item.storageType = WebDragData::Item::StorageTypeString;
859     item.stringType = "text/uri-list";
860     item.stringData = WebString::fromUTF8(url);
861     dragData.addItem(item);
862
863     const WebPoint clientPoint(0, 0);
864     const WebPoint screenPoint(0, 0);
865     webView->dragTargetDragEnter(dragData, clientPoint, screenPoint, blink::WebDragOperationCopy, 0);
866     webView->dragTargetDrop(clientPoint, screenPoint, 0);
867     FrameTestHelpers::runPendingTasks();
868     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
869 }
870
871 TEST_F(WebViewTest, DragDropURL)
872 {
873     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "foo.html");
874     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "bar.html");
875
876     const std::string fooUrl = m_baseURL + "foo.html";
877     const std::string barUrl = m_baseURL + "bar.html";
878
879     WebViewImpl* webView = m_webViewHelper.initializeAndLoad(fooUrl);
880
881     ASSERT_TRUE(webView);
882
883     // Drag and drop barUrl and verify that we've navigated to it.
884     DragAndDropURL(webView, barUrl);
885     EXPECT_EQ(barUrl, webView->mainFrame()->document().url().string().utf8());
886
887     // Drag and drop fooUrl and verify that we've navigated back to it.
888     DragAndDropURL(webView, fooUrl);
889     EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
890
891     // Disable navigation on drag-and-drop.
892     webView->settingsImpl()->setNavigateOnDragDrop(false);
893
894     // Attempt to drag and drop to barUrl and verify that no navigation has occurred.
895     DragAndDropURL(webView, barUrl);
896     EXPECT_EQ(fooUrl, webView->mainFrame()->document().url().string().utf8());
897 }
898
899 class ContentDetectorClient : public WebViewClient {
900 public:
901     ContentDetectorClient() { reset(); }
902
903     virtual WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) OVERRIDE
904     {
905         m_contentDetectionRequested = true;
906         return m_contentDetectionResult;
907     }
908
909     virtual void scheduleContentIntent(const WebURL& url) OVERRIDE
910     {
911         m_scheduledIntentURL = url;
912     }
913
914     virtual void cancelScheduledContentIntents() OVERRIDE
915     {
916         m_pendingIntentsCancelled = true;
917     }
918
919     void reset()
920     {
921         m_contentDetectionRequested = false;
922         m_pendingIntentsCancelled = false;
923         m_scheduledIntentURL = WebURL();
924         m_contentDetectionResult = WebContentDetectionResult();
925     }
926
927     bool contentDetectionRequested() const { return m_contentDetectionRequested; }
928     bool pendingIntentsCancelled() const { return m_pendingIntentsCancelled; }
929     const WebURL& scheduledIntentURL() const { return m_scheduledIntentURL; }
930     void setContentDetectionResult(const WebContentDetectionResult& result) { m_contentDetectionResult = result; }
931
932 private:
933     bool m_contentDetectionRequested;
934     bool m_pendingIntentsCancelled;
935     WebURL m_scheduledIntentURL;
936     WebContentDetectionResult m_contentDetectionResult;
937 };
938
939 static bool tapElementById(WebView* webView, WebInputEvent::Type type, const WebString& id)
940 {
941     ASSERT(webView);
942     RefPtr<WebCore::Element> element = static_cast<PassRefPtr<WebCore::Element> >(webView->mainFrame()->document().getElementById(id));
943     if (!element)
944         return false;
945
946     element->scrollIntoViewIfNeeded();
947     WebCore::IntPoint center = element->screenRect().center();
948
949     WebGestureEvent event;
950     event.type = type;
951     event.x = center.x();
952     event.y = center.y();
953
954     webView->handleInputEvent(event);
955     runPendingTasks();
956     return true;
957 }
958
959 TEST_F(WebViewTest, DetectContentAroundPosition)
960 {
961     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_listeners.html"));
962
963     ContentDetectorClient client;
964     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "content_listeners.html", true, 0, &client);
965     webView->resize(WebSize(500, 300));
966     webView->layout();
967     runPendingTasks();
968
969     WebString clickListener = WebString::fromUTF8("clickListener");
970     WebString touchstartListener = WebString::fromUTF8("touchstartListener");
971     WebString mousedownListener = WebString::fromUTF8("mousedownListener");
972     WebString noListener = WebString::fromUTF8("noListener");
973     WebString link = WebString::fromUTF8("link");
974
975     // Ensure content detection is not requested for nodes listening to click,
976     // mouse or touch events when we do simple taps.
977     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, clickListener));
978     EXPECT_FALSE(client.contentDetectionRequested());
979     client.reset();
980
981     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, touchstartListener));
982     EXPECT_FALSE(client.contentDetectionRequested());
983     client.reset();
984
985     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, mousedownListener));
986     EXPECT_FALSE(client.contentDetectionRequested());
987     client.reset();
988
989     // Content detection should work normally without these event listeners.
990     // The click listener in the body should be ignored as a special case.
991     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
992     EXPECT_TRUE(client.contentDetectionRequested());
993     EXPECT_FALSE(client.scheduledIntentURL().isValid());
994
995     WebURL intentURL = toKURL(m_baseURL);
996     client.setContentDetectionResult(WebContentDetectionResult(WebRange(), WebString(), intentURL));
997     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
998     EXPECT_TRUE(client.scheduledIntentURL() == intentURL);
999
1000     // Tapping elsewhere should cancel the scheduled intent.
1001     WebGestureEvent event;
1002     event.type = WebInputEvent::GestureTap;
1003     webView->handleInputEvent(event);
1004     runPendingTasks();
1005     EXPECT_TRUE(client.pendingIntentsCancelled());
1006
1007     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1008 }
1009
1010 TEST_F(WebViewTest, ClientTapHandling)
1011 {
1012     TapHandlingWebViewClient client;
1013     client.reset();
1014     WebView* webView = m_webViewHelper.initializeAndLoad("about:blank", true, 0, &client);
1015     WebGestureEvent event;
1016     event.type = WebInputEvent::GestureTap;
1017     event.x = 3;
1018     event.y = 8;
1019     webView->handleInputEvent(event);
1020     runPendingTasks();
1021     EXPECT_EQ(3, client.tapX());
1022     EXPECT_EQ(8, client.tapY());
1023     client.reset();
1024     event.type = WebInputEvent::GestureLongPress;
1025     event.x = 25;
1026     event.y = 7;
1027     webView->handleInputEvent(event);
1028     runPendingTasks();
1029     EXPECT_EQ(25, client.longpressX());
1030     EXPECT_EQ(7, client.longpressY());
1031
1032     m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
1033 }
1034
1035 #if OS(ANDROID)
1036 TEST_F(WebViewTest, LongPressSelection)
1037 {
1038     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
1039
1040     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "longpress_selection.html", true);
1041     webView->resize(WebSize(500, 300));
1042     webView->layout();
1043     runPendingTasks();
1044
1045     WebString target = WebString::fromUTF8("target");
1046     WebString onselectstartfalse = WebString::fromUTF8("onselectstartfalse");
1047     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1048
1049     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, onselectstartfalse));
1050     EXPECT_EQ("", std::string(frame->selectionAsText().utf8().data()));
1051     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
1052     EXPECT_EQ("testword", std::string(frame->selectionAsText().utf8().data()));
1053 }
1054 #endif
1055
1056 TEST_F(WebViewTest, SelectionOnDisabledInput)
1057 {
1058     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_disabled.html"));
1059     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "selection_disabled.html", true);
1060     webView->resize(WebSize(640, 480));
1061     webView->layout();
1062     runPendingTasks();
1063
1064     std::string testWord = "This text should be selected.";
1065
1066     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1067     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
1068
1069     size_t location;
1070     size_t length;
1071     EXPECT_TRUE(toWebViewImpl(webView)->caretOrSelectionRange(&location, &length));
1072     EXPECT_EQ(location, 0UL);
1073     EXPECT_EQ(length, testWord.length());
1074 }
1075
1076 TEST_F(WebViewTest, SelectionOnReadOnlyInput)
1077 {
1078     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_readonly.html"));
1079     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "selection_readonly.html", true);
1080     webView->resize(WebSize(640, 480));
1081     webView->layout();
1082     runPendingTasks();
1083
1084     std::string testWord = "This text should be selected.";
1085
1086     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1087     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
1088
1089     size_t location;
1090     size_t length;
1091     EXPECT_TRUE(toWebViewImpl(webView)->caretOrSelectionRange(&location, &length));
1092     EXPECT_EQ(location, 0UL);
1093     EXPECT_EQ(length, testWord.length());
1094 }
1095
1096 static void configueCompositingWebView(WebSettings* settings)
1097 {
1098     settings->setForceCompositingMode(true);
1099     settings->setAcceleratedCompositingEnabled(true);
1100     settings->setAcceleratedCompositingForFixedPositionEnabled(true);
1101     settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
1102     settings->setAcceleratedCompositingForScrollableFramesEnabled(true);
1103     settings->setCompositedScrollingForFramesEnabled(true);
1104 }
1105
1106 TEST_F(WebViewTest, ShowPressOnTransformedLink)
1107 {
1108     OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient());
1109     FrameTestHelpers::WebViewHelper webViewHelper;
1110     WebViewImpl* webViewImpl = webViewHelper.initialize(true, 0, fakeCompositingWebViewClient.get(), &configueCompositingWebView);
1111
1112     int pageWidth = 640;
1113     int pageHeight = 480;
1114     webViewImpl->resize(WebSize(pageWidth, pageHeight));
1115
1116     WebURL baseURL = URLTestHelpers::toKURL("http://example.com/");
1117     webViewImpl->mainFrame()->loadHTMLString(
1118         "<a href='http://www.test.com' style='position: absolute; left: 20px; top: 20px; width: 200px; -webkit-transform:translateZ(0);'>A link to highlight</a>", baseURL);
1119     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
1120
1121     WebGestureEvent event;
1122     event.type = WebInputEvent::GestureShowPress;
1123     event.x = 20;
1124     event.y = 20;
1125
1126     // Just make sure we don't hit any asserts.
1127     webViewImpl->handleInputEvent(event);
1128 }
1129
1130 class MockAutofillClient : public WebAutofillClient {
1131 public:
1132     MockAutofillClient()
1133         : m_ignoreTextChanges(false)
1134         , m_textChangesWhileIgnored(0)
1135         , m_textChangesWhileNotIgnored(0) { }
1136
1137     virtual ~MockAutofillClient() { }
1138
1139     virtual void setIgnoreTextChanges(bool ignore) OVERRIDE { m_ignoreTextChanges = ignore; }
1140     virtual void textFieldDidChange(const WebFormControlElement&) OVERRIDE
1141     {
1142         if (m_ignoreTextChanges)
1143             ++m_textChangesWhileIgnored;
1144         else
1145             ++m_textChangesWhileNotIgnored;
1146     }
1147
1148     void clearChangeCounts()
1149     {
1150         m_textChangesWhileIgnored = 0;
1151         m_textChangesWhileNotIgnored = 0;
1152     }
1153
1154     int textChangesWhileIgnored() { return m_textChangesWhileIgnored; }
1155     int textChangesWhileNotIgnored() { return m_textChangesWhileNotIgnored; }
1156
1157 private:
1158     bool m_ignoreTextChanges;
1159     int m_textChangesWhileIgnored;
1160     int m_textChangesWhileNotIgnored;
1161 };
1162
1163
1164 TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange)
1165 {
1166     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1167     MockAutofillClient client;
1168     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1169     webView->setAutofillClient(&client);
1170     webView->setInitialFocus(false);
1171
1172     // Set up a composition that needs to be committed.
1173     WebVector<WebCompositionUnderline> emptyUnderlines;
1174     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1175     frame->setEditableSelectionOffsets(4, 10);
1176     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1177     WebTextInputInfo info = webView->textInputInfo();
1178     EXPECT_EQ(4, info.selectionStart);
1179     EXPECT_EQ(10, info.selectionEnd);
1180     EXPECT_EQ(8, info.compositionStart);
1181     EXPECT_EQ(12, info.compositionEnd);
1182
1183     // Clear the focus and track that the subsequent composition commit does not trigger a
1184     // text changed notification for autofill.
1185     client.clearChangeCounts();
1186     webView->setFocus(false);
1187     EXPECT_EQ(1, client.textChangesWhileIgnored());
1188     EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1189
1190     webView->setAutofillClient(0);
1191 }
1192
1193 TEST_F(WebViewTest, ConfirmCompositionTriggersAutofillTextChange)
1194 {
1195     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1196     MockAutofillClient client;
1197     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html");
1198     webView->setAutofillClient(&client);
1199     webView->setInitialFocus(false);
1200
1201     // Set up a composition that needs to be committed.
1202     std::string compositionText("testingtext");
1203
1204     WebVector<WebCompositionUnderline> emptyUnderlines;
1205     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 0, compositionText.length());
1206
1207     WebTextInputInfo info = webView->textInputInfo();
1208     EXPECT_EQ(0, info.selectionStart);
1209     EXPECT_EQ((int) compositionText.length(), info.selectionEnd);
1210     EXPECT_EQ(0, info.compositionStart);
1211     EXPECT_EQ((int) compositionText.length(), info.compositionEnd);
1212
1213     client.clearChangeCounts();
1214     webView->confirmComposition();
1215     EXPECT_EQ(0, client.textChangesWhileIgnored());
1216     EXPECT_EQ(1, client.textChangesWhileNotIgnored());
1217
1218     webView->setAutofillClient(0);
1219 }
1220
1221 TEST_F(WebViewTest, SetCompositionFromExistingTextTriggersAutofillTextChange)
1222 {
1223     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
1224     MockAutofillClient client;
1225     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "input_field_populated.html", true);
1226     webView->setAutofillClient(&client);
1227     webView->setInitialFocus(false);
1228
1229     WebVector<WebCompositionUnderline> emptyUnderlines;
1230
1231     client.clearChangeCounts();
1232     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1233     frame->setCompositionFromExistingText(8, 12, emptyUnderlines);
1234
1235     WebTextInputInfo info = webView->textInputInfo();
1236     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
1237     EXPECT_EQ(8, info.compositionStart);
1238     EXPECT_EQ(12, info.compositionEnd);
1239
1240     EXPECT_EQ(0, client.textChangesWhileIgnored());
1241     EXPECT_EQ(0, client.textChangesWhileNotIgnored());
1242
1243     WebDocument document = webView->mainFrame()->document();
1244     EXPECT_EQ(WebString::fromUTF8("none"),  document.getElementById("inputEvent").firstChild().nodeValue());
1245
1246     webView->setAutofillClient(0);
1247 }
1248
1249 TEST_F(WebViewTest, ShadowRoot)
1250 {
1251     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("shadow_dom_test.html"));
1252     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(m_baseURL + "shadow_dom_test.html", true);
1253
1254     WebDocument document = webViewImpl->mainFrame()->document();
1255     {
1256         WebElement elementWithShadowRoot = document.getElementById("shadowroot");
1257         EXPECT_FALSE(elementWithShadowRoot.isNull());
1258         WebNode shadowRoot = elementWithShadowRoot.shadowRoot();
1259         EXPECT_FALSE(shadowRoot.isNull());
1260     }
1261     {
1262         WebElement elementWithoutShadowRoot = document.getElementById("noshadowroot");
1263         EXPECT_FALSE(elementWithoutShadowRoot.isNull());
1264         WebNode shadowRoot = elementWithoutShadowRoot.shadowRoot();
1265         EXPECT_TRUE(shadowRoot.isNull());
1266     }
1267 }
1268
1269 class ViewCreatingWebViewClient : public WebViewClient {
1270 public:
1271     ViewCreatingWebViewClient()
1272         : m_didFocusCalled(false)
1273     {
1274     }
1275
1276     // WebViewClient methods
1277     virtual WebView* createView(WebFrame*, const WebURLRequest&, const WebWindowFeatures&, const WebString& name, WebNavigationPolicy, bool) OVERRIDE
1278     {
1279         return m_webViewHelper.initialize(true, 0, 0);
1280     }
1281
1282     // WebWidgetClient methods
1283     virtual void didFocus() OVERRIDE
1284     {
1285         m_didFocusCalled = true;
1286     }
1287
1288     bool didFocusCalled() const { return m_didFocusCalled; }
1289     WebView* createdWebView() const { return m_webViewHelper.webView(); }
1290
1291 private:
1292     FrameTestHelpers::WebViewHelper m_webViewHelper;
1293     bool m_didFocusCalled;
1294 };
1295
1296 TEST_F(WebViewTest, FocusExistingFrameOnNavigate)
1297 {
1298     ViewCreatingWebViewClient client;
1299     FrameTestHelpers::WebViewHelper m_webViewHelper;
1300     WebViewImpl* webViewImpl = m_webViewHelper.initialize(true, 0, &client);
1301     webViewImpl->page()->settings().setJavaScriptCanOpenWindowsAutomatically(true);
1302     WebFrameImpl* frame = toWebFrameImpl(webViewImpl->mainFrame());
1303     frame->setName("_start");
1304
1305     // Make a request that will open a new window
1306     WebURLRequest webURLRequest;
1307     webURLRequest.initialize();
1308     WebCore::FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
1309     webViewImpl->page()->mainFrame()->loader().load(request);
1310     ASSERT_TRUE(client.createdWebView());
1311     EXPECT_FALSE(client.didFocusCalled());
1312
1313     // Make a request from the new window that will navigate the original window. The original window should be focused.
1314     WebURLRequest webURLRequestWithTargetStart;
1315     webURLRequestWithTargetStart.initialize();
1316     WebCore::FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
1317     toWebViewImpl(client.createdWebView())->page()->mainFrame()->loader().load(requestWithTargetStart);
1318     EXPECT_TRUE(client.didFocusCalled());
1319
1320     m_webViewHelper.reset(); // Remove dependency on locally scoped client.
1321 }
1322
1323 TEST_F(WebViewTest, DispatchesFocusOutFocusInOnViewToggleFocus)
1324 {
1325     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focusout_focusin_events.html");
1326     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focusout_focusin_events.html", true, 0);
1327
1328     webView->setFocus(true);
1329     webView->setFocus(false);
1330     webView->setFocus(true);
1331
1332     WebElement element = webView->mainFrame()->document().getElementById("message");
1333     EXPECT_STREQ("focusoutfocusin", element.innerText().utf8().data());
1334 }
1335
1336 TEST_F(WebViewTest, DispatchesDomFocusOutDomFocusInOnViewToggleFocus)
1337 {
1338     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "domfocusout_domfocusin_events.html");
1339     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "domfocusout_domfocusin_events.html", true, 0);
1340
1341     webView->setFocus(true);
1342     webView->setFocus(false);
1343     webView->setFocus(true);
1344
1345     WebElement element = webView->mainFrame()->document().getElementById("message");
1346     EXPECT_STREQ("DOMFocusOutDOMFocusIn", element.innerText().utf8().data());
1347 }
1348
1349 #if !ENABLE(INPUT_MULTIPLE_FIELDS_UI)
1350 static void openDateTimeChooser(WebView* webView, WebCore::HTMLInputElement* inputElement)
1351 {
1352     inputElement->focus();
1353
1354     WebKeyboardEvent keyEvent;
1355     keyEvent.windowsKeyCode = WebCore::VKEY_SPACE;
1356     keyEvent.type = WebInputEvent::RawKeyDown;
1357     keyEvent.setKeyIdentifierFromWindowsKeyCode();
1358     webView->handleInputEvent(keyEvent);
1359
1360     keyEvent.type = WebInputEvent::KeyUp;
1361     webView->handleInputEvent(keyEvent);
1362 }
1363
1364 TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
1365 {
1366     DateTimeChooserWebViewClient client;
1367     std::string url = m_baseURL + "date_time_chooser.html";
1368     URLTestHelpers::registerMockedURLLoad(toKURL(url), "date_time_chooser.html");
1369     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
1370
1371     WebCore::Document* document = webViewImpl->mainFrameImpl()->frame()->document();
1372
1373     WebCore::HTMLInputElement* inputElement;
1374
1375     inputElement = toHTMLInputElement(document->getElementById("date"));
1376     openDateTimeChooser(webViewImpl, inputElement);
1377     client.chooserCompletion()->didChooseValue(0);
1378     client.clearChooserCompletion();
1379     EXPECT_STREQ("1970-01-01", inputElement->value().utf8().data());
1380
1381     openDateTimeChooser(webViewImpl, inputElement);
1382     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1383     client.clearChooserCompletion();
1384     EXPECT_STREQ("", inputElement->value().utf8().data());
1385
1386     inputElement = toHTMLInputElement(document->getElementById("datetimelocal"));
1387     openDateTimeChooser(webViewImpl, inputElement);
1388     client.chooserCompletion()->didChooseValue(0);
1389     client.clearChooserCompletion();
1390     EXPECT_STREQ("1970-01-01T00:00", inputElement->value().utf8().data());
1391
1392     openDateTimeChooser(webViewImpl, inputElement);
1393     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1394     client.clearChooserCompletion();
1395     EXPECT_STREQ("", inputElement->value().utf8().data());
1396
1397     inputElement = toHTMLInputElement(document->getElementById("month"));
1398     openDateTimeChooser(webViewImpl, inputElement);
1399     client.chooserCompletion()->didChooseValue(0);
1400     client.clearChooserCompletion();
1401     EXPECT_STREQ("1970-01", inputElement->value().utf8().data());
1402
1403     openDateTimeChooser(webViewImpl, inputElement);
1404     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1405     client.clearChooserCompletion();
1406     EXPECT_STREQ("", inputElement->value().utf8().data());
1407
1408     inputElement = toHTMLInputElement(document->getElementById("time"));
1409     openDateTimeChooser(webViewImpl, inputElement);
1410     client.chooserCompletion()->didChooseValue(0);
1411     client.clearChooserCompletion();
1412     EXPECT_STREQ("00:00", inputElement->value().utf8().data());
1413
1414     openDateTimeChooser(webViewImpl, inputElement);
1415     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1416     client.clearChooserCompletion();
1417     EXPECT_STREQ("", inputElement->value().utf8().data());
1418
1419     inputElement = toHTMLInputElement(document->getElementById("week"));
1420     openDateTimeChooser(webViewImpl, inputElement);
1421     client.chooserCompletion()->didChooseValue(0);
1422     client.clearChooserCompletion();
1423     EXPECT_STREQ("1970-W01", inputElement->value().utf8().data());
1424
1425     openDateTimeChooser(webViewImpl, inputElement);
1426     client.chooserCompletion()->didChooseValue(std::numeric_limits<double>::quiet_NaN());
1427     client.clearChooserCompletion();
1428     EXPECT_STREQ("", inputElement->value().utf8().data());
1429 }
1430 #endif
1431
1432 TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle)
1433 {
1434     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "focus_blur_events.html");
1435     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "focus_blur_events.html", true, 0);
1436
1437     webView->setFocus(true);
1438     webView->setFocus(false);
1439     webView->setFocus(true);
1440
1441     WebElement element = webView->mainFrame()->document().getElementById("message");
1442     // Expect not to see duplication of events.
1443     EXPECT_STREQ("blurfocus", element.innerText().utf8().data());
1444 }
1445
1446 TEST_F(WebViewTest, SmartClipData)
1447 {
1448     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf"));
1449     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html"));
1450     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html");
1451     webView->resize(WebSize(500, 500));
1452     webView->layout();
1453     WebRect cropRect(300, 125, 100, 50);
1454
1455     // FIXME: We should test the structure of the data we get back.
1456     EXPECT_FALSE(webView->getSmartClipData(cropRect).isEmpty());
1457 }
1458
1459 class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient {
1460 public:
1461     CreateChildCounterFrameClient() : m_count(0) { }
1462     virtual WebFrame* createChildFrame(WebFrame* parent, const WebString& frameName) OVERRIDE;
1463
1464     int count() const { return m_count; }
1465
1466 private:
1467     int m_count;
1468 };
1469
1470 WebFrame* CreateChildCounterFrameClient::createChildFrame(WebFrame* parent, const WebString& frameName)
1471 {
1472     ++m_count;
1473     return TestWebFrameClient::createChildFrame(parent, frameName);
1474 }
1475
1476 TEST_F(WebViewTest, AddFrameInCloseUnload)
1477 {
1478     CreateChildCounterFrameClient frameClient;
1479     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1480     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1481     m_webViewHelper.reset();
1482     EXPECT_EQ(0, frameClient.count());
1483 }
1484
1485 TEST_F(WebViewTest, AddFrameInCloseURLUnload)
1486 {
1487     CreateChildCounterFrameClient frameClient;
1488     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1489     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1490     m_webViewHelper.webViewImpl()->dispatchUnloadEvent();
1491     EXPECT_EQ(0, frameClient.count());
1492     m_webViewHelper.reset();
1493 }
1494
1495 TEST_F(WebViewTest, AddFrameInNavigateUnload)
1496 {
1497     CreateChildCounterFrameClient frameClient;
1498     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1499     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload.html", true, &frameClient);
1500     FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
1501     EXPECT_EQ(0, frameClient.count());
1502     m_webViewHelper.reset();
1503 }
1504
1505 TEST_F(WebViewTest, AddFrameInChildInNavigateUnload)
1506 {
1507     CreateChildCounterFrameClient frameClient;
1508     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload_wrapper.html"));
1509     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("add_frame_in_unload.html"));
1510     m_webViewHelper.initializeAndLoad(m_baseURL + "add_frame_in_unload_wrapper.html", true, &frameClient);
1511     FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(), "about:blank");
1512     EXPECT_EQ(1, frameClient.count());
1513     m_webViewHelper.reset();
1514 }
1515
1516 class TouchEventHandlerWebViewClient : public WebViewClient {
1517 public:
1518     // WebWidgetClient methods
1519     virtual void hasTouchEventHandlers(bool state) OVERRIDE
1520     {
1521         m_hasTouchEventHandlerCount[state]++;
1522     }
1523
1524     // Local methods
1525     TouchEventHandlerWebViewClient() : m_hasTouchEventHandlerCount()
1526     {
1527     }
1528
1529     int getAndResetHasTouchEventHandlerCallCount(bool state)
1530     {
1531         int value = m_hasTouchEventHandlerCount[state];
1532         m_hasTouchEventHandlerCount[state] = 0;
1533         return value;
1534     }
1535
1536 private:
1537     int m_hasTouchEventHandlerCount[2];
1538 };
1539
1540 // This test verifies that WebWidgetClient::hasTouchEventHandlers is called accordingly for various
1541 // calls to Document::did{Add|Remove|Clear}TouchEventHandler. Verifying that those calls are made
1542 // correctly is the job of LayoutTests/fast/events/touch/touch-handler-count.html.
1543 TEST_F(WebViewTest, HasTouchEventHandlers)
1544 {
1545     TouchEventHandlerWebViewClient client;
1546     std::string url = m_baseURL + "has_touch_event_handlers.html";
1547     URLTestHelpers::registerMockedURLLoad(toKURL(url), "has_touch_event_handlers.html");
1548     WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client);
1549
1550     // The page is initialized with at least one no-handlers call.
1551     // In practice we get two such calls because WebViewHelper::initializeAndLoad first
1552     // initializes and empty frame, and then loads a document into it, so there are two
1553     // FrameLoader::commitProvisionalLoad calls.
1554     EXPECT_GE(client.getAndResetHasTouchEventHandlerCallCount(false), 1);
1555     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1556
1557     // Adding the first document handler results in a has-handlers call.
1558     WebCore::Document* document = webViewImpl->mainFrameImpl()->frame()->document();
1559     document->didAddTouchEventHandler(document);
1560     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1561     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1562
1563     // Adding another handler has no effect.
1564     document->didAddTouchEventHandler(document);
1565     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1566     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1567
1568     // Removing the duplicate handler has no effect.
1569     document->didRemoveTouchEventHandler(document);
1570     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1571     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1572
1573     // Removing the final handler results in a no-handlers call.
1574     document->didRemoveTouchEventHandler(document);
1575     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1576     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1577
1578     // Adding a handler on a div results in a has-handlers call.
1579     WebCore::Element* parentDiv = document->getElementById("parentdiv");
1580     ASSERT(parentDiv);
1581     document->didAddTouchEventHandler(parentDiv);
1582     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1583     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1584
1585     // Adding a duplicate handler on the div, clearing all document handlers
1586     // (of which there are none) and removing the extra handler on the div
1587     // all have no effect.
1588     document->didAddTouchEventHandler(parentDiv);
1589     document->didClearTouchEventHandlers(document);
1590     document->didRemoveTouchEventHandler(parentDiv);
1591     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1592     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1593
1594     // Removing the final handler on the div results in a no-handlers call.
1595     document->didRemoveTouchEventHandler(parentDiv);
1596     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1597     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1598
1599     // Adding two handlers then clearing them in a single call results in a
1600     // has-handlers then no-handlers call.
1601     document->didAddTouchEventHandler(parentDiv);
1602     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1603     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1604     document->didAddTouchEventHandler(parentDiv);
1605     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1606     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1607     document->didClearTouchEventHandlers(parentDiv);
1608     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1609     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1610
1611     // Adding a handler inside of a child iframe results in a has-handlers call.
1612     WebCore::Element* childFrame = document->getElementById("childframe");
1613     ASSERT(childFrame);
1614     WebCore::Document* childDocument = toHTMLIFrameElement(childFrame)->contentDocument();
1615     WebCore::Element* childDiv = childDocument->getElementById("childdiv");
1616     ASSERT(childDiv);
1617     childDocument->didAddTouchEventHandler(childDiv);
1618     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1619     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1620
1621     // Adding and clearing handlers in the parent doc or elsewhere in the child doc
1622     // has no impact.
1623     document->didAddTouchEventHandler(document);
1624     document->didAddTouchEventHandler(childFrame);
1625     childDocument->didAddTouchEventHandler(childDocument);
1626     document->didClearTouchEventHandlers(document);
1627     document->didClearTouchEventHandlers(childFrame);
1628     childDocument->didClearTouchEventHandlers(childDocument);
1629     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1630     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1631
1632     // Removing the final handler inside the child frame results in a no-handlers call.
1633     childDocument->didRemoveTouchEventHandler(childDiv);
1634     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1635     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1636
1637     // Adding a handler inside the child frame results in a has-handlers call.
1638     childDocument->didAddTouchEventHandler(childDocument);
1639     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1640     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(true));
1641
1642     // Adding a handler in the parent document and removing the one in the frame
1643     // has no effect.
1644     document->didAddTouchEventHandler(childFrame);
1645     childDocument->didRemoveTouchEventHandler(childDocument);
1646     childDocument->didClearTouchEventHandlers(childDocument);
1647     document->didClearTouchEventHandlers(document);
1648     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(false));
1649     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1650
1651     // Now removing the handler in the parent document results in a no-handlers call.
1652     document->didRemoveTouchEventHandler(childFrame);
1653     EXPECT_EQ(1, client.getAndResetHasTouchEventHandlerCallCount(false));
1654     EXPECT_EQ(0, client.getAndResetHasTouchEventHandlerCallCount(true));
1655 }
1656
1657 static WebRect ExpectedRootBounds(WebCore::Document* document, float scaleFactor)
1658 {
1659     WebCore::Element* element = document->getElementById("root");
1660     if (!element)
1661         element = document->getElementById("target");
1662     if (element->hasTagName(WebCore::HTMLNames::iframeTag))
1663         return ExpectedRootBounds(toHTMLIFrameElement(element)->contentDocument(), scaleFactor);
1664
1665     WebCore::IntRect boundingBox = element->pixelSnappedBoundingBox();
1666     boundingBox = document->frame()->view()->contentsToWindow(boundingBox);
1667     boundingBox.scale(scaleFactor);
1668     return boundingBox;
1669 }
1670
1671 void WebViewTest::testSelectionRootBounds(const char* htmlFile, float pageScaleFactor)
1672 {
1673     std::string url = m_baseURL + htmlFile;
1674
1675     WebView* webView = m_webViewHelper.initializeAndLoad(url, true);
1676     webView->resize(WebSize(640, 480));
1677     webView->setPageScaleFactor(pageScaleFactor, WebPoint(0, 0));
1678     webView->layout();
1679     runPendingTasks();
1680
1681     WebFrameImpl* frame = toWebFrameImpl(webView->mainFrame());
1682     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
1683     WebCore::HTMLDocument* document = WebCore::toHTMLDocument(frame->frame()->document());
1684
1685     WebRect expectedRootBounds = ExpectedRootBounds(document, webView->pageScaleFactor());
1686     WebRect actualRootBounds;
1687     webView->getSelectionRootBounds(actualRootBounds);
1688     ASSERT_EQ(expectedRootBounds, actualRootBounds);
1689
1690     WebRect anchor, focus;
1691     webView->selectionBounds(anchor, focus);
1692     WebCore::IntRect expectedIntRect = expectedRootBounds;
1693     ASSERT_TRUE(expectedIntRect.contains(anchor));
1694     // The "overflow" tests have the focus boundary outside of the element box.
1695     ASSERT_EQ(url.find("overflow") == std::string::npos, expectedIntRect.contains(focus));
1696 }
1697
1698 TEST_F(WebViewTest, GetSelectionRootBounds)
1699 {
1700     // Register all the pages we will be using.
1701     registerMockedHttpURLLoad("select_range_basic.html");
1702     registerMockedHttpURLLoad("select_range_div_editable.html");
1703     registerMockedHttpURLLoad("select_range_scroll.html");
1704     registerMockedHttpURLLoad("select_range_span_editable.html");
1705     registerMockedHttpURLLoad("select_range_input.html");
1706     registerMockedHttpURLLoad("select_range_input_overflow.html");
1707     registerMockedHttpURLLoad("select_range_textarea.html");
1708     registerMockedHttpURLLoad("select_range_textarea_overflow.html");
1709     registerMockedHttpURLLoad("select_range_iframe.html");
1710     registerMockedHttpURLLoad("select_range_iframe_div_editable.html");
1711     registerMockedHttpURLLoad("select_range_iframe_scroll.html");
1712     registerMockedHttpURLLoad("select_range_iframe_span_editable.html");
1713     registerMockedHttpURLLoad("select_range_iframe_input.html");
1714     registerMockedHttpURLLoad("select_range_iframe_input_overflow.html");
1715     registerMockedHttpURLLoad("select_range_iframe_textarea.html");
1716     registerMockedHttpURLLoad("select_range_iframe_textarea_overflow.html");
1717
1718     // Test with simple pages.
1719     testSelectionRootBounds("select_range_basic.html", 1.0f);
1720     testSelectionRootBounds("select_range_div_editable.html", 1.0f);
1721     testSelectionRootBounds("select_range_scroll.html", 1.0f);
1722     testSelectionRootBounds("select_range_span_editable.html", 1.0f);
1723     testSelectionRootBounds("select_range_input.html", 1.0f);
1724     testSelectionRootBounds("select_range_input_overflow.html", 1.0f);
1725     testSelectionRootBounds("select_range_textarea.html", 1.0f);
1726     testSelectionRootBounds("select_range_textarea_overflow.html", 1.0f);
1727
1728     // Test with the same pages as above in iframes.
1729     testSelectionRootBounds("select_range_iframe.html", 1.0f);
1730     testSelectionRootBounds("select_range_iframe_div_editable.html", 1.0f);
1731     testSelectionRootBounds("select_range_iframe_scroll.html", 1.0f);
1732     testSelectionRootBounds("select_range_iframe_span_editable.html", 1.0f);
1733     testSelectionRootBounds("select_range_iframe_input.html", 1.0f);
1734     testSelectionRootBounds("select_range_iframe_input_overflow.html", 1.0f);
1735     testSelectionRootBounds("select_range_iframe_textarea.html", 1.0f);
1736     testSelectionRootBounds("select_range_iframe_textarea_overflow.html", 1.0f);
1737
1738     // Basic page with scale factor.
1739     testSelectionRootBounds("select_range_basic.html", 0.0f);
1740     testSelectionRootBounds("select_range_basic.html", 0.1f);
1741     testSelectionRootBounds("select_range_basic.html", 1.5f);
1742     testSelectionRootBounds("select_range_basic.html", 2.0f);
1743 }
1744
1745 } // namespace