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