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