[chromium] No triggering autofill on unfocus
[WebKit-https.git] / Source / WebKit / chromium / 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 "Document.h"
35 #include "Element.h"
36 #include "FrameTestHelpers.h"
37 #include "FrameView.h"
38 #include "HTMLDocument.h"
39 #include "URLTestHelpers.h"
40 #include "WebAutofillClient.h"
41 #include "WebContentDetectionResult.h"
42 #include "WebDocument.h"
43 #include "WebElement.h"
44 #include "WebFrame.h"
45 #include "WebFrameClient.h"
46 #include "WebFrameImpl.h"
47 #include "WebInputEvent.h"
48 #include "WebViewClient.h"
49 #include "WebViewImpl.h"
50 #include <gtest/gtest.h>
51 #include <public/Platform.h>
52 #include <public/WebSize.h>
53 #include <public/WebThread.h>
54 #include <public/WebUnitTestSupport.h>
55
56 using namespace WebKit;
57 using WebKit::FrameTestHelpers::runPendingTasks;
58 using WebKit::URLTestHelpers::toKURL;
59
60 namespace {
61
62 enum HorizontalScrollbarState {
63     NoHorizontalScrollbar,
64     VisibleHorizontalScrollbar,
65 };
66
67 enum VerticalScrollbarState {
68     NoVerticalScrollbar,
69     VisibleVerticalScrollbar,
70 };
71
72 class TestData {
73 public:
74     void setWebView(WebView* webView) { m_webView = static_cast<WebViewImpl*>(webView); }
75     void setSize(const WebSize& newSize) { m_size = newSize; }
76     HorizontalScrollbarState horizontalScrollbarState() const
77     {
78         return m_webView->hasHorizontalScrollbar() ? VisibleHorizontalScrollbar: NoHorizontalScrollbar;
79     }
80     VerticalScrollbarState verticalScrollbarState() const
81     {
82         return m_webView->hasVerticalScrollbar() ? VisibleVerticalScrollbar : NoVerticalScrollbar;
83     }
84     int width() const { return m_size.width; }
85     int height() const { return m_size.height; }
86
87 private:
88     WebSize m_size;
89     WebViewImpl* m_webView;
90 };
91
92 class AutoResizeWebViewClient : public WebViewClient {
93 public:
94     // WebViewClient methods
95     virtual void didAutoResize(const WebSize& newSize) { m_testData.setSize(newSize); }
96
97     // Local methods
98     TestData& testData() { return m_testData; }
99
100 private:
101     TestData m_testData;
102 };
103
104 class FormChangeWebViewClient : public WebViewClient {
105 public:
106     // WebViewClient methods
107     virtual void didChangeFormState(const WebNode& node)
108     {
109         m_focused = node.focused();
110         m_called = true;
111     }
112
113     // Local methods
114     void reset()
115     {
116         m_called = false;
117         m_focused = false;
118     }
119     bool called() { return m_called; }
120     bool focused() { return m_focused; }
121
122 private:
123     bool m_called;
124     bool m_focused;
125 };
126
127 class TapHandlingWebViewClient : public WebViewClient {
128 public:
129     // WebViewClient methods
130     virtual void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled)
131     {
132         if (event.type == WebInputEvent::GestureTap) {
133             m_tapX = event.x;
134             m_tapY = event.y;
135         } else if (event.type == WebInputEvent::GestureLongPress) {
136             m_longpressX = event.x;
137             m_longpressY = event.y;
138         }
139     }
140
141     // Local methods
142     void reset()
143     {
144         m_tapX = -1;
145         m_tapY = -1;
146         m_longpressX = -1;
147         m_longpressY = -1;
148     }
149     int tapX() { return m_tapX; }
150     int tapY() { return m_tapY; }
151     int longpressX() { return m_longpressX; }
152     int longpressY() { return m_longpressY; }
153
154 private:
155     int m_tapX;
156     int m_tapY;
157     int m_longpressX;
158     int m_longpressY;
159 };
160
161 class WebViewTest : public testing::Test {
162 public:
163     WebViewTest()
164         : m_baseURL("http://www.test.com/")
165     {
166     }
167
168     virtual void TearDown()
169     {
170         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
171     }
172
173 protected:
174     void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
175                         const std::string& pageWidth, const std::string& pageHeight,
176                         int expectedWidth, int expectedHeight,
177                         HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState);
178
179     void testTextInputType(WebTextInputType expectedType, const std::string& htmlFile);
180
181     std::string m_baseURL;
182 };
183
184 TEST_F(WebViewTest, FocusIsInactive)
185 {
186     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
187     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "visible_iframe.html");
188
189     webView->setFocus(true);
190     webView->setIsActive(true);
191     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
192     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
193
194     WebCore::HTMLDocument* document = static_cast<WebCore::HTMLDocument*>(frame->frame()->document());
195     EXPECT_TRUE(document->hasFocus());
196     webView->setFocus(false);
197     webView->setIsActive(false);
198     EXPECT_FALSE(document->hasFocus());
199     webView->setFocus(true);
200     webView->setIsActive(true);
201     EXPECT_TRUE(document->hasFocus());
202     webView->setFocus(true);
203     webView->setIsActive(false);
204     EXPECT_FALSE(document->hasFocus());
205     webView->setFocus(false);
206     webView->setIsActive(true);
207     EXPECT_TRUE(document->hasFocus());
208
209     webView->close();
210 }
211
212 TEST_F(WebViewTest, ActiveState)
213 {
214     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), "visible_iframe.html");
215     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "visible_iframe.html");
216
217     ASSERT_TRUE(webView);
218
219     webView->setIsActive(true);
220     EXPECT_TRUE(webView->isActive());
221
222     webView->setIsActive(false);
223     EXPECT_FALSE(webView->isActive());
224
225     webView->setIsActive(true);
226     EXPECT_TRUE(webView->isActive());
227
228     webView->close();
229 }
230
231 void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
232                                  const std::string& pageWidth, const std::string& pageHeight,
233                                  int expectedWidth, int expectedHeight,
234                                  HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState)
235 {
236     AutoResizeWebViewClient client;
237     std::string url = m_baseURL + "specify_size.html?" + pageWidth + ":" + pageHeight;
238     URLTestHelpers::registerMockedURLLoad(toKURL(url), "specify_size.html");
239     WebView* webView = FrameTestHelpers::createWebViewAndLoad(url, true, 0, &client);
240     client.testData().setWebView(webView);
241
242     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
243     WebCore::FrameView* frameView = frame->frame()->view();
244     frameView->layout();
245     EXPECT_FALSE(frameView->layoutPending());
246     EXPECT_FALSE(frameView->needsLayout());
247
248     webView->enableAutoResizeMode(minAutoResize, maxAutoResize);
249     EXPECT_TRUE(frameView->layoutPending());
250     EXPECT_TRUE(frameView->needsLayout());
251     frameView->layout();
252
253     EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
254
255     EXPECT_EQ(expectedWidth, client.testData().width());
256     EXPECT_EQ(expectedHeight, client.testData().height());
257     EXPECT_EQ(expectedHorizontalState, client.testData().horizontalScrollbarState());
258     EXPECT_EQ(expectedVerticalState, client.testData().verticalScrollbarState());
259
260     webView->close();
261 }
262
263 TEST_F(WebViewTest, DISABLED_AutoResizeMinimumSize)
264 {
265     WebSize minAutoResize(91, 56);
266     WebSize maxAutoResize(403, 302);
267     std::string pageWidth = "91px";
268     std::string pageHeight = "56px";
269     int expectedWidth = 91;
270     int expectedHeight = 56;
271     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
272                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
273 }
274
275 TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth)
276 {
277     WebSize minAutoResize(90, 95);
278     WebSize maxAutoResize(90, 100);
279     std::string pageWidth = "60px";
280     std::string pageHeight = "200px";
281     int expectedWidth = 90;
282     int expectedHeight = 100;
283     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
284                    expectedWidth, expectedHeight, NoHorizontalScrollbar, VisibleVerticalScrollbar);
285 }
286
287 TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
288 {
289     WebSize minAutoResize(90, 100);
290     WebSize maxAutoResize(200, 100);
291     std::string pageWidth = "300px";
292     std::string pageHeight = "80px";
293     int expectedWidth = 200;
294     int expectedHeight = 100;
295     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
296                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, NoVerticalScrollbar);
297 }
298
299 // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
300 // It seems we can run three AutoResize tests, then the next one breaks.
301 TEST_F(WebViewTest, DISABLED_AutoResizeInBetweenSizes)
302 {
303     WebSize minAutoResize(90, 95);
304     WebSize maxAutoResize(200, 300);
305     std::string pageWidth = "100px";
306     std::string pageHeight = "200px";
307     int expectedWidth = 100;
308     int expectedHeight = 200;
309     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
310                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
311 }
312
313 TEST_F(WebViewTest, DISABLED_AutoResizeOverflowSizes)
314 {
315     WebSize minAutoResize(90, 95);
316     WebSize maxAutoResize(200, 300);
317     std::string pageWidth = "300px";
318     std::string pageHeight = "400px";
319     int expectedWidth = 200;
320     int expectedHeight = 300;
321     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
322                    expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
323 }
324
325 TEST_F(WebViewTest, DISABLED_AutoResizeMaxSize)
326 {
327     WebSize minAutoResize(90, 95);
328     WebSize maxAutoResize(200, 300);
329     std::string pageWidth = "200px";
330     std::string pageHeight = "300px";
331     int expectedWidth = 200;
332     int expectedHeight = 300;
333     testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
334                    expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
335 }
336
337 void WebViewTest::testTextInputType(WebTextInputType expectedType, const std::string& htmlFile)
338 {
339     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
340     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + htmlFile);
341     webView->setInitialFocus(false);
342     EXPECT_EQ(expectedType, webView->textInputType());
343     webView->close();
344 }
345
346 // Disabled for https://bugs.webkit.org/show_bug.cgi?id=78746#c29
347 TEST_F(WebViewTest, DISABLED_TextInputType)
348 {
349     testTextInputType(WebTextInputTypeText, "input_field_default.html");
350     testTextInputType(WebTextInputTypePassword, "input_field_password.html");
351     testTextInputType(WebTextInputTypeEmail, "input_field_email.html");
352     testTextInputType(WebTextInputTypeSearch, "input_field_search.html");
353     testTextInputType(WebTextInputTypeNumber, "input_field_number.html");
354     testTextInputType(WebTextInputTypeTelephone, "input_field_tel.html");
355     testTextInputType(WebTextInputTypeURL, "input_field_url.html");
356 #if ENABLE(INPUT_TYPE_DATE)
357     testTextInputType(WebTextInputTypeDate, "input_field_date.html");
358 #endif
359 #if ENABLE(INPUT_TYPE_DATETIME)
360     testTextInputType(WebTextInputTypeDateTime, "input_field_datetime.html");
361 #endif
362 #if ENABLE(INPUT_TYPE_DATETIMELOCAL)
363     testTextInputType(WebTextInputTypeDateTimeLocal, "input_field_datetimelocal.html");
364 #endif
365 #if ENABLE(INPUT_TYPE_MONTH)
366     testTextInputType(WebTextInputTypeMonth, "input_field_month.html");
367 #endif
368 #if ENABLE(INPUT_TYPE_TIME)
369     testTextInputType(WebTextInputTypeTime, "input_field_time.html");
370 #endif
371 #if ENABLE(INPUT_TYPE_WEEK)
372     testTextInputType(WebTextInputTypeWeek, "input_field_week.html");
373 #endif
374
375 }
376
377 TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
378 {
379     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
380     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
381     webView->setInitialFocus(false);
382     webView->setEditableSelectionOffsets(5, 13);
383     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
384     EXPECT_EQ("56789abc", frame->selectionAsText());
385     WebTextInputInfo info = webView->textInputInfo();
386     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
387     EXPECT_EQ(5, info.selectionStart);
388     EXPECT_EQ(13, info.selectionEnd);
389     EXPECT_EQ(-1, info.compositionStart);
390     EXPECT_EQ(-1, info.compositionEnd);
391     webView->close();
392
393     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_editable_populated.html"));
394     webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "content_editable_populated.html");
395     webView->setInitialFocus(false);
396     webView->setEditableSelectionOffsets(8, 19);
397     frame = static_cast<WebFrameImpl*>(webView->mainFrame());
398     EXPECT_EQ("89abcdefghi", frame->selectionAsText());
399     info = webView->textInputInfo();
400     EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", info.value);
401     EXPECT_EQ(8, info.selectionStart);
402     EXPECT_EQ(19, info.selectionEnd);
403     EXPECT_EQ(-1, info.compositionStart);
404     EXPECT_EQ(-1, info.compositionEnd);
405     webView->close();
406 }
407
408 TEST_F(WebViewTest, FormChange)
409 {
410     FormChangeWebViewClient client;
411     client.reset();
412     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_set_value_while_focused.html"));
413     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_set_value_while_focused.html", true, 0, &client);
414     EXPECT_TRUE(client.called());
415     EXPECT_TRUE(client.focused());
416     client.reset();
417     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_set_value_while_not_focused.html"));
418     webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_set_value_while_not_focused.html", true, 0, &client);
419     EXPECT_TRUE(client.called());
420     EXPECT_FALSE(client.focused());
421     webView->close();
422 }
423
424 TEST_F(WebViewTest, ExtendSelectionAndDelete)
425 {
426     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
427     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
428     webView->setInitialFocus(false);
429     webView->setEditableSelectionOffsets(10, 10);
430     webView->extendSelectionAndDelete(5, 8);
431     WebTextInputInfo info = webView->textInputInfo();
432     EXPECT_EQ("01234ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
433     EXPECT_EQ(5, info.selectionStart);
434     EXPECT_EQ(5, info.selectionEnd);
435     webView->extendSelectionAndDelete(10, 0);
436     info = webView->textInputInfo();
437     EXPECT_EQ("ijklmnopqrstuvwxyz", std::string(info.value.utf8().data()));
438     webView->close();
439 }
440
441 TEST_F(WebViewTest, SetCompositionFromExistingText)
442 {
443     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
444     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
445     webView->setInitialFocus(false);
446     WebVector<WebCompositionUnderline> emptyUnderlines;
447     webView->setEditableSelectionOffsets(4, 10);
448     webView->setCompositionFromExistingText(8, 12, emptyUnderlines);
449     WebTextInputInfo info = webView->textInputInfo();
450     EXPECT_EQ(4, info.selectionStart);
451     EXPECT_EQ(10, info.selectionEnd);
452     EXPECT_EQ(8, info.compositionStart);
453     EXPECT_EQ(12, info.compositionEnd);
454     webView->setCompositionFromExistingText(0, 0, emptyUnderlines);
455     info = webView->textInputInfo();
456     EXPECT_EQ(4, info.selectionStart);
457     EXPECT_EQ(10, info.selectionEnd);
458     EXPECT_EQ(-1, info.compositionStart);
459     EXPECT_EQ(-1, info.compositionEnd);
460     webView->close();
461 }
462
463 TEST_F(WebViewTest, IsSelectionAnchorFirst)
464 {
465     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
466     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
467     WebFrame* frame = webView->mainFrame();
468
469     webView->setInitialFocus(false);
470     webView->setEditableSelectionOffsets(4, 10);
471     EXPECT_TRUE(webView->isSelectionAnchorFirst());
472     WebRect anchor;
473     WebRect focus;
474     webView->selectionBounds(anchor, focus);
475     frame->selectRange(WebPoint(focus.x, focus.y), WebPoint(anchor.x, anchor.y));
476     EXPECT_FALSE(webView->isSelectionAnchorFirst());
477     webView->close();
478 }
479
480 TEST_F(WebViewTest, ResetScrollAndScaleState)
481 {
482     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("hello_world.html"));
483     WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "hello_world.html"));
484     webViewImpl->resize(WebSize(640, 480));
485     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
486     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
487
488     // Make the page scale and scroll with the given paremeters.
489     webViewImpl->setPageScaleFactor(2.0f, WebPoint(116, 84));
490     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
491     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
492     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
493     webViewImpl->page()->mainFrame()->loader()->history()->saveDocumentAndScrollState();
494
495     // Confirm that restoring the page state restores the parameters.
496     webViewImpl->setPageScaleFactor(1.5f, WebPoint(16, 24));
497     EXPECT_EQ(1.5f, webViewImpl->pageScaleFactor());
498     EXPECT_EQ(16, webViewImpl->mainFrame()->scrollOffset().width);
499     EXPECT_EQ(24, webViewImpl->mainFrame()->scrollOffset().height);
500     webViewImpl->page()->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
501     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
502     EXPECT_EQ(116, webViewImpl->mainFrame()->scrollOffset().width);
503     EXPECT_EQ(84, webViewImpl->mainFrame()->scrollOffset().height);
504     webViewImpl->page()->mainFrame()->loader()->history()->saveDocumentAndScrollState();
505
506     // Confirm that resetting the page state resets the saved scroll position.
507     // The HistoryController treats a page scale factor of 0.0f as special and avoids
508     // restoring it to the WebView.
509     webViewImpl->resetScrollAndScaleState();
510     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
511     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
512     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
513     webViewImpl->page()->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
514     EXPECT_EQ(1.0f, webViewImpl->pageScaleFactor());
515     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().width);
516     EXPECT_EQ(0, webViewImpl->mainFrame()->scrollOffset().height);
517     webViewImpl->close();
518 }
519
520 class ContentDetectorClient : public WebViewClient {
521 public:
522     ContentDetectorClient() { reset(); }
523
524     virtual WebContentDetectionResult detectContentAround(const WebHitTestResult& hitTest) OVERRIDE
525     {
526         m_contentDetectionRequested = true;
527         return m_contentDetectionResult;
528     }
529
530     virtual void scheduleContentIntent(const WebURL& url) OVERRIDE
531     {
532         m_scheduledIntentURL = url;
533     }
534
535     virtual void cancelScheduledContentIntents() OVERRIDE
536     {
537         m_pendingIntentsCancelled = true;
538     }
539
540     void reset()
541     {
542         m_contentDetectionRequested = false;
543         m_pendingIntentsCancelled = false;
544         m_scheduledIntentURL = WebURL();
545         m_contentDetectionResult = WebContentDetectionResult();
546     }
547
548     bool contentDetectionRequested() const { return m_contentDetectionRequested; }
549     bool pendingIntentsCancelled() const { return m_pendingIntentsCancelled; }
550     const WebURL& scheduledIntentURL() const { return m_scheduledIntentURL; }
551     void setContentDetectionResult(const WebContentDetectionResult& result) { m_contentDetectionResult = result; }
552
553 private:
554     bool m_contentDetectionRequested;
555     bool m_pendingIntentsCancelled;
556     WebURL m_scheduledIntentURL;
557     WebContentDetectionResult m_contentDetectionResult;
558 };
559
560 static bool tapElementById(WebView* webView, WebInputEvent::Type type, const WebString& id)
561 {
562     ASSERT(webView);
563     RefPtr<WebCore::Element> element = static_cast<PassRefPtr<WebCore::Element> >(webView->mainFrame()->document().getElementById(id));
564     if (!element)
565         return false;
566
567     element->scrollIntoViewIfNeeded();
568     WebCore::IntPoint center = element->screenRect().center();
569
570     WebGestureEvent event;
571     event.type = type;
572     event.x = center.x();
573     event.y = center.y();
574
575     webView->handleInputEvent(event);
576     runPendingTasks();
577     return true;
578 }
579
580 TEST_F(WebViewTest, DetectContentAroundPosition)
581 {
582     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("content_listeners.html"));
583
584     ContentDetectorClient client;
585     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "content_listeners.html", true, 0, &client);
586     webView->resize(WebSize(500, 300));
587     webView->layout();
588     runPendingTasks();
589
590     WebString clickListener = WebString::fromUTF8("clickListener");
591     WebString touchstartListener = WebString::fromUTF8("touchstartListener");
592     WebString mousedownListener = WebString::fromUTF8("mousedownListener");
593     WebString noListener = WebString::fromUTF8("noListener");
594     WebString link = WebString::fromUTF8("link");
595
596     // Ensure content detection is not requested for nodes listening to click,
597     // mouse or touch events when we do simple taps.
598     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, clickListener));
599     EXPECT_FALSE(client.contentDetectionRequested());
600     client.reset();
601
602     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, touchstartListener));
603     EXPECT_FALSE(client.contentDetectionRequested());
604     client.reset();
605
606     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, mousedownListener));
607     EXPECT_FALSE(client.contentDetectionRequested());
608     client.reset();
609
610     // Content detection should work normally without these event listeners.
611     // The click listener in the body should be ignored as a special case.
612     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
613     EXPECT_TRUE(client.contentDetectionRequested());
614     EXPECT_FALSE(client.scheduledIntentURL().isValid());
615
616     WebURL intentURL = toKURL(m_baseURL);
617     client.setContentDetectionResult(WebContentDetectionResult(WebRange(), WebString(), intentURL));
618     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureTap, noListener));
619     EXPECT_TRUE(client.scheduledIntentURL() == intentURL);
620
621     // Tapping elsewhere should cancel the scheduled intent.
622     WebGestureEvent event;
623     event.type = WebInputEvent::GestureTap;
624     webView->handleInputEvent(event);
625     runPendingTasks();
626     EXPECT_TRUE(client.pendingIntentsCancelled());
627     webView->close();
628 }
629
630 TEST_F(WebViewTest, ClientTapHandling)
631 {
632     TapHandlingWebViewClient client;
633     client.reset();
634     WebView* webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true, 0, &client);
635     WebGestureEvent event;
636     event.type = WebInputEvent::GestureTap;
637     event.x = 3;
638     event.y = 8;
639     webView->handleInputEvent(event);
640     runPendingTasks();
641     EXPECT_EQ(3, client.tapX());
642     EXPECT_EQ(8, client.tapY());
643     client.reset();
644     event.type = WebInputEvent::GestureLongPress;
645     event.x = 25;
646     event.y = 7;
647     webView->handleInputEvent(event);
648     runPendingTasks();
649     EXPECT_EQ(25, client.longpressX());
650     EXPECT_EQ(7, client.longpressY());
651     webView->close();
652 }
653
654 #if OS(ANDROID)
655 TEST_F(WebViewTest, LongPressSelection)
656 {
657     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("longpress_selection.html"));
658
659     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "longpress_selection.html", true);
660     webView->resize(WebSize(500, 300));
661     webView->layout();
662     runPendingTasks();
663
664     WebString target = WebString::fromUTF8("target");
665     WebString onselectstartfalse = WebString::fromUTF8("onselectstartfalse");
666     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
667
668     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, onselectstartfalse));
669     EXPECT_EQ("", std::string(frame->selectionAsText().utf8().data()));
670     EXPECT_TRUE(tapElementById(webView, WebInputEvent::GestureLongPress, target));
671     EXPECT_EQ("testword", std::string(frame->selectionAsText().utf8().data()));
672     webView->close();
673 }
674 #endif
675
676 TEST_F(WebViewTest, SelectionOnDisabledInput)
677 {
678     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_disabled.html"));
679     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "selection_disabled.html", true);
680     webView->resize(WebSize(640, 480));
681     webView->layout();
682     runPendingTasks();
683
684     std::string testWord = "This text should be selected.";
685
686     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
687     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
688
689     size_t location;
690     size_t length;
691     WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(webView);
692
693     EXPECT_TRUE(webViewImpl->caretOrSelectionRange(&location, &length));
694     EXPECT_EQ(location, 0UL);
695     EXPECT_EQ(length, testWord.length());
696
697     webView->close();
698 }
699
700 TEST_F(WebViewTest, SelectionOnReadOnlyInput)
701 {
702     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("selection_readonly.html"));
703     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "selection_readonly.html", true);
704     webView->resize(WebSize(640, 480));
705     webView->layout();
706     runPendingTasks();
707
708     std::string testWord = "This text should be selected.";
709
710     WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
711     EXPECT_EQ(testWord, std::string(frame->selectionAsText().utf8().data()));
712
713     size_t location;
714     size_t length;
715     WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(webView);
716
717     EXPECT_TRUE(webViewImpl->caretOrSelectionRange(&location, &length));
718     EXPECT_EQ(location, 0UL);
719     EXPECT_EQ(length, testWord.length());
720
721     webView->close();
722 }
723
724 class MockAutofillClient : public WebAutofillClient {
725 public:
726     MockAutofillClient()
727         : m_ignoreTextChanges(false)
728         , m_textChangesWhileIgnored(0)
729         , m_textChangesWhileNotIgnored(0) { }
730
731     virtual ~MockAutofillClient() { }
732
733     virtual void setIgnoreTextChanges(bool ignore) OVERRIDE { m_ignoreTextChanges = ignore; }
734     virtual void textFieldDidChange(const WebInputElement&) OVERRIDE
735     {
736         if (m_ignoreTextChanges)
737             ++m_textChangesWhileIgnored;
738         else
739             ++m_textChangesWhileNotIgnored;
740     }
741
742     void clearChangeCounts()
743     {
744         m_textChangesWhileIgnored = 0;
745         m_textChangesWhileNotIgnored = 0;
746     }
747
748     int textChangesWhileIgnored() { return m_textChangesWhileIgnored; }
749     int textChangesWhileNotIgnored() { return m_textChangesWhileNotIgnored; }
750
751 private:
752     bool m_ignoreTextChanges;
753     int m_textChangesWhileIgnored;
754     int m_textChangesWhileNotIgnored;
755 };
756
757
758 TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange)
759 {
760     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
761     MockAutofillClient client;
762     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
763     webView->setAutofillClient(&client);
764     webView->setInitialFocus(false);
765
766     // Set up a composition that needs to be committed.
767     WebVector<WebCompositionUnderline> emptyUnderlines;
768     webView->setEditableSelectionOffsets(4, 10);
769     webView->setCompositionFromExistingText(8, 12, emptyUnderlines);
770     WebTextInputInfo info = webView->textInputInfo();
771     EXPECT_EQ(4, info.selectionStart);
772     EXPECT_EQ(10, info.selectionEnd);
773     EXPECT_EQ(8, info.compositionStart);
774     EXPECT_EQ(12, info.compositionEnd);
775
776     // Clear the focus and track that the subsequent composition commit does not trigger a
777     // text changed notification for autofill.
778     client.clearChangeCounts();
779     webView->setFocus(false);
780     EXPECT_EQ(1, client.textChangesWhileIgnored());
781     EXPECT_EQ(0, client.textChangesWhileNotIgnored());
782
783     webView->setAutofillClient(0);
784     webView->close();
785 }
786
787 TEST_F(WebViewTest, ConfirmCompositionTriggersAutofillTextChange)
788 {
789     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
790     MockAutofillClient client;
791     WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "input_field_populated.html");
792     webView->setAutofillClient(&client);
793     webView->setInitialFocus(false);
794
795     // Set up a composition that needs to be committed.
796     std::string compositionText("testingtext");
797
798     WebVector<WebCompositionUnderline> emptyUnderlines;
799     webView->setComposition(WebString::fromUTF8(compositionText.c_str()), emptyUnderlines, 0, compositionText.length());
800
801     WebTextInputInfo info = webView->textInputInfo();
802     EXPECT_EQ(0, info.selectionStart);
803     EXPECT_EQ((int) compositionText.length(), info.selectionEnd);
804     EXPECT_EQ(0, info.compositionStart);
805     EXPECT_EQ((int) compositionText.length(), info.compositionEnd);
806
807     client.clearChangeCounts();
808     webView->confirmComposition();
809     EXPECT_EQ(0, client.textChangesWhileIgnored());
810     EXPECT_EQ(1, client.textChangesWhileNotIgnored());
811
812     webView->setAutofillClient(0);
813     webView->close();
814 }
815
816 }