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