1 /* 2 * Copyright (C) 2010 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 33 #include "WebFrame.h" 34 35 #include <gmock/gmock.h> 36 #include <gtest/gtest.h> 37 #include "FrameTestHelpers.h" 38 #include "RuntimeEnabledFeatures.h" 39 #include "SkBitmap.h" 40 #include "SkCanvas.h" 41 #include "URLTestHelpers.h" 42 #include "WebDataSource.h" 43 #include "WebDocument.h" 44 #include "WebFindOptions.h" 45 #include "WebFormElement.h" 46 #include "WebFrameClient.h" 47 #include "WebFrameImpl.h" 48 #include "WebHistoryItem.h" 49 #include "WebRange.h" 50 #include "WebScriptSource.h" 51 #include "WebSearchableFormData.h" 52 #include "WebSecurityOrigin.h" 53 #include "WebSecurityPolicy.h" 54 #include "WebSettings.h" 55 #include "WebSpellCheckClient.h" 56 #include "WebTextCheckingCompletion.h" 57 #include "WebTextCheckingResult.h" 58 #include "WebViewClient.h" 59 #include "WebViewImpl.h" 60 #include "core/dom/Clipboard.h" 61 #include "core/dom/DocumentMarkerController.h" 62 #include "core/events/MouseEvent.h" 63 #include "core/dom/Range.h" 64 #include "core/editing/Editor.h" 65 #include "core/editing/FrameSelection.h" 66 #include "core/editing/SpellChecker.h" 67 #include "core/editing/VisiblePosition.h" 68 #include "core/html/HTMLFormElement.h" 69 #include "core/loader/FrameLoadRequest.h" 70 #include "core/page/EventHandler.h" 71 #include "core/frame/Frame.h" 72 #include "core/frame/FrameView.h" 73 #include "core/frame/Settings.h" 74 #include "core/rendering/HitTestResult.h" 75 #include "core/rendering/RenderLayerCompositor.h" 76 #include "core/rendering/RenderView.h" 77 #include "core/rendering/TextAutosizer.h" 78 #include "platform/geometry/FloatRect.h" 79 #include "platform/network/ResourceError.h" 80 #include "platform/scroll/ScrollbarTheme.h" 81 #include "v8.h" 82 #include "public/platform/Platform.h" 83 #include "public/platform/WebFloatRect.h" 84 #include "public/platform/WebThread.h" 85 #include "public/platform/WebURL.h" 86 #include "public/platform/WebURLResponse.h" 87 #include "public/platform/WebUnitTestSupport.h" 88 #include "wtf/dtoa/utils.h" 89 #include "wtf/Forward.h" 90 #include <map> 91 92 using namespace blink; 93 using WebCore::Document; 94 using WebCore::DocumentMarker; 95 using WebCore::Element; 96 using WebCore::FloatRect; 97 using WebCore::HitTestRequest; 98 using WebCore::Range; 99 using blink::URLTestHelpers::toKURL; 100 using blink::FrameTestHelpers::runPendingTasks; 101 102 namespace { 103 104 const int touchPointPadding = 32; 105 106 #define EXPECT_EQ_RECT(a, b) \ 107 EXPECT_EQ(a.x(), b.x()); \ 108 EXPECT_EQ(a.y(), b.y()); \ 109 EXPECT_EQ(a.width(), b.width()); \ 110 EXPECT_EQ(a.height(), b.height()); 111 112 class FakeWebFrameClient : public WebFrameClient { 113 // To make the destructor public. 114 }; 115 116 class FakeCompositingWebViewClient : public WebViewClient { 117 public: 118 virtual ~FakeCompositingWebViewClient() 119 { 120 } 121 122 virtual void initializeLayerTreeView() OVERRIDE 123 { 124 m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting(WebUnitTestSupport::TestViewTypeUnitTest)); 125 ASSERT(m_layerTreeView); 126 } 127 128 virtual WebLayerTreeView* layerTreeView() OVERRIDE 129 { 130 return m_layerTreeView.get(); 131 } 132 133 FakeWebFrameClient m_fakeWebFrameClient; 134 135 private: 136 OwnPtr<WebLayerTreeView> m_layerTreeView; 137 }; 138 139 class WebFrameTest : public testing::Test { 140 protected: 141 WebFrameTest() 142 : m_baseURL("http://www.test.com/") 143 , m_chromeURL("chrome://") 144 { 145 } 146 147 virtual ~WebFrameTest() 148 { 149 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 150 } 151 152 void registerMockedHttpURLLoad(const std::string& fileName) 153 { 154 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str())); 155 } 156 157 void registerMockedChromeURLLoad(const std::string& fileName) 158 { 159 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_chromeURL.c_str()), WebString::fromUTF8(fileName.c_str())); 160 } 161 162 static void configueCompositingWebView(WebSettings* settings) 163 { 164 settings->setForceCompositingMode(true); 165 settings->setAcceleratedCompositingEnabled(true); 166 settings->setAcceleratedCompositingForFixedPositionEnabled(true); 167 settings->setAcceleratedCompositingForOverflowScrollEnabled(true); 168 settings->setAcceleratedCompositingForScrollableFramesEnabled(true); 169 settings->setCompositedScrollingForFramesEnabled(true); 170 settings->setFixedPositionCreatesStackingContext(true); 171 } 172 173 void initializeTextSelectionWebView(const std::string& url, FrameTestHelpers::WebViewHelper* webViewHelper) 174 { 175 webViewHelper->initializeAndLoad(url, true); 176 webViewHelper->webView()->settings()->setDefaultFontSize(12); 177 webViewHelper->webView()->resize(WebSize(640, 480)); 178 } 179 180 std::string m_baseURL; 181 std::string m_chromeURL; 182 }; 183 184 class UseMockScrollbarSettings { 185 public: 186 UseMockScrollbarSettings() 187 { 188 WebCore::Settings::setMockScrollbarsEnabled(true); 189 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true); 190 EXPECT_TRUE(WebCore::ScrollbarTheme::theme()->usesOverlayScrollbars()); 191 } 192 193 ~UseMockScrollbarSettings() 194 { 195 WebCore::Settings::setMockScrollbarsEnabled(false); 196 WebCore::RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false); 197 } 198 }; 199 200 TEST_F(WebFrameTest, ContentText) 201 { 202 registerMockedHttpURLLoad("iframes_test.html"); 203 registerMockedHttpURLLoad("visible_iframe.html"); 204 registerMockedHttpURLLoad("invisible_iframe.html"); 205 registerMockedHttpURLLoad("zero_sized_iframe.html"); 206 207 FrameTestHelpers::WebViewHelper webViewHelper; 208 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html"); 209 210 // Now retrieve the frames text and test it only includes visible elements. 211 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 212 EXPECT_NE(std::string::npos, content.find(" visible paragraph")); 213 EXPECT_NE(std::string::npos, content.find(" visible iframe")); 214 EXPECT_EQ(std::string::npos, content.find(" invisible pararaph")); 215 EXPECT_EQ(std::string::npos, content.find(" invisible iframe")); 216 EXPECT_EQ(std::string::npos, content.find("iframe with zero size")); 217 } 218 219 TEST_F(WebFrameTest, FrameForEnteredContext) 220 { 221 registerMockedHttpURLLoad("iframes_test.html"); 222 registerMockedHttpURLLoad("visible_iframe.html"); 223 registerMockedHttpURLLoad("invisible_iframe.html"); 224 registerMockedHttpURLLoad("zero_sized_iframe.html"); 225 226 FrameTestHelpers::WebViewHelper webViewHelper; 227 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", true); 228 229 v8::HandleScope scope(v8::Isolate::GetCurrent()); 230 EXPECT_EQ(webViewHelper.webView()->mainFrame(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->mainWorldScriptContext())); 231 EXPECT_EQ(webViewHelper.webView()->mainFrame()->firstChild(), WebFrame::frameForContext(webViewHelper.webView()->mainFrame()->firstChild()->mainWorldScriptContext())); 232 } 233 234 TEST_F(WebFrameTest, FormWithNullFrame) 235 { 236 registerMockedHttpURLLoad("form.html"); 237 238 FrameTestHelpers::WebViewHelper webViewHelper; 239 webViewHelper.initializeAndLoad(m_baseURL + "form.html"); 240 241 WebVector<WebFormElement> forms; 242 webViewHelper.webView()->mainFrame()->document().forms(forms); 243 webViewHelper.reset(); 244 245 EXPECT_EQ(forms.size(), 1U); 246 247 // This test passes if this doesn't crash. 248 WebSearchableFormData searchableDataForm(forms[0]); 249 } 250 251 TEST_F(WebFrameTest, ChromePageJavascript) 252 { 253 registerMockedChromeURLLoad("history.html"); 254 255 // Pass true to enable JavaScript. 256 FrameTestHelpers::WebViewHelper webViewHelper; 257 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true); 258 259 // Try to run JS against the chrome-style URL. 260 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))"); 261 262 // Required to see any updates in contentAsText. 263 webViewHelper.webView()->layout(); 264 265 // Now retrieve the frame's text and ensure it was modified by running javascript. 266 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 267 EXPECT_NE(std::string::npos, content.find("Clobbered")); 268 } 269 270 TEST_F(WebFrameTest, ChromePageNoJavascript) 271 { 272 registerMockedChromeURLLoad("history.html"); 273 274 /// Pass true to enable JavaScript. 275 FrameTestHelpers::WebViewHelper webViewHelper; 276 webViewHelper.initializeAndLoad(m_chromeURL + "history.html", true); 277 278 // Try to run JS against the chrome-style URL after prohibiting it. 279 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome"); 280 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Clobbered'))"); 281 282 // Required to see any updates in contentAsText. 283 webViewHelper.webView()->layout(); 284 285 // Now retrieve the frame's text and ensure it wasn't modified by running javascript. 286 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 287 EXPECT_EQ(std::string::npos, content.find("Clobbered")); 288 } 289 290 TEST_F(WebFrameTest, LocationSetHostWithMissingPort) 291 { 292 std::string fileName = "print-location-href.html"; 293 registerMockedHttpURLLoad(fileName); 294 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName)); 295 296 FrameTestHelpers::WebViewHelper webViewHelper; 297 298 /// Pass true to enable JavaScript. 299 webViewHelper.initializeAndLoad(m_baseURL + fileName, true); 300 301 // Setting host to "hostname:" should be treated as "hostname:0". 302 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.host = 'www.test.com:'; void 0;"); 303 304 runPendingTasks(); 305 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 306 307 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;"); 308 // Required to see any updates in contentAsText. 309 runPendingTasks(); 310 webViewHelper.webView()->layout(); 311 312 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 313 EXPECT_EQ("http://www.test.com:0/" + fileName, content); 314 } 315 316 TEST_F(WebFrameTest, LocationSetEmptyPort) 317 { 318 std::string fileName = "print-location-href.html"; 319 registerMockedHttpURLLoad(fileName); 320 URLTestHelpers::registerMockedURLLoad(toKURL("http://www.test.com:0/" + fileName), WebString::fromUTF8(fileName)); 321 322 FrameTestHelpers::WebViewHelper webViewHelper; 323 324 /// Pass true to enable JavaScript. 325 webViewHelper.initializeAndLoad(m_baseURL + fileName, true); 326 327 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:location.port = ''; void 0;"); 328 329 runPendingTasks(); 330 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 331 332 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.textContent = location.href; void 0;"); 333 // Required to see any updates in contentAsText. 334 runPendingTasks(); 335 webViewHelper.webView()->layout(); 336 337 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 338 EXPECT_EQ("http://www.test.com:0/" + fileName, content); 339 } 340 341 class CSSCallbackWebFrameClient : public WebFrameClient { 342 public: 343 CSSCallbackWebFrameClient() : m_updateCount(0) { } 344 virtual void didMatchCSS(WebFrame*, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE; 345 346 std::map<WebFrame*, std::set<std::string> > m_matchedSelectors; 347 int m_updateCount; 348 }; 349 350 void CSSCallbackWebFrameClient::didMatchCSS(WebFrame* frame, const WebVector<WebString>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) 351 { 352 ++m_updateCount; 353 std::set<std::string>& frameSelectors = m_matchedSelectors[frame]; 354 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) { 355 std::string selector = newlyMatchingSelectors[i].utf8(); 356 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector; 357 frameSelectors.insert(selector); 358 } 359 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) { 360 std::string selector = stoppedMatchingSelectors[i].utf8(); 361 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector; 362 frameSelectors.erase(selector); 363 } 364 } 365 366 class WebFrameCSSCallbackTest : public testing::Test { 367 protected: 368 WebFrameCSSCallbackTest() 369 { 370 371 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->mainFrame(); 372 } 373 374 ~WebFrameCSSCallbackTest() 375 { 376 EXPECT_EQ(1U, m_client.m_matchedSelectors.size()); 377 } 378 379 WebDocument doc() const 380 { 381 return m_frame->document(); 382 } 383 384 int updateCount() const 385 { 386 return m_client.m_updateCount; 387 } 388 389 const std::set<std::string>& matchedSelectors() 390 { 391 return m_client.m_matchedSelectors[m_frame]; 392 } 393 394 void loadHTML(const WebData& html) 395 { 396 m_frame->loadHTMLString(html, toKURL("about:blank")); 397 runPendingTasks(); 398 } 399 400 void executeScript(const WebString& code) 401 { 402 m_frame->executeScript(WebScriptSource(code)); 403 runPendingTasks(); 404 } 405 406 CSSCallbackWebFrameClient m_client; 407 FrameTestHelpers::WebViewHelper m_helper; 408 WebFrame* m_frame; 409 }; 410 411 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet) 412 { 413 loadHTML( 414 "<style>" 415 // This stylesheet checks that the internal property and value can't be 416 // set by a stylesheet, only WebDocument::watchCSSSelectors(). 417 "div.initial_on { -internal-callback: none; }" 418 "div.initial_off { -internal-callback: -internal-presence; }" 419 "</style>" 420 "<div class=\"initial_on\"></div>" 421 "<div class=\"initial_off\"></div>"); 422 423 std::vector<WebString> selectors; 424 selectors.push_back(WebString::fromUTF8("div.initial_on")); 425 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors)); 426 runPendingTasks(); 427 EXPECT_EQ(1, updateCount()); 428 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on")); 429 430 // Check that adding a watched selector calls back for already-present nodes. 431 selectors.push_back(WebString::fromUTF8("div.initial_off")); 432 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 433 runPendingTasks(); 434 EXPECT_EQ(2, updateCount()); 435 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div.initial_on")); 436 437 // Check that we can turn off callbacks for certain selectors. 438 doc().watchCSSSelectors(WebVector<WebString>()); 439 runPendingTasks(); 440 EXPECT_EQ(3, updateCount()); 441 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); 442 } 443 444 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle) 445 { 446 // Check that adding an element calls back when it matches an existing rule. 447 std::vector<WebString> selectors; 448 selectors.push_back(WebString::fromUTF8("span")); 449 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 450 451 executeScript( 452 "i1 = document.createElement('span');" 453 "i1.id = 'first_span';" 454 "document.body.appendChild(i1)"); 455 EXPECT_EQ(1, updateCount()); 456 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 457 458 // Adding a second element that shares a RenderStyle shouldn't call back. 459 // We use <span>s to avoid default style rules that can set 460 // RenderStyle::unique(). 461 executeScript( 462 "i2 = document.createElement('span');" 463 "i2.id = 'second_span';" 464 "i1 = document.getElementById('first_span');" 465 "i1.parentNode.insertBefore(i2, i1.nextSibling);"); 466 EXPECT_EQ(1, updateCount()); 467 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 468 469 // Removing the first element shouldn't call back. 470 executeScript( 471 "i1 = document.getElementById('first_span');" 472 "i1.parentNode.removeChild(i1);"); 473 EXPECT_EQ(1, updateCount()); 474 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 475 476 // But removing the second element *should* call back. 477 executeScript( 478 "i2 = document.getElementById('second_span');" 479 "i2.parentNode.removeChild(i2);"); 480 EXPECT_EQ(2, updateCount()); 481 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); 482 } 483 484 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange) 485 { 486 loadHTML("<span></span>"); 487 488 std::vector<WebString> selectors; 489 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]")); 490 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 491 runPendingTasks(); 492 493 EXPECT_EQ(0, updateCount()); 494 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); 495 496 executeScript( 497 "document.querySelector('span').setAttribute('attr', 'value');"); 498 EXPECT_EQ(1, updateCount()); 499 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]")); 500 } 501 502 TEST_F(WebFrameCSSCallbackTest, DisplayNone) 503 { 504 loadHTML("<div style='display:none'><span></span></div>"); 505 506 std::vector<WebString> selectors; 507 selectors.push_back(WebString::fromUTF8("span")); 508 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 509 runPendingTasks(); 510 511 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees."; 512 513 executeScript( 514 "d = document.querySelector('div');" 515 "d.style.display = 'block';"); 516 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed."; 517 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 518 519 executeScript( 520 "d = document.querySelector('div');" 521 "d.style.display = 'none';"); 522 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplayed."; 523 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); 524 525 executeScript( 526 "s = document.querySelector('span');" 527 "s.style.display = 'none';"); 528 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's already undisplayed."; 529 530 executeScript( 531 "d = document.querySelector('div');" 532 "d.style.display = 'block';"); 533 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span is display:none."; 534 535 executeScript( 536 "s = document.querySelector('span');" 537 "s.style.display = 'inline';"); 538 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callback."; 539 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 540 541 executeScript( 542 "s = document.querySelector('span');" 543 "s.style.display = 'none';"); 544 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produce another callback."; 545 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); 546 } 547 548 TEST_F(WebFrameCSSCallbackTest, Reparenting) 549 { 550 loadHTML( 551 "<div id='d1'><span></span></div>" 552 "<div id='d2'></div>"); 553 554 std::vector<WebString> selectors; 555 selectors.push_back(WebString::fromUTF8("span")); 556 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 557 runPendingTasks(); 558 559 EXPECT_EQ(1, updateCount()); 560 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 561 562 executeScript( 563 "s = document.querySelector('span');" 564 "d2 = document.getElementById('d2');" 565 "d2.appendChild(s);"); 566 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to match shouldn't send a spurious callback."; 567 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); 568 } 569 570 TEST_F(WebFrameCSSCallbackTest, MultiSelector) 571 { 572 loadHTML("<span></span>"); 573 574 // Check that selector lists match as the whole list, not as each element 575 // independently. 576 std::vector<WebString> selectors; 577 selectors.push_back(WebString::fromUTF8("span")); 578 selectors.push_back(WebString::fromUTF8("span,p")); 579 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 580 581 runPendingTasks(); 582 EXPECT_EQ(1, updateCount()); 583 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p")); 584 } 585 586 TEST_F(WebFrameCSSCallbackTest, InvalidSelector) 587 { 588 loadHTML("<p><span></span></p>"); 589 590 // Build a list with one valid selector and one invalid. 591 std::vector<WebString> selectors; 592 selectors.push_back(WebString::fromUTF8("span")); 593 selectors.push_back(WebString::fromUTF8("[")); // Invalid. 594 selectors.push_back(WebString::fromUTF8("p span")); // Not compound. 595 doc().watchCSSSelectors(WebVector<WebString>(selectors)); 596 597 runPendingTasks(); 598 EXPECT_EQ(1, updateCount()); 599 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")) 600 << "An invalid selector shouldn't prevent other selectors from matching."; 601 } 602 603 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) 604 { 605 registerMockedHttpURLLoad("postmessage_test.html"); 606 607 // Pass true to enable JavaScript. 608 FrameTestHelpers::WebViewHelper webViewHelper; 609 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true); 610 611 // Send a message with the correct origin. 612 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL))); 613 WebDOMEvent event = webViewHelper.webView()->mainFrame()->document().createEvent("MessageEvent"); 614 WebDOMMessageEvent message = event.to<WebDOMMessageEvent>(); 615 WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo")); 616 message.initMessageEvent("message", false, false, data, "http://origin.com", 0, ""); 617 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message); 618 619 // Send another message with incorrect origin. 620 WebSecurityOrigin incorrectOrigin(WebSecurityOrigin::create(toKURL(m_chromeURL))); 621 webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(incorrectOrigin, message); 622 623 // Required to see any updates in contentAsText. 624 webViewHelper.webView()->layout(); 625 626 // Verify that only the first addition is in the body of the page. 627 std::string content = webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 628 EXPECT_NE(std::string::npos, content.find("Message 1.")); 629 EXPECT_EQ(std::string::npos, content.find("Message 2.")); 630 } 631 632 class FixedLayoutTestWebViewClient : public WebViewClient { 633 public: 634 virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; } 635 636 WebScreenInfo m_screenInfo; 637 }; 638 639 // Viewport settings need to be set before the page gets loaded 640 static void enableViewportSettings(WebSettings* settings) 641 { 642 settings->setViewportMetaEnabled(true); 643 settings->setViewportEnabled(true); 644 settings->setMainFrameResizesAreOrientationChanges(true); 645 } 646 647 TEST_F(WebFrameTest, FrameViewNeedsLayoutOnFixedLayoutResize) 648 { 649 UseMockScrollbarSettings mockScrollbarSettings; 650 registerMockedHttpURLLoad("fixed_layout.html"); 651 652 FixedLayoutTestWebViewClient client; 653 int viewportWidth = 640; 654 int viewportHeight = 480; 655 656 // Make sure we initialize to minimum scale, even if the window size 657 // only becomes available after the load begins. 658 FrameTestHelpers::WebViewHelper webViewHelper; 659 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 660 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 661 webViewHelper.webView()->layout(); 662 663 webViewHelper.webViewImpl()->setFixedLayoutSize(WebCore::IntSize(100, 100)); 664 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); 665 666 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount(); 667 webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->setFrameRect(WebCore::IntRect(0, 0, 641, 481)); 668 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount()); 669 670 webViewHelper.webViewImpl()->layout(); 671 } 672 673 TEST_F(WebFrameTest, ChangeInFixedLayoutTriggersTextAutosizingRecalculate) 674 { 675 UseMockScrollbarSettings mockScrollbarSettings; 676 registerMockedHttpURLLoad("fixed_layout.html"); 677 678 FixedLayoutTestWebViewClient client; 679 int viewportWidth = 640; 680 int viewportHeight = 480; 681 682 // Make sure we initialize to minimum scale, even if the window size 683 // only becomes available after the load begins. 684 FrameTestHelpers::WebViewHelper webViewHelper; 685 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 686 687 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document(); 688 document->settings()->setTextAutosizingEnabled(true); 689 EXPECT_TRUE(document->settings()->textAutosizingEnabled()); 690 webViewHelper.webViewImpl()->resize(WebSize(viewportWidth, viewportHeight)); 691 webViewHelper.webViewImpl()->layout(); 692 693 WebCore::RenderObject* renderer = document->renderer(); 694 bool multiplierSetAtLeastOnce = false; 695 while (renderer) { 696 if (renderer->style()) { 697 renderer->style()->setTextAutosizingMultiplier(2); 698 EXPECT_EQ(2, renderer->style()->textAutosizingMultiplier()); 699 multiplierSetAtLeastOnce = true; 700 } 701 renderer = renderer->nextInPreOrder(); 702 } 703 EXPECT_TRUE(multiplierSetAtLeastOnce); 704 705 WebCore::ViewportDescription description = document->viewportDescription(); 706 // Choose a width that's not going match the viewport width of the loaded document. 707 description.minWidth = WebCore::Length(100, WebCore::Fixed); 708 description.maxWidth = WebCore::Length(100, WebCore::Fixed); 709 webViewHelper.webViewImpl()->updatePageDefinedViewportConstraints(description); 710 711 bool multiplierCheckedAtLeastOnce = false; 712 renderer = document->renderer(); 713 while (renderer) { 714 if (renderer->style()) { 715 EXPECT_EQ(1, renderer->style()->textAutosizingMultiplier()); 716 multiplierCheckedAtLeastOnce = true; 717 } 718 renderer = renderer->nextInPreOrder(); 719 } 720 EXPECT_TRUE(multiplierCheckedAtLeastOnce); 721 } 722 723 TEST_F(WebFrameTest, FixedLayoutSizeStopsResizeFromChangingLayoutSize) 724 { 725 UseMockScrollbarSettings mockScrollbarSettings; 726 registerMockedHttpURLLoad("fixed_layout.html"); 727 728 int viewportWidth = 640; 729 int viewportHeight = 480; 730 731 int fixedLayoutWidth = viewportWidth / 2; 732 int fixedLayoutHeight = viewportHeight / 2; 733 734 FrameTestHelpers::WebViewHelper webViewHelper; 735 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings); 736 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight)); 737 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 738 webViewHelper.webView()->layout(); 739 740 EXPECT_EQ(fixedLayoutWidth, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().width()); 741 EXPECT_EQ(fixedLayoutHeight, webViewHelper.webViewImpl()->page()->mainFrame()->view()->layoutSize().height()); 742 } 743 744 TEST_F(WebFrameTest, FixedLayoutSizePreventsResizeFromChangingPageScale) 745 { 746 UseMockScrollbarSettings mockScrollbarSettings; 747 registerMockedHttpURLLoad("fixed_layout.html"); 748 749 int viewportWidth = 640; 750 int viewportHeight = 480; 751 752 int fixedLayoutWidth = viewportWidth / 2; 753 int fixedLayoutHeight = viewportHeight / 2; 754 755 FrameTestHelpers::WebViewHelper webViewHelper; 756 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings); 757 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight)); 758 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 759 webViewHelper.webView()->layout(); 760 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor(); 761 762 webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight * 2)); 763 764 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 765 } 766 767 TEST_F(WebFrameTest, FixedLayoutSizePreventsLayoutFromChangingPageScale) 768 { 769 UseMockScrollbarSettings mockScrollbarSettings; 770 registerMockedHttpURLLoad("fixed_layout.html"); 771 772 int viewportWidth = 640; 773 int viewportHeight = 480; 774 775 int fixedLayoutWidth = viewportWidth * 2; 776 int fixedLayoutHeight = viewportHeight * 2; 777 778 FrameTestHelpers::WebViewHelper webViewHelper; 779 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, 0, enableViewportSettings); 780 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight)); 781 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 782 webViewHelper.webView()->layout(); 783 float pageScaleFactor = webViewHelper.webView()->pageScaleFactor(); 784 785 webViewHelper.webView()->setFixedLayoutSize(WebSize(fixedLayoutWidth, fixedLayoutHeight)); 786 webViewHelper.webView()->layout(); 787 788 EXPECT_EQ(pageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 789 } 790 791 TEST_F(WebFrameTest, PreferredSizeAndContentSizeReportedCorrectlyWithZeroHeightFixedLayout) 792 { 793 UseMockScrollbarSettings mockScrollbarSettings; 794 registerMockedHttpURLLoad("200-by-300.html"); 795 796 int windowWidth = 100; 797 int windowHeight = 100; 798 int viewportWidth = 100; 799 int viewportHeight = 0; 800 int divWidth = 200; 801 int divHeight = 300; 802 803 FixedLayoutTestWebViewClient client; 804 client.m_screenInfo.deviceScaleFactor = 1; 805 806 FrameTestHelpers::WebViewHelper webViewHelper; 807 webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings); 808 webViewHelper.webView()->resize(WebSize(windowWidth, windowHeight)); 809 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight)); 810 webViewHelper.webView()->layout(); 811 812 EXPECT_EQ(divWidth, webViewHelper.webView()->mainFrame()->contentsSize().width); 813 EXPECT_EQ(divHeight, webViewHelper.webView()->mainFrame()->contentsSize().height); 814 815 EXPECT_EQ(divWidth, webViewHelper.webView()->contentsPreferredMinimumSize().width); 816 EXPECT_EQ(divHeight, webViewHelper.webView()->contentsPreferredMinimumSize().height); 817 } 818 819 TEST_F(WebFrameTest, DisablingFixedLayoutSizeSetsCorrectLayoutSize) 820 { 821 UseMockScrollbarSettings mockScrollbarSettings; 822 registerMockedHttpURLLoad("no_viewport_tag.html"); 823 824 FixedLayoutTestWebViewClient client; 825 client.m_screenInfo.deviceScaleFactor = 1; 826 int viewportWidth = 640; 827 int viewportHeight = 480; 828 829 FrameTestHelpers::WebViewHelper webViewHelper; 830 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings); 831 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 832 webViewHelper.webView()->settings()->setUseWideViewport(true); 833 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 834 835 webViewHelper.webView()->setFixedLayoutSize(WebSize(viewportWidth, viewportHeight)); 836 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); 837 webViewHelper.webView()->layout(); 838 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 839 840 webViewHelper.webView()->setFixedLayoutSize(WebSize(0, 0)); 841 EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); 842 webViewHelper.webView()->layout(); 843 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 844 } 845 846 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored) 847 { 848 UseMockScrollbarSettings mockScrollbarSettings; 849 850 FixedLayoutTestWebViewClient client; 851 client.m_screenInfo.deviceScaleFactor = 1; 852 int viewportWidth = 1280; 853 int viewportHeight = 0; 854 855 FrameTestHelpers::WebViewHelper webViewHelper; 856 webViewHelper.initialize(true, 0, &client, enableViewportSettings); 857 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 858 859 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 860 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); 861 } 862 863 TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag) 864 { 865 UseMockScrollbarSettings mockScrollbarSettings; 866 registerMockedHttpURLLoad("no_viewport_tag.html"); 867 868 int viewportWidth = 640; 869 int viewportHeight = 480; 870 871 FixedLayoutTestWebViewClient client; 872 client.m_screenInfo.deviceScaleFactor = 2; 873 874 FrameTestHelpers::WebViewHelper webViewHelper; 875 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings); 876 877 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 878 webViewHelper.webView()->layout(); 879 880 EXPECT_EQ(2, webViewHelper.webView()->deviceScaleFactor()); 881 882 // Device scale factor should be independent of page scale. 883 webViewHelper.webView()->setPageScaleFactorLimits(1, 2); 884 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(0.5); 885 webViewHelper.webView()->layout(); 886 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor()); 887 888 // Force the layout to happen before leaving the test. 889 webViewHelper.webView()->mainFrame()->contentAsText(1024).utf8(); 890 } 891 892 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale) 893 { 894 UseMockScrollbarSettings mockScrollbarSettings; 895 896 registerMockedHttpURLLoad("fixed_layout.html"); 897 898 FixedLayoutTestWebViewClient client; 899 client.m_screenInfo.deviceScaleFactor = 1; 900 int viewportWidth = 640; 901 int viewportHeight = 480; 902 903 // Make sure we initialize to minimum scale, even if the window size 904 // only becomes available after the load begins. 905 FrameTestHelpers::WebViewHelper webViewHelper; 906 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 907 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 908 909 int defaultFixedLayoutWidth = 980; 910 float minimumPageScaleFactor = viewportWidth / (float) defaultFixedLayoutWidth; 911 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 912 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor()); 913 914 // Assume the user has pinch zoomed to page scale factor 2. 915 float userPinchPageScaleFactor = 2; 916 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor); 917 webViewHelper.webView()->layout(); 918 919 // Make sure we don't reset to initial scale if the page continues to load. 920 webViewHelper.webViewImpl()->didCommitLoad(false, false); 921 webViewHelper.webViewImpl()->didChangeContentsSize(); 922 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 923 924 // Make sure we don't reset to initial scale if the viewport size changes. 925 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100)); 926 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 927 } 928 929 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale) 930 { 931 UseMockScrollbarSettings mockScrollbarSettings; 932 933 registerMockedHttpURLLoad("wide_document.html"); 934 935 FixedLayoutTestWebViewClient client; 936 client.m_screenInfo.deviceScaleFactor = 1; 937 int viewportWidth = 640; 938 int viewportHeight = 480; 939 940 // Make sure we initialize to minimum scale, even if the window size 941 // only becomes available after the load begins. 942 FrameTestHelpers::WebViewHelper webViewHelper; 943 webViewHelper.initializeAndLoad(m_baseURL + "wide_document.html", true, 0, &client, enableViewportSettings); 944 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 945 946 int wideDocumentWidth = 1500; 947 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth; 948 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 949 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor()); 950 951 // Assume the user has pinch zoomed to page scale factor 2. 952 float userPinchPageScaleFactor = 2; 953 webViewHelper.webView()->setPageScaleFactorPreservingScrollOffset(userPinchPageScaleFactor); 954 webViewHelper.webView()->layout(); 955 956 // Make sure we don't reset to initial scale if the page continues to load. 957 webViewHelper.webViewImpl()->didCommitLoad(false, false); 958 webViewHelper.webViewImpl()->didChangeContentsSize(); 959 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 960 961 // Make sure we don't reset to initial scale if the viewport size changes. 962 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight + 100)); 963 EXPECT_EQ(userPinchPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 964 } 965 966 TEST_F(WebFrameTest, DelayedViewportInitialScale) 967 { 968 UseMockScrollbarSettings mockScrollbarSettings; 969 registerMockedHttpURLLoad("viewport-auto-initial-scale.html"); 970 971 FixedLayoutTestWebViewClient client; 972 client.m_screenInfo.deviceScaleFactor = 1; 973 int viewportWidth = 640; 974 int viewportHeight = 480; 975 976 FrameTestHelpers::WebViewHelper webViewHelper; 977 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings); 978 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 979 980 EXPECT_EQ(0.25f, webViewHelper.webView()->pageScaleFactor()); 981 982 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document(); 983 WebCore::ViewportDescription description = document->viewportDescription(); 984 description.zoom = 2; 985 document->setViewportDescription(description); 986 webViewHelper.webView()->layout(); 987 EXPECT_EQ(2, webViewHelper.webView()->pageScaleFactor()); 988 } 989 990 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse) 991 { 992 UseMockScrollbarSettings mockScrollbarSettings; 993 registerMockedHttpURLLoad("viewport-auto-initial-scale.html"); 994 995 FixedLayoutTestWebViewClient client; 996 client.m_screenInfo.deviceScaleFactor = 1; 997 int viewportWidth = 640; 998 int viewportHeight = 480; 999 1000 FrameTestHelpers::WebViewHelper webViewHelper; 1001 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings); 1002 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1003 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1004 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1005 1006 // The page must be displayed at 100% zoom. 1007 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor()); 1008 } 1009 1010 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport) 1011 { 1012 UseMockScrollbarSettings mockScrollbarSettings; 1013 registerMockedHttpURLLoad("large-div.html"); 1014 1015 FixedLayoutTestWebViewClient client; 1016 client.m_screenInfo.deviceScaleFactor = 1; 1017 int viewportWidth = 640; 1018 int viewportHeight = 480; 1019 1020 FrameTestHelpers::WebViewHelper webViewHelper; 1021 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings); 1022 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1023 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1024 webViewHelper.webView()->settings()->setUseWideViewport(false); 1025 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1026 1027 // The page must be displayed at 100% zoom, despite that it hosts a wide div element. 1028 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor()); 1029 } 1030 1031 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth) 1032 { 1033 UseMockScrollbarSettings mockScrollbarSettings; 1034 registerMockedHttpURLLoad("viewport-auto-initial-scale.html"); 1035 1036 FixedLayoutTestWebViewClient client; 1037 client.m_screenInfo.deviceScaleFactor = 1; 1038 int viewportWidth = 640; 1039 int viewportHeight = 480; 1040 1041 FrameTestHelpers::WebViewHelper webViewHelper; 1042 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings); 1043 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1044 webViewHelper.webView()->settings()->setUseWideViewport(false); 1045 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1046 1047 // The page sets viewport width to 3000, but with UseWideViewport == false is must be ignored. 1048 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1049 EXPECT_EQ(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height()); 1050 } 1051 1052 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale) 1053 { 1054 UseMockScrollbarSettings mockScrollbarSettings; 1055 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html"); 1056 1057 FixedLayoutTestWebViewClient client; 1058 client.m_screenInfo.deviceScaleFactor = 1; 1059 int viewportWidth = 640; 1060 int viewportHeight = 480; 1061 1062 FrameTestHelpers::WebViewHelper webViewHelper; 1063 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings); 1064 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1065 webViewHelper.webView()->settings()->setUseWideViewport(false); 1066 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1067 1068 // The page sets viewport width to 3000, but with UseWideViewport == false it must be ignored. 1069 // While the initial scale specified by the page must be accounted. 1070 EXPECT_EQ(viewportWidth / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1071 EXPECT_EQ(viewportHeight / 2, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height()); 1072 } 1073 1074 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag) 1075 { 1076 UseMockScrollbarSettings mockScrollbarSettings; 1077 registerMockedHttpURLLoad("no_viewport_tag.html"); 1078 1079 FixedLayoutTestWebViewClient client; 1080 client.m_screenInfo.deviceScaleFactor = 1; 1081 int viewportWidth = 640; 1082 int viewportHeight = 480; 1083 1084 FrameTestHelpers::WebViewHelper webViewHelper; 1085 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings); 1086 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1087 webViewHelper.webView()->settings()->setUseWideViewport(true); 1088 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1089 1090 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1091 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height()); 1092 } 1093 1094 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta) 1095 { 1096 UseMockScrollbarSettings mockScrollbarSettings; 1097 registerMockedHttpURLLoad("viewport-height-1000.html"); 1098 1099 FixedLayoutTestWebViewClient client; 1100 client.m_screenInfo.deviceScaleFactor = 1; 1101 int viewportWidth = 640; 1102 int viewportHeight = 480; 1103 1104 FrameTestHelpers::WebViewHelper webViewHelper; 1105 webViewHelper.initializeAndLoad(m_baseURL + "viewport-height-1000.html", true, 0, &client, enableViewportSettings); 1106 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1107 webViewHelper.webView()->settings()->setUseWideViewport(false); 1108 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1109 1110 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1111 } 1112 1113 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth) 1114 { 1115 UseMockScrollbarSettings mockScrollbarSettings; 1116 registerMockedHttpURLLoad("viewport-2x-initial-scale.html"); 1117 1118 FixedLayoutTestWebViewClient client; 1119 client.m_screenInfo.deviceScaleFactor = 1; 1120 int viewportWidth = 640; 1121 int viewportHeight = 480; 1122 1123 FrameTestHelpers::WebViewHelper webViewHelper; 1124 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale.html", true, 0, &client, enableViewportSettings); 1125 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1126 webViewHelper.webView()->settings()->setUseWideViewport(true); 1127 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1128 1129 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1130 EXPECT_EQ(980.0 / viewportWidth * viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().height()); 1131 } 1132 1133 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode) 1134 { 1135 UseMockScrollbarSettings mockScrollbarSettings; 1136 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html"); 1137 1138 FixedLayoutTestWebViewClient client; 1139 client.m_screenInfo.deviceScaleFactor = 1; 1140 int viewportWidth = 640; 1141 int viewportHeight = 480; 1142 1143 FrameTestHelpers::WebViewHelper webViewHelper; 1144 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings); 1145 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1146 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1147 1148 // The page must be displayed at 200% zoom, as specified in its viewport meta tag. 1149 EXPECT_EQ(2.0f, webViewHelper.webView()->pageScaleFactor()); 1150 } 1151 1152 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently) 1153 { 1154 UseMockScrollbarSettings mockScrollbarSettings; 1155 1156 registerMockedHttpURLLoad("fixed_layout.html"); 1157 1158 FixedLayoutTestWebViewClient client; 1159 client.m_screenInfo.deviceScaleFactor = 1; 1160 float enforcedPageScaleFactor = 2.0f; 1161 1162 FrameTestHelpers::WebViewHelper webViewHelper; 1163 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 1164 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1165 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1166 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1167 webViewHelper.webView()->layout(); 1168 1169 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1170 1171 int viewportWidth = 640; 1172 int viewportHeight = 480; 1173 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1174 webViewHelper.webView()->layout(); 1175 1176 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1177 1178 webViewHelper.webView()->setInitialPageScaleOverride(-1); 1179 webViewHelper.webView()->layout(); 1180 EXPECT_EQ(1.0, webViewHelper.webView()->pageScaleFactor()); 1181 } 1182 1183 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode) 1184 { 1185 UseMockScrollbarSettings mockScrollbarSettings; 1186 registerMockedHttpURLLoad("viewport-auto-initial-scale.html"); 1187 1188 FixedLayoutTestWebViewClient client; 1189 client.m_screenInfo.deviceScaleFactor = 1; 1190 int viewportWidth = 640; 1191 int viewportHeight = 480; 1192 float enforcedPageScaleFactor = 0.5f; 1193 1194 FrameTestHelpers::WebViewHelper webViewHelper; 1195 webViewHelper.initializeAndLoad(m_baseURL + "viewport-auto-initial-scale.html", true, 0, &client, enableViewportSettings); 1196 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1197 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1198 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1199 1200 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1201 } 1202 1203 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorOverridesPageViewportInitialScale) 1204 { 1205 UseMockScrollbarSettings mockScrollbarSettings; 1206 registerMockedHttpURLLoad("viewport-wide-2x-initial-scale.html"); 1207 1208 FixedLayoutTestWebViewClient client; 1209 client.m_screenInfo.deviceScaleFactor = 1; 1210 int viewportWidth = 640; 1211 int viewportHeight = 480; 1212 float enforcedPageScaleFactor = 0.5f; 1213 1214 FrameTestHelpers::WebViewHelper webViewHelper; 1215 webViewHelper.initializeAndLoad(m_baseURL + "viewport-wide-2x-initial-scale.html", true, 0, &client, enableViewportSettings); 1216 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1217 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1218 1219 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1220 } 1221 1222 TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered) 1223 { 1224 UseMockScrollbarSettings mockScrollbarSettings; 1225 const char* pages[] = { 1226 // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array. 1227 "viewport-device-0.5x-initial-scale.html", 1228 "viewport-initial-scale-1.html", 1229 // These ones do not. 1230 "viewport-auto-initial-scale.html", 1231 "viewport-target-densitydpi-device-and-fixed-width.html" 1232 }; 1233 float pageScaleFactors[] = { 0.5f, 1.0f }; 1234 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) 1235 registerMockedHttpURLLoad(pages[i]); 1236 1237 FixedLayoutTestWebViewClient client; 1238 client.m_screenInfo.deviceScaleFactor = 1; 1239 int viewportWidth = 400; 1240 int viewportHeight = 300; 1241 float enforcedPageScaleFactor = 0.75f; 1242 1243 for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) { 1244 for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) { 1245 FrameTestHelpers::WebViewHelper webViewHelper; 1246 webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings); 1247 webViewHelper.webView()->settings()->setClobberUserAgentInitialScaleQuirk(quirkEnabled); 1248 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1249 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1250 1251 float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor; 1252 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1253 } 1254 } 1255 } 1256 1257 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth) 1258 { 1259 UseMockScrollbarSettings mockScrollbarSettings; 1260 1261 FixedLayoutTestWebViewClient client; 1262 client.m_screenInfo.deviceScaleFactor = 1; 1263 int viewportWidth = 640; 1264 int viewportHeight = 480; 1265 float enforcedPageScaleFactor = 0.5; 1266 1267 FrameTestHelpers::WebViewHelper webViewHelper; 1268 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings); 1269 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1270 webViewHelper.webView()->settings()->setUseWideViewport(false); 1271 webViewHelper.webView()->settings()->setLoadWithOverviewMode(false); 1272 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1273 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1274 1275 EXPECT_EQ(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1276 EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1277 } 1278 1279 TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth) 1280 { 1281 UseMockScrollbarSettings mockScrollbarSettings; 1282 registerMockedHttpURLLoad("viewport-device-0.5x-initial-scale.html"); 1283 1284 FixedLayoutTestWebViewClient client; 1285 client.m_screenInfo.deviceScaleFactor = 1; 1286 int viewportWidth = 640; 1287 int viewportHeight = 480; 1288 1289 FrameTestHelpers::WebViewHelper webViewHelper; 1290 webViewHelper.initializeAndLoad(m_baseURL + "viewport-device-0.5x-initial-scale.html", true, 0, &client, enableViewportSettings); 1291 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1292 webViewHelper.webView()->settings()->setUseWideViewport(true); 1293 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true); 1294 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1295 1296 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1297 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor()); 1298 1299 webViewHelper.webView()->setFixedLayoutSize(WebSize(2000, 1500)); 1300 webViewHelper.webView()->layout(); 1301 EXPECT_EQ(2000, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1302 EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor()); 1303 } 1304 1305 TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale) 1306 { 1307 UseMockScrollbarSettings mockScrollbarSettings; 1308 registerMockedHttpURLLoad("wide_document_width_viewport.html"); 1309 1310 FixedLayoutTestWebViewClient client; 1311 client.m_screenInfo.deviceScaleFactor = 1; 1312 int viewportWidth = 600; 1313 int viewportHeight = 800; 1314 1315 FrameTestHelpers::WebViewHelper webViewHelper; 1316 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings); 1317 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1318 webViewHelper.webView()->settings()->setUseWideViewport(true); 1319 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true); 1320 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1321 1322 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "wide_document_width_viewport.html"); 1323 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1324 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1325 1326 int wideDocumentWidth = 800; 1327 float minimumPageScaleFactor = viewportWidth / (float) wideDocumentWidth; 1328 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1329 EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webView()->minimumPageScaleFactor()); 1330 } 1331 1332 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight) 1333 { 1334 UseMockScrollbarSettings mockScrollbarSettings; 1335 registerMockedHttpURLLoad("viewport-height-1000.html"); 1336 1337 FixedLayoutTestWebViewClient client; 1338 client.m_screenInfo.deviceScaleFactor = 1; 1339 int viewportWidth = 600; 1340 int viewportHeight = 800; 1341 1342 FrameTestHelpers::WebViewHelper webViewHelper; 1343 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings); 1344 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1345 webViewHelper.webView()->settings()->setUseWideViewport(false); 1346 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true); 1347 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1348 1349 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-height-1000.html"); 1350 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1351 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1352 1353 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); 1354 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor()); 1355 } 1356 1357 TEST_F(WebFrameTest, LayoutSize320Quirk) 1358 { 1359 UseMockScrollbarSettings mockScrollbarSettings; 1360 registerMockedHttpURLLoad("viewport/viewport-30.html"); 1361 1362 FixedLayoutTestWebViewClient client; 1363 client.m_screenInfo.deviceScaleFactor = 1; 1364 int viewportWidth = 600; 1365 int viewportHeight = 800; 1366 1367 FrameTestHelpers::WebViewHelper webViewHelper; 1368 webViewHelper.initializeAndLoad("about:blank", true, 0, &client, enableViewportSettings); 1369 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1370 webViewHelper.webView()->settings()->setUseWideViewport(true); 1371 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true); 1372 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1373 1374 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport/viewport-30.html"); 1375 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1376 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1377 1378 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1379 EXPECT_EQ(800, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); 1380 EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor()); 1381 1382 // The magic number to snap to device-width is 320, so test that 321 is 1383 // respected. 1384 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document(); 1385 WebCore::ViewportDescription description = document->viewportDescription(); 1386 description.minWidth = WebCore::Length(321, WebCore::Fixed); 1387 description.maxWidth = WebCore::Length(321, WebCore::Fixed); 1388 document->setViewportDescription(description); 1389 webViewHelper.webView()->layout(); 1390 EXPECT_EQ(321, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1391 1392 description.minWidth = WebCore::Length(320, WebCore::Fixed); 1393 description.maxWidth = WebCore::Length(320, WebCore::Fixed); 1394 document->setViewportDescription(description); 1395 webViewHelper.webView()->layout(); 1396 EXPECT_EQ(600, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1397 } 1398 1399 TEST_F(WebFrameTest, ZeroValuesQuirk) 1400 { 1401 UseMockScrollbarSettings mockScrollbarSettings; 1402 registerMockedHttpURLLoad("viewport-zero-values.html"); 1403 1404 FixedLayoutTestWebViewClient client; 1405 client.m_screenInfo.deviceScaleFactor = 1; 1406 int viewportWidth = 640; 1407 int viewportHeight = 480; 1408 1409 FrameTestHelpers::WebViewHelper webViewHelper; 1410 webViewHelper.initialize(true, 0, &client, enableViewportSettings); 1411 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true); 1412 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1413 webViewHelper.webView()->settings()->setViewportMetaLayoutSizeQuirk(true); 1414 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-zero-values.html"); 1415 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1416 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1417 1418 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1419 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor()); 1420 1421 webViewHelper.webView()->settings()->setUseWideViewport(true); 1422 webViewHelper.webView()->layout(); 1423 EXPECT_EQ(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1424 EXPECT_EQ(1.0f, webViewHelper.webView()->pageScaleFactor()); 1425 } 1426 1427 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling) 1428 { 1429 registerMockedHttpURLLoad("body-overflow-hidden.html"); 1430 1431 FixedLayoutTestWebViewClient client; 1432 client.m_screenInfo.deviceScaleFactor = 1; 1433 int viewportWidth = 640; 1434 int viewportHeight = 480; 1435 1436 FrameTestHelpers::WebViewHelper webViewHelper; 1437 webViewHelper.initialize(true, 0, &client); 1438 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html"); 1439 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1440 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1441 1442 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 1443 EXPECT_FALSE(view->userInputScrollable(WebCore::VerticalScrollbar)); 1444 } 1445 1446 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) 1447 { 1448 registerMockedHttpURLLoad("body-overflow-hidden.html"); 1449 1450 FixedLayoutTestWebViewClient client; 1451 client.m_screenInfo.deviceScaleFactor = 1; 1452 int viewportWidth = 640; 1453 int viewportHeight = 480; 1454 1455 FrameTestHelpers::WebViewHelper webViewHelper; 1456 webViewHelper.initialize(true, 0, &client); 1457 webViewHelper.webView()->settings()->setIgnoreMainFrameOverflowHiddenQuirk(true); 1458 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "body-overflow-hidden.html"); 1459 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1460 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1461 1462 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 1463 EXPECT_TRUE(view->userInputScrollable(WebCore::VerticalScrollbar)); 1464 } 1465 1466 TEST_F(WebFrameTest, NonZeroValuesNoQuirk) 1467 { 1468 UseMockScrollbarSettings mockScrollbarSettings; 1469 registerMockedHttpURLLoad("viewport-nonzero-values.html"); 1470 1471 FixedLayoutTestWebViewClient client; 1472 client.m_screenInfo.deviceScaleFactor = 1; 1473 int viewportWidth = 640; 1474 int viewportHeight = 480; 1475 float expectedPageScaleFactor = 0.5f; 1476 1477 FrameTestHelpers::WebViewHelper webViewHelper; 1478 webViewHelper.initialize(true, 0, &client, enableViewportSettings); 1479 webViewHelper.webView()->settings()->setViewportMetaZeroValuesQuirk(true); 1480 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1481 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "viewport-nonzero-values.html"); 1482 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1483 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1484 1485 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1486 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1487 1488 webViewHelper.webView()->settings()->setUseWideViewport(true); 1489 webViewHelper.webView()->layout(); 1490 EXPECT_EQ(viewportWidth / expectedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width()); 1491 EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); 1492 } 1493 1494 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout) 1495 { 1496 UseMockScrollbarSettings mockScrollbarSettings; 1497 registerMockedHttpURLLoad("fixed_layout.html"); 1498 1499 FixedLayoutTestWebViewClient client; 1500 client.m_screenInfo.deviceScaleFactor = 1; 1501 // Small viewport to ensure there are always scrollbars. 1502 int viewportWidth = 64; 1503 int viewportHeight = 48; 1504 1505 FrameTestHelpers::WebViewHelper webViewHelper; 1506 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 1507 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1508 webViewHelper.webView()->layout(); 1509 1510 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount(); 1511 webViewHelper.webViewImpl()->setPageScaleFactor(3, WebPoint()); 1512 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); 1513 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount()); 1514 } 1515 1516 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout) 1517 { 1518 UseMockScrollbarSettings mockScrollbarSettings; 1519 1520 registerMockedHttpURLLoad("fixed_layout.html"); 1521 1522 FixedLayoutTestWebViewClient client; 1523 client.m_screenInfo.deviceScaleFactor = 1; 1524 int viewportWidth = 640; 1525 int viewportHeight = 480; 1526 1527 FrameTestHelpers::WebViewHelper webViewHelper; 1528 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 1529 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1530 webViewHelper.webView()->layout(); 1531 1532 int prevLayoutCount = webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount(); 1533 webViewHelper.webViewImpl()->setPageScaleFactor(30, WebPoint()); 1534 EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); 1535 EXPECT_EQ(prevLayoutCount, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutCount()); 1536 1537 } 1538 1539 TEST_F(WebFrameTest, setPageScaleFactorBeforeFrameHasView) 1540 { 1541 registerMockedHttpURLLoad("fixed_layout.html"); 1542 1543 float pageScaleFactor = 3; 1544 FrameTestHelpers::WebViewHelper webViewHelper; 1545 webViewHelper.initializeAndLoad("about:html", true, 0, 0); 1546 webViewHelper.webView()->setPageScaleFactor(pageScaleFactor, WebPoint()); 1547 1548 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html"); 1549 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 1550 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 1551 EXPECT_EQ(pageScaleFactor, view->visibleContentScaleFactor()); 1552 } 1553 1554 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem) 1555 { 1556 UseMockScrollbarSettings mockScrollbarSettings; 1557 registerMockedHttpURLLoad("fixed_layout.html"); 1558 1559 FixedLayoutTestWebViewClient client; 1560 client.m_screenInfo.deviceScaleFactor = 1; 1561 int viewportWidth = 640; 1562 int viewportHeight = 480; 1563 1564 FrameTestHelpers::WebViewHelper webViewHelper; 1565 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 1566 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1567 webViewHelper.webView()->layout(); 1568 1569 webViewHelper.webView()->setPageScaleFactor(3, WebPoint()); 1570 webViewHelper.webViewImpl()->page()->mainFrame()->loader().saveDocumentAndScrollState(); 1571 webViewHelper.webView()->setPageScaleFactor(1, WebPoint()); 1572 webViewHelper.webViewImpl()->page()->mainFrame()->loader().setLoadType(WebCore::FrameLoadTypeBackForward); 1573 webViewHelper.webViewImpl()->page()->mainFrame()->loader().restoreScrollPositionAndViewState(); 1574 EXPECT_EQ(3, webViewHelper.webView()->pageScaleFactor()); 1575 } 1576 1577 TEST_F(WebFrameTest, pageScaleFactorShrinksViewport) 1578 { 1579 UseMockScrollbarSettings mockScrollbarSettings; 1580 registerMockedHttpURLLoad("large-div.html"); 1581 1582 FixedLayoutTestWebViewClient client; 1583 client.m_screenInfo.deviceScaleFactor = 1; 1584 // Small viewport to ensure there are always scrollbars. 1585 int viewportWidth = 64; 1586 int viewportHeight = 48; 1587 1588 FrameTestHelpers::WebViewHelper webViewHelper; 1589 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings); 1590 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1591 webViewHelper.webView()->layout(); 1592 1593 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 1594 int viewportWidthMinusScrollbar = viewportWidth - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15); 1595 int viewportHeightMinusScrollbar = viewportHeight - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15); 1596 1597 webViewHelper.webView()->setPageScaleFactor(2, WebPoint()); 1598 1599 WebCore::IntSize unscaledSize = view->unscaledVisibleContentSize(WebCore::ScrollableArea::IncludeScrollbars); 1600 EXPECT_EQ(viewportWidth, unscaledSize.width()); 1601 EXPECT_EQ(viewportHeight, unscaledSize.height()); 1602 1603 WebCore::IntSize unscaledSizeMinusScrollbar = view->unscaledVisibleContentSize(WebCore::ScrollableArea::ExcludeScrollbars); 1604 EXPECT_EQ(viewportWidthMinusScrollbar, unscaledSizeMinusScrollbar.width()); 1605 EXPECT_EQ(viewportHeightMinusScrollbar, unscaledSizeMinusScrollbar.height()); 1606 1607 WebCore::IntSize scaledSize = view->visibleContentRect().size(); 1608 EXPECT_EQ(ceil(viewportWidthMinusScrollbar / 2.0), scaledSize.width()); 1609 EXPECT_EQ(ceil(viewportHeightMinusScrollbar / 2.0), scaledSize.height()); 1610 } 1611 1612 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform) 1613 { 1614 UseMockScrollbarSettings mockScrollbarSettings; 1615 registerMockedHttpURLLoad("fixed_layout.html"); 1616 1617 FixedLayoutTestWebViewClient client; 1618 client.m_screenInfo.deviceScaleFactor = 1; 1619 int viewportWidth = 640; 1620 int viewportHeight = 480; 1621 1622 FrameTestHelpers::WebViewHelper webViewHelper; 1623 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 1624 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1625 webViewHelper.webView()->layout(); 1626 1627 webViewHelper.webView()->setPageScaleFactor(2, WebPoint()); 1628 1629 EXPECT_EQ(980, webViewHelper.webViewImpl()->page()->mainFrame()->contentRenderer()->unscaledDocumentRect().width()); 1630 EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width()); 1631 } 1632 1633 TEST_F(WebFrameTest, targetDensityDpiHigh) 1634 { 1635 UseMockScrollbarSettings mockScrollbarSettings; 1636 registerMockedHttpURLLoad("viewport-target-densitydpi-high.html"); 1637 1638 FixedLayoutTestWebViewClient client; 1639 // high-dpi = 240 1640 float targetDpi = 240.0f; 1641 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f }; 1642 int viewportWidth = 640; 1643 int viewportHeight = 480; 1644 1645 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { 1646 float deviceScaleFactor = deviceScaleFactors[i]; 1647 float deviceDpi = deviceScaleFactor * 160.0f; 1648 client.m_screenInfo.deviceScaleFactor = deviceScaleFactor; 1649 1650 FrameTestHelpers::WebViewHelper webViewHelper; 1651 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-high.html", true, 0, &client, enableViewportSettings); 1652 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1653 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1654 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1655 1656 // We need to account for the fact that logical pixels are unconditionally multiplied by deviceScaleFactor to produce 1657 // physical pixels. 1658 float densityDpiScaleRatio = deviceScaleFactor * targetDpi / deviceDpi; 1659 EXPECT_NEAR(viewportWidth * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1660 EXPECT_NEAR(viewportHeight * densityDpiScaleRatio, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1661 EXPECT_NEAR(1.0f / densityDpiScaleRatio, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1662 } 1663 } 1664 1665 TEST_F(WebFrameTest, targetDensityDpiDevice) 1666 { 1667 UseMockScrollbarSettings mockScrollbarSettings; 1668 registerMockedHttpURLLoad("viewport-target-densitydpi-device.html"); 1669 1670 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f }; 1671 1672 FixedLayoutTestWebViewClient client; 1673 int viewportWidth = 640; 1674 int viewportHeight = 480; 1675 1676 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { 1677 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i]; 1678 1679 FrameTestHelpers::WebViewHelper webViewHelper; 1680 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device.html", true, 0, &client, enableViewportSettings); 1681 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1682 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1683 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1684 1685 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1686 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1687 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1688 } 1689 } 1690 1691 TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth) 1692 { 1693 UseMockScrollbarSettings mockScrollbarSettings; 1694 registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html"); 1695 1696 float deviceScaleFactors[] = { 1.0f, 4.0f / 3.0f, 2.0f }; 1697 1698 FixedLayoutTestWebViewClient client; 1699 int viewportWidth = 640; 1700 int viewportHeight = 480; 1701 1702 for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { 1703 client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i]; 1704 1705 FrameTestHelpers::WebViewHelper webViewHelper; 1706 webViewHelper.initializeAndLoad(m_baseURL + "viewport-target-densitydpi-device-and-fixed-width.html", true, 0, &client, enableViewportSettings); 1707 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1708 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1709 webViewHelper.webView()->settings()->setUseWideViewport(true); 1710 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1711 1712 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1713 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1714 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1715 } 1716 } 1717 1718 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) 1719 { 1720 UseMockScrollbarSettings mockScrollbarSettings; 1721 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1.html"); 1722 1723 FixedLayoutTestWebViewClient client; 1724 client.m_screenInfo.deviceScaleFactor = 1.33f; 1725 int viewportWidth = 640; 1726 int viewportHeight = 480; 1727 1728 FrameTestHelpers::WebViewHelper webViewHelper; 1729 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1.html", true, 0, &client, enableViewportSettings); 1730 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1731 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1732 webViewHelper.webView()->settings()->setUseWideViewport(false); 1733 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1734 webViewHelper.webView()->layout(); 1735 1736 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1737 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1738 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1739 } 1740 1741 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) 1742 { 1743 UseMockScrollbarSettings mockScrollbarSettings; 1744 registerMockedHttpURLLoad("viewport-initial-scale-less-than-1-device-width.html"); 1745 1746 FixedLayoutTestWebViewClient client; 1747 client.m_screenInfo.deviceScaleFactor = 1.33f; 1748 int viewportWidth = 640; 1749 int viewportHeight = 480; 1750 1751 FrameTestHelpers::WebViewHelper webViewHelper; 1752 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-less-than-1-device-width.html", true, 0, &client, enableViewportSettings); 1753 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1754 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1755 webViewHelper.webView()->settings()->setUseWideViewport(false); 1756 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1757 webViewHelper.webView()->layout(); 1758 1759 const float pageZoom = 0.25f; 1760 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1761 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor / pageZoom, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1762 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1763 } 1764 1765 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) 1766 { 1767 UseMockScrollbarSettings mockScrollbarSettings; 1768 registerMockedHttpURLLoad("large-div.html"); 1769 1770 FixedLayoutTestWebViewClient client; 1771 int viewportWidth = 640; 1772 int viewportHeight = 480; 1773 float enforcedPageScaleFactor = 5.0f; 1774 1775 FrameTestHelpers::WebViewHelper webViewHelper; 1776 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client, enableViewportSettings); 1777 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1778 webViewHelper.webView()->settings()->setUseWideViewport(false); 1779 webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); 1780 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1781 webViewHelper.webView()->layout(); 1782 1783 EXPECT_NEAR(viewportWidth / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1784 EXPECT_NEAR(viewportHeight / enforcedPageScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1785 EXPECT_NEAR(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1786 } 1787 1788 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale) 1789 { 1790 UseMockScrollbarSettings mockScrollbarSettings; 1791 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html"); 1792 1793 FixedLayoutTestWebViewClient client; 1794 int viewportWidth = 640; 1795 int viewportHeight = 480; 1796 1797 FrameTestHelpers::WebViewHelper webViewHelper; 1798 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings); 1799 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true); 1800 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1801 webViewHelper.webView()->layout(); 1802 1803 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1804 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1805 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1806 } 1807 1808 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport) 1809 { 1810 UseMockScrollbarSettings mockScrollbarSettings; 1811 registerMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html"); 1812 1813 FixedLayoutTestWebViewClient client; 1814 client.m_screenInfo.deviceScaleFactor = 1.33f; 1815 int viewportWidth = 640; 1816 int viewportHeight = 480; 1817 1818 FrameTestHelpers::WebViewHelper webViewHelper; 1819 webViewHelper.initializeAndLoad(m_baseURL + "viewport-initial-scale-and-user-scalable-no.html", true, 0, &client, enableViewportSettings); 1820 webViewHelper.webView()->settings()->setSupportDeprecatedTargetDensityDPI(true); 1821 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true); 1822 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1823 webViewHelper.webView()->settings()->setUseWideViewport(false); 1824 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1825 webViewHelper.webView()->layout(); 1826 1827 EXPECT_NEAR(viewportWidth * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1828 EXPECT_NEAR(viewportHeight * client.m_screenInfo.deviceScaleFactor, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1829 EXPECT_NEAR(1.0f / client.m_screenInfo.deviceScaleFactor, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1830 } 1831 1832 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) 1833 { 1834 UseMockScrollbarSettings mockScrollbarSettings; 1835 registerMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html"); 1836 1837 FixedLayoutTestWebViewClient client; 1838 int viewportWidth = 640; 1839 int viewportHeight = 480; 1840 1841 FrameTestHelpers::WebViewHelper webViewHelper; 1842 webViewHelper.initializeAndLoad(m_baseURL + "viewport-2x-initial-scale-non-user-scalable.html", true, 0, &client, enableViewportSettings); 1843 webViewHelper.webView()->settings()->setViewportMetaNonUserScalableQuirk(true); 1844 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1845 webViewHelper.webView()->settings()->setUseWideViewport(true); 1846 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1847 1848 EXPECT_NEAR(viewportWidth, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().width(), 1.0f); 1849 EXPECT_NEAR(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height(), 1.0f); 1850 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1851 } 1852 1853 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff) 1854 { 1855 UseMockScrollbarSettings mockScrollbarSettings; 1856 registerMockedHttpURLLoad("no_viewport_tag.html"); 1857 1858 FixedLayoutTestWebViewClient client; 1859 int viewportWidth = 640; 1860 int viewportHeight = 480; 1861 1862 FrameTestHelpers::WebViewHelper webViewHelper; 1863 webViewHelper.initializeAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client, enableViewportSettings); 1864 webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); 1865 webViewHelper.webView()->settings()->setUseWideViewport(false); 1866 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 1867 1868 EXPECT_NEAR(1.0f, webViewHelper.webView()->pageScaleFactor(), 0.01f); 1869 EXPECT_NEAR(1.0f, webViewHelper.webView()->minimumPageScaleFactor(), 0.01f); 1870 EXPECT_NEAR(5.0f, webViewHelper.webView()->maximumPageScaleFactor(), 0.01f); 1871 } 1872 1873 class WebFrameResizeTest : public WebFrameTest { 1874 protected: 1875 1876 static WebCore::FloatSize computeRelativeOffset(const WebCore::IntPoint& absoluteOffset, const WebCore::LayoutRect& rect) 1877 { 1878 WebCore::FloatSize relativeOffset = WebCore::FloatPoint(absoluteOffset) - rect.location(); 1879 relativeOffset.scale(1.f / rect.width(), 1.f / rect.height()); 1880 return relativeOffset; 1881 } 1882 1883 void testResizeYieldsCorrectScrollAndScale(const char* url, 1884 const float initialPageScaleFactor, 1885 const WebSize scrollOffset, 1886 const WebSize viewportSize, 1887 const bool shouldScaleRelativeToViewportWidth) { 1888 UseMockScrollbarSettings mockScrollbarSettings; 1889 registerMockedHttpURLLoad(url); 1890 1891 const float aspectRatio = static_cast<float>(viewportSize.width) / viewportSize.height; 1892 1893 FrameTestHelpers::WebViewHelper webViewHelper; 1894 webViewHelper.initializeAndLoad(m_baseURL + url, true, 0, 0, enableViewportSettings); 1895 1896 // Origin scrollOffsets preserved under resize. 1897 { 1898 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height)); 1899 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint()); 1900 ASSERT_EQ(viewportSize, webViewHelper.webViewImpl()->size()); 1901 ASSERT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor()); 1902 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width)); 1903 float expectedPageScaleFactor = initialPageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1); 1904 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f); 1905 EXPECT_EQ(WebSize(), webViewHelper.webViewImpl()->mainFrame()->scrollOffset()); 1906 } 1907 1908 // Resizing just the height should not affect pageScaleFactor or scrollOffset. 1909 { 1910 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height)); 1911 webViewHelper.webViewImpl()->setPageScaleFactor(initialPageScaleFactor, WebPoint(scrollOffset.width, scrollOffset.height)); 1912 webViewHelper.webViewImpl()->layout(); 1913 const WebSize expectedScrollOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset(); 1914 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f)); 1915 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor()); 1916 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset()); 1917 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height * 0.8f)); 1918 EXPECT_EQ(initialPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor()); 1919 EXPECT_EQ(expectedScrollOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset()); 1920 } 1921 1922 // Generic resize preserves scrollOffset relative to anchor node located 1923 // the top center of the screen. 1924 { 1925 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width)); 1926 float pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor(); 1927 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.width, viewportSize.height)); 1928 float expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? aspectRatio : 1); 1929 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f); 1930 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(scrollOffset); 1931 1932 WebCore::IntPoint anchorPoint = WebCore::IntPoint(scrollOffset) + WebCore::IntPoint(viewportSize.width / 2, 0); 1933 RefPtr<WebCore::Node> anchorNode = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->eventHandler().hitTestResultAtPoint(anchorPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent).innerNode(); 1934 ASSERT(anchorNode); 1935 1936 pageScaleFactor = webViewHelper.webViewImpl()->pageScaleFactor(); 1937 const WebCore::FloatSize preResizeRelativeOffset 1938 = computeRelativeOffset(anchorPoint, anchorNode->boundingBox()); 1939 webViewHelper.webViewImpl()->resize(WebSize(viewportSize.height, viewportSize.width)); 1940 WebCore::IntPoint newAnchorPoint = WebCore::IntPoint(webViewHelper.webViewImpl()->mainFrame()->scrollOffset()) + WebCore::IntPoint(viewportSize.height / 2, 0); 1941 const WebCore::FloatSize postResizeRelativeOffset 1942 = computeRelativeOffset(newAnchorPoint, anchorNode->boundingBox()); 1943 EXPECT_NEAR(preResizeRelativeOffset.width(), postResizeRelativeOffset.width(), 0.15f); 1944 expectedPageScaleFactor = pageScaleFactor * (shouldScaleRelativeToViewportWidth ? 1 / aspectRatio : 1); 1945 EXPECT_NEAR(expectedPageScaleFactor, webViewHelper.webViewImpl()->pageScaleFactor(), 0.05f); 1946 } 1947 } 1948 }; 1949 1950 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForWidthEqualsDeviceWidth) 1951 { 1952 // With width=device-width, pageScaleFactor is preserved across resizes as 1953 // long as the content adjusts according to the device-width. 1954 const char* url = "resize_scroll_mobile.html"; 1955 const float initialPageScaleFactor = 1; 1956 const WebSize scrollOffset(0, 50); 1957 const WebSize viewportSize(120, 160); 1958 const bool shouldScaleRelativeToViewportWidth = true; 1959 1960 testResizeYieldsCorrectScrollAndScale( 1961 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth); 1962 } 1963 1964 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedWidth) 1965 { 1966 // With a fixed width, pageScaleFactor scales by the relative change in viewport width. 1967 const char* url = "resize_scroll_fixed_width.html"; 1968 const float initialPageScaleFactor = 2; 1969 const WebSize scrollOffset(0, 200); 1970 const WebSize viewportSize(240, 320); 1971 const bool shouldScaleRelativeToViewportWidth = true; 1972 1973 testResizeYieldsCorrectScrollAndScale( 1974 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth); 1975 } 1976 1977 TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout) 1978 { 1979 // With a fixed layout, pageScaleFactor scales by the relative change in viewport width. 1980 const char* url = "resize_scroll_fixed_layout.html"; 1981 const float initialPageScaleFactor = 2; 1982 const WebSize scrollOffset(200, 400); 1983 const WebSize viewportSize(320, 240); 1984 const bool shouldScaleRelativeToViewportWidth = true; 1985 1986 testResizeYieldsCorrectScrollAndScale( 1987 url, initialPageScaleFactor, scrollOffset, viewportSize, shouldScaleRelativeToViewportWidth); 1988 } 1989 1990 TEST_F(WebFrameTest, pageScaleFactorScalesPaintClip) 1991 { 1992 UseMockScrollbarSettings mockScrollbarSettings; 1993 registerMockedHttpURLLoad("large-div.html"); 1994 1995 FixedLayoutTestWebViewClient client; 1996 client.m_screenInfo.deviceScaleFactor = 1; 1997 int viewportWidth = 50; 1998 int viewportHeight = 50; 1999 2000 FrameTestHelpers::WebViewHelper webViewHelper; 2001 webViewHelper.initializeAndLoad(m_baseURL + "large-div.html", true, 0, &client); 2002 // FIXME: This test breaks if the viewport is enabled before loading the page due to the paint 2003 // calls below not working on composited layers. For some reason, enabling the viewport here 2004 // doesn't cause compositing 2005 webViewHelper.webView()->settings()->setViewportEnabled(true); 2006 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2007 webViewHelper.webView()->layout(); 2008 2009 // Set <1 page scale so that the clip rect should be larger than 2010 // the viewport size as passed into resize(). 2011 webViewHelper.webView()->setPageScaleFactor(0.5, WebPoint()); 2012 2013 SkBitmap bitmap; 2014 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200); 2015 bitmap.allocPixels(); 2016 bitmap.eraseColor(0); 2017 SkCanvas canvas(bitmap); 2018 2019 WebCore::GraphicsContext context(&canvas); 2020 context.setTrackOpaqueRegion(true); 2021 2022 EXPECT_EQ_RECT(WebCore::IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 2023 2024 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 2025 WebCore::IntRect paintRect(0, 0, 200, 200); 2026 view->paint(&context, paintRect); 2027 2028 int viewportWidthMinusScrollbar = 50 - (view->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15); 2029 int viewportHeightMinusScrollbar = 50 - (view->horizontalScrollbar()->isOverlayScrollbar() ? 0 : 15); 2030 WebCore::IntRect clippedRect(0, 0, viewportWidthMinusScrollbar * 2, viewportHeightMinusScrollbar * 2); 2031 EXPECT_EQ_RECT(clippedRect, context.opaqueRegion().asRect()); 2032 } 2033 2034 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars) 2035 { 2036 UseMockScrollbarSettings mockScrollbarSettings; 2037 registerMockedHttpURLLoad("fixed_layout.html"); 2038 2039 FixedLayoutTestWebViewClient client; 2040 client.m_screenInfo.deviceScaleFactor = 1; 2041 int viewportWidth = 640; 2042 int viewportHeight = 480; 2043 2044 FrameTestHelpers::WebViewHelper webViewHelper; 2045 webViewHelper.initializeAndLoad(m_baseURL + "fixed_layout.html", true, 0, &client, enableViewportSettings); 2046 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2047 webViewHelper.webView()->layout(); 2048 2049 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 2050 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width()); 2051 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height()); 2052 2053 webViewHelper.webView()->setPageScaleFactor(10, WebPoint()); 2054 2055 EXPECT_EQ(view->scrollSize(WebCore::HorizontalScrollbar), view->contentsSize().width() - view->visibleContentRect().width()); 2056 EXPECT_EQ(view->scrollSize(WebCore::VerticalScrollbar), view->contentsSize().height() - view->visibleContentRect().height()); 2057 } 2058 2059 TEST_F(WebFrameTest, CanOverrideScaleLimits) 2060 { 2061 UseMockScrollbarSettings mockScrollbarSettings; 2062 2063 registerMockedHttpURLLoad("no_scale_for_you.html"); 2064 2065 FixedLayoutTestWebViewClient client; 2066 client.m_screenInfo.deviceScaleFactor = 1; 2067 int viewportWidth = 640; 2068 int viewportHeight = 480; 2069 2070 FrameTestHelpers::WebViewHelper webViewHelper; 2071 webViewHelper.initializeAndLoad(m_baseURL + "no_scale_for_you.html", true, 0, &client, enableViewportSettings); 2072 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2073 2074 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor()); 2075 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor()); 2076 2077 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(true); 2078 webViewHelper.webView()->layout(); 2079 2080 EXPECT_EQ(1.0f, webViewHelper.webView()->minimumPageScaleFactor()); 2081 EXPECT_EQ(5.0f, webViewHelper.webView()->maximumPageScaleFactor()); 2082 2083 webViewHelper.webView()->setIgnoreViewportTagScaleLimits(false); 2084 webViewHelper.webView()->layout(); 2085 2086 EXPECT_EQ(2.0f, webViewHelper.webView()->minimumPageScaleFactor()); 2087 EXPECT_EQ(2.0f, webViewHelper.webView()->maximumPageScaleFactor()); 2088 } 2089 2090 TEST_F(WebFrameTest, updateOverlayScrollbarLayers) 2091 { 2092 UseMockScrollbarSettings mockScrollbarSettings; 2093 2094 registerMockedHttpURLLoad("large-div.html"); 2095 2096 int viewWidth = 500; 2097 int viewHeight = 500; 2098 2099 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient()); 2100 FrameTestHelpers::WebViewHelper webViewHelper; 2101 webViewHelper.initialize(true, &fakeCompositingWebViewClient->m_fakeWebFrameClient, fakeCompositingWebViewClient.get(), &configueCompositingWebView); 2102 2103 webViewHelper.webView()->resize(WebSize(viewWidth, viewHeight)); 2104 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html"); 2105 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2106 webViewHelper.webView()->layout(); 2107 2108 WebCore::FrameView* view = webViewHelper.webViewImpl()->mainFrameImpl()->frameView(); 2109 EXPECT_TRUE(view->renderView()->compositor()->layerForHorizontalScrollbar()); 2110 EXPECT_TRUE(view->renderView()->compositor()->layerForVerticalScrollbar()); 2111 2112 webViewHelper.webView()->resize(WebSize(viewWidth * 10, viewHeight * 10)); 2113 webViewHelper.webView()->layout(); 2114 EXPECT_FALSE(view->renderView()->compositor()->layerForHorizontalScrollbar()); 2115 EXPECT_FALSE(view->renderView()->compositor()->layerForVerticalScrollbar()); 2116 } 2117 2118 void setScaleAndScrollAndLayout(blink::WebView* webView, WebPoint scroll, float scale) 2119 { 2120 webView->setPageScaleFactor(scale, WebPoint(scroll.x, scroll.y)); 2121 webView->layout(); 2122 } 2123 2124 TEST_F(WebFrameTest, DivAutoZoomParamsTest) 2125 { 2126 registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html"); 2127 2128 const float deviceScaleFactor = 2.0f; 2129 int viewportWidth = 640 / deviceScaleFactor; 2130 int viewportHeight = 1280 / deviceScaleFactor; 2131 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2132 FrameTestHelpers::WebViewHelper webViewHelper; 2133 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html"); 2134 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor); 2135 webViewHelper.webView()->setPageScaleFactorLimits(0.01f, 4); 2136 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0)); 2137 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2138 webViewHelper.webView()->layout(); 2139 2140 WebRect wideDiv(200, 100, 400, 150); 2141 WebRect tallDiv(200, 300, 400, 800); 2142 WebRect doubleTapPointWide(wideDiv.x + 50, wideDiv.y + 50, touchPointPadding, touchPointPadding); 2143 WebRect doubleTapPointTall(tallDiv.x + 50, tallDiv.y + 50, touchPointPadding, touchPointPadding); 2144 WebRect wideBlockBounds; 2145 WebRect tallBlockBounds; 2146 float scale; 2147 WebPoint scroll; 2148 2149 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2150 2151 // Test double-tap zooming into wide div. 2152 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false); 2153 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll); 2154 // The div should horizontally fill the screen (modulo margins), and 2155 // vertically centered (modulo integer rounding). 2156 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1); 2157 EXPECT_NEAR(wideDiv.x, scroll.x, 20); 2158 EXPECT_EQ(0, scroll.y); 2159 2160 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale); 2161 2162 // Test zoom out back to minimum scale. 2163 wideBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointWide, false); 2164 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointWide.x, doubleTapPointWide.y), wideBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll); 2165 2166 scale = webViewHelper.webViewImpl()->minimumPageScaleFactor(); 2167 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), scale); 2168 2169 // Test double-tap zooming into tall div. 2170 tallBlockBounds = webViewHelper.webViewImpl()->computeBlockBounds(doubleTapPointTall, false); 2171 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(doubleTapPointTall.x, doubleTapPointTall.y), tallBlockBounds, touchPointPadding, doubleTapZoomAlreadyLegibleScale, scale, scroll); 2172 // The div should start at the top left of the viewport. 2173 EXPECT_NEAR(viewportWidth / (float) tallDiv.width, scale, 0.1); 2174 EXPECT_NEAR(tallDiv.x, scroll.x, 20); 2175 EXPECT_NEAR(tallDiv.y, scroll.y, 20); 2176 2177 // Test for Non-doubletap scaling 2178 // Test zooming into div. 2179 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(WebPoint(250, 250), webViewHelper.webViewImpl()->computeBlockBounds(WebRect(250, 250, 10, 10), true), 0, doubleTapZoomAlreadyLegibleScale, scale, scroll); 2180 EXPECT_NEAR(viewportWidth / (float) wideDiv.width, scale, 0.1); 2181 } 2182 2183 void simulatePageScale(WebViewImpl* webViewImpl, float& scale) 2184 { 2185 WebCore::IntSize scrollDelta = webViewImpl->fakePageScaleAnimationTargetPositionForTesting() - webViewImpl->mainFrameImpl()->frameView()->scrollPosition(); 2186 float scaleDelta = webViewImpl->fakePageScaleAnimationPageScaleForTesting() / webViewImpl->pageScaleFactor(); 2187 webViewImpl->applyScrollAndScale(scrollDelta, scaleDelta); 2188 scale = webViewImpl->pageScaleFactor(); 2189 } 2190 2191 void simulateMultiTargetZoom(WebViewImpl* webViewImpl, const WebRect& rect, float& scale) 2192 { 2193 if (webViewImpl->zoomToMultipleTargetsRect(rect)) 2194 simulatePageScale(webViewImpl, scale); 2195 } 2196 2197 void simulateDoubleTap(WebViewImpl* webViewImpl, WebPoint& point, float& scale) 2198 { 2199 webViewImpl->animateDoubleTapZoom(point); 2200 EXPECT_TRUE(webViewImpl->fakeDoubleTapAnimationPendingForTesting()); 2201 simulatePageScale(webViewImpl, scale); 2202 } 2203 2204 TEST_F(WebFrameTest, DivAutoZoomWideDivTest) 2205 { 2206 registerMockedHttpURLLoad("get_wide_div_for_auto_zoom_test.html"); 2207 2208 const float deviceScaleFactor = 2.0f; 2209 int viewportWidth = 640 / deviceScaleFactor; 2210 int viewportHeight = 1280 / deviceScaleFactor; 2211 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2212 FrameTestHelpers::WebViewHelper webViewHelper; 2213 webViewHelper.initializeAndLoad(m_baseURL + "get_wide_div_for_auto_zoom_test.html"); 2214 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2215 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4); 2216 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor); 2217 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0)); 2218 webViewHelper.webView()->layout(); 2219 2220 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2221 2222 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2223 2224 WebRect div(0, 100, viewportWidth, 150); 2225 WebPoint point(div.x + 50, div.y + 50); 2226 float scale; 2227 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2228 2229 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale); 2230 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2231 simulateDoubleTap(webViewHelper.webViewImpl(), point, scale); 2232 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2233 } 2234 2235 TEST_F(WebFrameTest, DivAutoZoomVeryTallTest) 2236 { 2237 // When a block is taller than the viewport and a zoom targets a lower part 2238 // of it, then we should keep the target point onscreen instead of snapping 2239 // back up the top of the block. 2240 registerMockedHttpURLLoad("very_tall_div.html"); 2241 2242 const float deviceScaleFactor = 2.0f; 2243 int viewportWidth = 640 / deviceScaleFactor; 2244 int viewportHeight = 1280 / deviceScaleFactor; 2245 FrameTestHelpers::WebViewHelper webViewHelper; 2246 webViewHelper.initializeAndLoad(m_baseURL + "very_tall_div.html", true, 0, 0, enableViewportSettings); 2247 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2248 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4); 2249 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor); 2250 webViewHelper.webView()->setPageScaleFactor(1.0f, WebPoint(0, 0)); 2251 webViewHelper.webView()->layout(); 2252 2253 WebRect div(200, 300, 400, 5000); 2254 WebPoint point(div.x + 50, div.y + 3000); 2255 float scale; 2256 WebPoint scroll; 2257 2258 WebRect blockBounds = webViewHelper.webViewImpl()->computeBlockBounds(WebRect(point.x, point.y, 0, 0), true); 2259 webViewHelper.webViewImpl()->computeScaleAndScrollForBlockRect(point, blockBounds, 0, 1.0f, scale, scroll); 2260 EXPECT_EQ(scale, 1.0f); 2261 EXPECT_EQ(scroll.y, 2660); 2262 } 2263 2264 TEST_F(WebFrameTest, DivAutoZoomMultipleDivsTest) 2265 { 2266 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html"); 2267 2268 const float deviceScaleFactor = 2.0f; 2269 int viewportWidth = 640 / deviceScaleFactor; 2270 int viewportHeight = 1280 / deviceScaleFactor; 2271 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2272 FrameTestHelpers::WebViewHelper webViewHelper; 2273 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html"); 2274 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2275 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4); 2276 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor); 2277 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0)); 2278 webViewHelper.webView()->layout(); 2279 2280 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2281 2282 WebRect topDiv(200, 100, 200, 150); 2283 WebRect bottomDiv(200, 300, 200, 150); 2284 WebPoint topPoint(topDiv.x + 50, topDiv.y + 50); 2285 WebPoint bottomPoint(bottomDiv.x + 50, bottomDiv.y + 50); 2286 float scale; 2287 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2288 2289 // Test double tap on two different divs 2290 // After first zoom, we should go back to minimum page scale with a second double tap. 2291 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale); 2292 EXPECT_FLOAT_EQ(1, scale); 2293 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale); 2294 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2295 2296 // If the user pinch zooms after double tap, a second double tap should zoom back to the div. 2297 simulateDoubleTap(webViewHelper.webViewImpl(), topPoint, scale); 2298 EXPECT_FLOAT_EQ(1, scale); 2299 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 0.6f); 2300 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale); 2301 EXPECT_FLOAT_EQ(1, scale); 2302 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale); 2303 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2304 2305 // If we didn't yet get an auto-zoom update and a second double-tap arrives, should go back to minimum scale. 2306 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2307 webViewHelper.webViewImpl()->animateDoubleTapZoom(topPoint); 2308 EXPECT_TRUE(webViewHelper.webViewImpl()->fakeDoubleTapAnimationPendingForTesting()); 2309 simulateDoubleTap(webViewHelper.webViewImpl(), bottomPoint, scale); 2310 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2311 } 2312 2313 TEST_F(WebFrameTest, DivAutoZoomScaleBoundsTest) 2314 { 2315 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html"); 2316 2317 int viewportWidth = 320; 2318 int viewportHeight = 480; 2319 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2320 FrameTestHelpers::WebViewHelper webViewHelper; 2321 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html"); 2322 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2323 webViewHelper.webView()->setDeviceScaleFactor(1.5f); 2324 webViewHelper.webView()->layout(); 2325 2326 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2327 2328 WebRect div(200, 100, 200, 150); 2329 WebPoint doubleTapPoint(div.x + 50, div.y + 50); 2330 float scale; 2331 2332 // Test double tap scale bounds. 2333 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 2334 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4); 2335 webViewHelper.webView()->layout(); 2336 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2337 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2338 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2339 EXPECT_FLOAT_EQ(1, scale); 2340 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2341 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2342 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2343 EXPECT_FLOAT_EQ(1, scale); 2344 2345 // Zoom in to reset double_tap_zoom_in_effect flag. 2346 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2347 // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale 2348 webViewHelper.webView()->setPageScaleFactorLimits(1.1f, 4); 2349 webViewHelper.webView()->layout(); 2350 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2351 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2352 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2353 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2354 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2355 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2356 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2357 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2358 2359 // Zoom in to reset double_tap_zoom_in_effect flag. 2360 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2361 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale 2362 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4); 2363 webViewHelper.webView()->layout(); 2364 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2365 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2366 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2367 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2368 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2369 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2370 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2371 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2372 } 2373 2374 TEST_F(WebFrameTest, DivAutoZoomScaleFontScaleFactorTest) 2375 { 2376 registerMockedHttpURLLoad("get_scale_bounds_check_for_auto_zoom_test.html"); 2377 2378 int viewportWidth = 320; 2379 int viewportHeight = 480; 2380 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2381 float accessibilityFontScaleFactor = 1.13f; 2382 FrameTestHelpers::WebViewHelper webViewHelper; 2383 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_bounds_check_for_auto_zoom_test.html"); 2384 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2385 webViewHelper.webView()->layout(); 2386 2387 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2388 webViewHelper.webViewImpl()->page()->settings().setTextAutosizingEnabled(true); 2389 webViewHelper.webViewImpl()->page()->settings().setAccessibilityFontScaleFactor(accessibilityFontScaleFactor); 2390 2391 WebRect div(200, 100, 200, 150); 2392 WebPoint doubleTapPoint(div.x + 50, div.y + 50); 2393 float scale; 2394 2395 // Test double tap scale bounds. 2396 // minimumPageScale < doubleTapZoomAlreadyLegibleScale < 1 < accessibilityFontScaleFactor 2397 float legibleScale = accessibilityFontScaleFactor; 2398 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2399 float doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2400 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4); 2401 webViewHelper.webView()->layout(); 2402 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2403 EXPECT_FLOAT_EQ(legibleScale, scale); 2404 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2405 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2406 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2407 EXPECT_FLOAT_EQ(legibleScale, scale); 2408 2409 // Zoom in to reset double_tap_zoom_in_effect flag. 2410 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2411 // 1 < accessibilityFontScaleFactor < minimumPageScale < doubleTapZoomAlreadyLegibleScale 2412 webViewHelper.webView()->setPageScaleFactorLimits(1.0f, 4); 2413 webViewHelper.webView()->layout(); 2414 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2415 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2416 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2417 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2418 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2419 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2420 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2421 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2422 2423 // Zoom in to reset double_tap_zoom_in_effect flag. 2424 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2425 // minimumPageScale < 1 < accessibilityFontScaleFactor < doubleTapZoomAlreadyLegibleScale 2426 webViewHelper.webView()->setPageScaleFactorLimits(0.95f, 4); 2427 webViewHelper.webView()->layout(); 2428 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2429 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2430 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2431 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2432 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2433 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2434 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2435 EXPECT_FLOAT_EQ(doubleTapZoomAlreadyLegibleScale, scale); 2436 2437 // Zoom in to reset double_tap_zoom_in_effect flag. 2438 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.1f); 2439 // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < accessibilityFontScaleFactor 2440 webViewHelper.webView()->setPageScaleFactorLimits(0.9f, 4); 2441 webViewHelper.webView()->layout(); 2442 doubleTapZoomAlreadyLegibleScale = webViewHelper.webViewImpl()->minimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio; 2443 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2444 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2445 EXPECT_FLOAT_EQ(legibleScale, scale); 2446 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2447 EXPECT_FLOAT_EQ(webViewHelper.webViewImpl()->minimumPageScaleFactor(), scale); 2448 simulateDoubleTap(webViewHelper.webViewImpl(), doubleTapPoint, scale); 2449 EXPECT_FLOAT_EQ(legibleScale, scale); 2450 } 2451 2452 TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest) 2453 { 2454 registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html"); 2455 2456 const float deviceScaleFactor = 2.0f; 2457 int viewportWidth = 640 / deviceScaleFactor; 2458 int viewportHeight = 1280 / deviceScaleFactor; 2459 float doubleTapZoomAlreadyLegibleRatio = 1.2f; 2460 FrameTestHelpers::WebViewHelper webViewHelper; 2461 webViewHelper.initializeAndLoad(m_baseURL + "get_multiple_divs_for_auto_zoom_test.html"); 2462 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2463 webViewHelper.webView()->setPageScaleFactorLimits(0.5f, 4); 2464 webViewHelper.webView()->setDeviceScaleFactor(deviceScaleFactor); 2465 webViewHelper.webView()->setPageScaleFactor(0.5f, WebPoint(0, 0)); 2466 webViewHelper.webView()->layout(); 2467 2468 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2469 2470 WebRect viewportRect(0, 0, viewportWidth, viewportHeight); 2471 WebRect topDiv(200, 100, 200, 150); 2472 WebRect bottomDiv(200, 300, 200, 150); 2473 float scale; 2474 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), WebPoint(0, 0), (webViewHelper.webViewImpl()->minimumPageScaleFactor()) * (1 + doubleTapZoomAlreadyLegibleRatio) / 2); 2475 2476 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale); 2477 EXPECT_FLOAT_EQ(1, scale); 2478 simulateMultiTargetZoom(webViewHelper.webViewImpl(), bottomDiv, scale); 2479 EXPECT_FLOAT_EQ(1, scale); 2480 simulateMultiTargetZoom(webViewHelper.webViewImpl(), viewportRect, scale); 2481 EXPECT_FLOAT_EQ(1, scale); 2482 webViewHelper.webViewImpl()->setPageScaleFactor(webViewHelper.webViewImpl()->minimumPageScaleFactor(), WebPoint(0, 0)); 2483 simulateMultiTargetZoom(webViewHelper.webViewImpl(), topDiv, scale); 2484 EXPECT_FLOAT_EQ(1, scale); 2485 } 2486 2487 TEST_F(WebFrameTest, DivScrollIntoEditableTest) 2488 { 2489 registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html"); 2490 2491 int viewportWidth = 450; 2492 int viewportHeight = 300; 2493 float leftBoxRatio = 0.3f; 2494 int caretPadding = 10; 2495 float minReadableCaretHeight = 18.0f; 2496 FrameTestHelpers::WebViewHelper webViewHelper; 2497 webViewHelper.initializeAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html"); 2498 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2499 webViewHelper.webView()->setPageScaleFactorLimits(1, 4); 2500 webViewHelper.webView()->layout(); 2501 webViewHelper.webView()->setDeviceScaleFactor(1.5f); 2502 webViewHelper.webView()->settings()->setAutoZoomFocusedNodeToLegibleScale(true); 2503 2504 webViewHelper.webViewImpl()->enableFakePageScaleAnimationForTesting(true); 2505 2506 WebRect editBoxWithText(200, 200, 250, 20); 2507 WebRect editBoxWithNoText(200, 250, 250, 20); 2508 2509 // Test scrolling the focused node 2510 // The edit box is shorter and narrower than the viewport when legible. 2511 webViewHelper.webView()->advanceFocus(false); 2512 // Set the caret to the end of the input box. 2513 webViewHelper.webView()->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000); 2514 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1); 2515 WebRect rect, caret; 2516 webViewHelper.webViewImpl()->selectionBounds(caret, rect); 2517 2518 float scale; 2519 WebCore::IntPoint scroll; 2520 bool needAnimation; 2521 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation); 2522 EXPECT_TRUE(needAnimation); 2523 // The edit box should be left aligned with a margin for possible label. 2524 int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale; 2525 EXPECT_NEAR(hScroll, scroll.x(), 1); 2526 int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height) / 2; 2527 EXPECT_NEAR(vScroll, scroll.y(), 1); 2528 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1); 2529 2530 // The edit box is wider than the viewport when legible. 2531 viewportWidth = 200; 2532 viewportHeight = 150; 2533 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 2534 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1); 2535 webViewHelper.webViewImpl()->selectionBounds(caret, rect); 2536 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation); 2537 EXPECT_TRUE(needAnimation); 2538 // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned. 2539 hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale; 2540 EXPECT_NEAR(hScroll, scroll.x(), 1); 2541 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1); 2542 2543 setScaleAndScrollAndLayout(webViewHelper.webView(), WebPoint(0, 0), 1); 2544 // Move focus to edit box with text. 2545 webViewHelper.webView()->advanceFocus(false); 2546 webViewHelper.webViewImpl()->selectionBounds(caret, rect); 2547 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation); 2548 EXPECT_TRUE(needAnimation); 2549 // The edit box should be left aligned. 2550 hScroll = editBoxWithNoText.x; 2551 EXPECT_NEAR(hScroll, scroll.x(), 1); 2552 vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2; 2553 EXPECT_NEAR(vScroll, scroll.y(), 1); 2554 EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1); 2555 2556 setScaleAndScrollAndLayout(webViewHelper.webViewImpl(), scroll, scale); 2557 2558 // Move focus back to the first edit box. 2559 webViewHelper.webView()->advanceFocus(true); 2560 webViewHelper.webViewImpl()->computeScaleAndScrollForFocusedNode(webViewHelper.webViewImpl()->focusedElement(), scale, scroll, needAnimation); 2561 // The position should have stayed the same since this box was already on screen with the right scale. 2562 EXPECT_FALSE(needAnimation); 2563 } 2564 2565 class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient { 2566 public: 2567 virtual WebNavigationPolicy decidePolicyForNavigation( 2568 WebFrame*, WebDataSource::ExtraData*, const WebURLRequest&, WebNavigationType, 2569 WebNavigationPolicy defaultPolicy, bool isRedirect) OVERRIDE 2570 { 2571 EXPECT_FALSE(isRedirect); 2572 return WebNavigationPolicyCurrentTab; 2573 } 2574 }; 2575 2576 TEST_F(WebFrameTest, ReloadDoesntSetRedirect) 2577 { 2578 // Test for case in http://crbug.com/73104. Reloading a frame very quickly 2579 // would sometimes call decidePolicyForNavigation with isRedirect=true 2580 registerMockedHttpURLLoad("form.html"); 2581 2582 TestReloadDoesntRedirectWebFrameClient webFrameClient; 2583 FrameTestHelpers::WebViewHelper webViewHelper; 2584 webViewHelper.initializeAndLoad(m_baseURL + "form.html", false, &webFrameClient); 2585 2586 webViewHelper.webView()->mainFrame()->reload(true); 2587 // start reload before request is delivered. 2588 webViewHelper.webView()->mainFrame()->reload(true); 2589 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2590 } 2591 2592 TEST_F(WebFrameTest, ReloadWithOverrideURLPreservesState) 2593 { 2594 const std::string firstURL = "find.html"; 2595 const std::string secondURL = "form.html"; 2596 const std::string thirdURL = "history.html"; 2597 const float pageScaleFactor = 1.1684f; 2598 const int pageWidth = 640; 2599 const int pageHeight = 480; 2600 2601 registerMockedHttpURLLoad(firstURL); 2602 registerMockedHttpURLLoad(secondURL); 2603 registerMockedHttpURLLoad(thirdURL); 2604 2605 FrameTestHelpers::WebViewHelper webViewHelper; 2606 webViewHelper.initializeAndLoad(m_baseURL + firstURL, true); 2607 webViewHelper.webViewImpl()->resize(WebSize(pageWidth, pageHeight)); 2608 webViewHelper.webViewImpl()->mainFrame()->setScrollOffset(WebSize(pageWidth / 4, pageHeight / 4)); 2609 webViewHelper.webViewImpl()->setPageScaleFactorPreservingScrollOffset(pageScaleFactor); 2610 2611 WebSize previousOffset = webViewHelper.webViewImpl()->mainFrame()->scrollOffset(); 2612 float previousScale = webViewHelper.webViewImpl()->pageScaleFactor(); 2613 2614 // Reload the page using the cache. 2615 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + secondURL), false); 2616 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2617 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset()); 2618 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor()); 2619 2620 // Reload the page while ignoring the cache. 2621 webViewHelper.webViewImpl()->mainFrame()->reloadWithOverrideURL(toKURL(m_baseURL + thirdURL), true); 2622 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2623 ASSERT_EQ(previousOffset, webViewHelper.webViewImpl()->mainFrame()->scrollOffset()); 2624 ASSERT_EQ(previousScale, webViewHelper.webViewImpl()->pageScaleFactor()); 2625 } 2626 2627 class TestReloadWhileProvisionalFrameClient : public WebFrameClient { 2628 }; 2629 2630 TEST_F(WebFrameTest, ReloadWhileProvisional) 2631 { 2632 // Test that reloading while the previous load is still pending does not cause the initial 2633 // request to get lost. 2634 registerMockedHttpURLLoad("fixed_layout.html"); 2635 2636 TestReloadWhileProvisionalFrameClient webFrameClient; 2637 FrameTestHelpers::WebViewHelper webViewHelper; 2638 webViewHelper.initialize(false, &webFrameClient); 2639 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "fixed_layout.html"); 2640 // start reload before first request is delivered. 2641 webViewHelper.webView()->mainFrame()->reload(true); 2642 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2643 ASSERT_EQ(WebURL(toKURL(m_baseURL + "fixed_layout.html")), 2644 webViewHelper.webView()->mainFrame()->dataSource()->request().url()); 2645 } 2646 2647 TEST_F(WebFrameTest, AppendRedirects) 2648 { 2649 const std::string firstURL = "about:blank"; 2650 const std::string secondURL = "http://www.test.com"; 2651 2652 FrameTestHelpers::WebViewHelper webViewHelper; 2653 webViewHelper.initializeAndLoad(firstURL, true); 2654 2655 WebDataSource* dataSource = webViewHelper.webView()->mainFrame()->dataSource(); 2656 ASSERT_TRUE(dataSource); 2657 dataSource->appendRedirect(toKURL(secondURL)); 2658 2659 WebVector<WebURL> redirects; 2660 dataSource->redirectChain(redirects); 2661 ASSERT_EQ(2U, redirects.size()); 2662 EXPECT_EQ(toKURL(firstURL), toKURL(redirects[0].spec().data())); 2663 EXPECT_EQ(toKURL(secondURL), toKURL(redirects[1].spec().data())); 2664 } 2665 2666 TEST_F(WebFrameTest, IframeRedirect) 2667 { 2668 registerMockedHttpURLLoad("iframe_redirect.html"); 2669 registerMockedHttpURLLoad("visible_iframe.html"); 2670 2671 FrameTestHelpers::WebViewHelper webViewHelper; 2672 webViewHelper.initializeAndLoad(m_baseURL + "iframe_redirect.html", true); 2673 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); // Load the iframe. 2674 2675 WebFrame* iframe = webViewHelper.webView()->findFrameByName(WebString::fromUTF8("ifr")); 2676 ASSERT_TRUE(iframe); 2677 WebDataSource* iframeDataSource = iframe->dataSource(); 2678 ASSERT_TRUE(iframeDataSource); 2679 WebVector<WebURL> redirects; 2680 iframeDataSource->redirectChain(redirects); 2681 ASSERT_EQ(2U, redirects.size()); 2682 EXPECT_EQ(toKURL("about:blank"), toKURL(redirects[0].spec().data())); 2683 EXPECT_EQ(toKURL("http://www.test.com/visible_iframe.html"), toKURL(redirects[1].spec().data())); 2684 } 2685 2686 TEST_F(WebFrameTest, ClearFocusedNodeTest) 2687 { 2688 registerMockedHttpURLLoad("iframe_clear_focused_node_test.html"); 2689 registerMockedHttpURLLoad("autofocus_input_field_iframe.html"); 2690 2691 FrameTestHelpers::WebViewHelper webViewHelper; 2692 webViewHelper.initializeAndLoad(m_baseURL + "iframe_clear_focused_node_test.html", true); 2693 2694 // Clear the focused node. 2695 webViewHelper.webView()->clearFocusedNode(); 2696 2697 // Now retrieve the FocusedNode and test it should be null. 2698 EXPECT_EQ(0, webViewHelper.webViewImpl()->focusedElement()); 2699 } 2700 2701 // Implementation of WebFrameClient that tracks the v8 contexts that are created 2702 // and destroyed for verification. 2703 class ContextLifetimeTestWebFrameClient : public WebFrameClient { 2704 public: 2705 struct Notification { 2706 public: 2707 Notification(WebFrame* frame, v8::Handle<v8::Context> context, int worldId) 2708 : frame(frame) 2709 , context(context->GetIsolate(), context) 2710 , worldId(worldId) 2711 { 2712 } 2713 2714 ~Notification() 2715 { 2716 context.Reset(); 2717 } 2718 2719 bool Equals(Notification* other) 2720 { 2721 return other && frame == other->frame && context == other->context && worldId == other->worldId; 2722 } 2723 2724 WebFrame* frame; 2725 v8::Persistent<v8::Context> context; 2726 int worldId; 2727 }; 2728 2729 virtual ~ContextLifetimeTestWebFrameClient() 2730 { 2731 reset(); 2732 } 2733 2734 void reset() 2735 { 2736 for (size_t i = 0; i < createNotifications.size(); ++i) 2737 delete createNotifications[i]; 2738 2739 for (size_t i = 0; i < releaseNotifications.size(); ++i) 2740 delete releaseNotifications[i]; 2741 2742 createNotifications.clear(); 2743 releaseNotifications.clear(); 2744 } 2745 2746 std::vector<Notification*> createNotifications; 2747 std::vector<Notification*> releaseNotifications; 2748 2749 private: 2750 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE 2751 { 2752 createNotifications.push_back(new Notification(frame, context, worldId)); 2753 } 2754 2755 virtual void willReleaseScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int worldId) OVERRIDE 2756 { 2757 releaseNotifications.push_back(new Notification(frame, context, worldId)); 2758 } 2759 }; 2760 2761 // TODO(aa): Deflake this test. 2762 TEST_F(WebFrameTest, FLAKY_ContextNotificationsLoadUnload) 2763 { 2764 v8::HandleScope handleScope(v8::Isolate::GetCurrent()); 2765 2766 registerMockedHttpURLLoad("context_notifications_test.html"); 2767 registerMockedHttpURLLoad("context_notifications_test_frame.html"); 2768 2769 // Load a frame with an iframe, make sure we get the right create notifications. 2770 ContextLifetimeTestWebFrameClient webFrameClient; 2771 FrameTestHelpers::WebViewHelper webViewHelper; 2772 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient); 2773 2774 WebFrame* mainFrame = webViewHelper.webView()->mainFrame(); 2775 WebFrame* childFrame = mainFrame->firstChild(); 2776 2777 ASSERT_EQ(2u, webFrameClient.createNotifications.size()); 2778 EXPECT_EQ(0u, webFrameClient.releaseNotifications.size()); 2779 2780 ContextLifetimeTestWebFrameClient::Notification* firstCreateNotification = webFrameClient.createNotifications[0]; 2781 ContextLifetimeTestWebFrameClient::Notification* secondCreateNotification = webFrameClient.createNotifications[1]; 2782 2783 EXPECT_EQ(mainFrame, firstCreateNotification->frame); 2784 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstCreateNotification->context); 2785 EXPECT_EQ(0, firstCreateNotification->worldId); 2786 2787 EXPECT_EQ(childFrame, secondCreateNotification->frame); 2788 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondCreateNotification->context); 2789 EXPECT_EQ(0, secondCreateNotification->worldId); 2790 2791 // Close the view. We should get two release notifications that are exactly the same as the create ones, in reverse order. 2792 webViewHelper.reset(); 2793 2794 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size()); 2795 ContextLifetimeTestWebFrameClient::Notification* firstReleaseNotification = webFrameClient.releaseNotifications[0]; 2796 ContextLifetimeTestWebFrameClient::Notification* secondReleaseNotification = webFrameClient.releaseNotifications[1]; 2797 2798 ASSERT_TRUE(firstCreateNotification->Equals(secondReleaseNotification)); 2799 ASSERT_TRUE(secondCreateNotification->Equals(firstReleaseNotification)); 2800 } 2801 2802 TEST_F(WebFrameTest, ContextNotificationsReload) 2803 { 2804 v8::HandleScope handleScope(v8::Isolate::GetCurrent()); 2805 2806 registerMockedHttpURLLoad("context_notifications_test.html"); 2807 registerMockedHttpURLLoad("context_notifications_test_frame.html"); 2808 2809 ContextLifetimeTestWebFrameClient webFrameClient; 2810 FrameTestHelpers::WebViewHelper webViewHelper; 2811 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient); 2812 2813 // Refresh, we should get two release notifications and two more create notifications. 2814 webViewHelper.webView()->mainFrame()->reload(false); 2815 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 2816 ASSERT_EQ(4u, webFrameClient.createNotifications.size()); 2817 ASSERT_EQ(2u, webFrameClient.releaseNotifications.size()); 2818 2819 // The two release notifications we got should be exactly the same as the first two create notifications. 2820 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) { 2821 EXPECT_TRUE(webFrameClient.releaseNotifications[i]->Equals( 2822 webFrameClient.createNotifications[webFrameClient.createNotifications.size() - 3 - i])); 2823 } 2824 2825 // The last two create notifications should be for the current frames and context. 2826 WebFrame* mainFrame = webViewHelper.webView()->mainFrame(); 2827 WebFrame* childFrame = mainFrame->firstChild(); 2828 ContextLifetimeTestWebFrameClient::Notification* firstRefreshNotification = webFrameClient.createNotifications[2]; 2829 ContextLifetimeTestWebFrameClient::Notification* secondRefreshNotification = webFrameClient.createNotifications[3]; 2830 2831 EXPECT_EQ(mainFrame, firstRefreshNotification->frame); 2832 EXPECT_EQ(mainFrame->mainWorldScriptContext(), firstRefreshNotification->context); 2833 EXPECT_EQ(0, firstRefreshNotification->worldId); 2834 2835 EXPECT_EQ(childFrame, secondRefreshNotification->frame); 2836 EXPECT_EQ(childFrame->mainWorldScriptContext(), secondRefreshNotification->context); 2837 EXPECT_EQ(0, secondRefreshNotification->worldId); 2838 } 2839 2840 TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds) 2841 { 2842 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 2843 v8::HandleScope handleScope(isolate); 2844 2845 registerMockedHttpURLLoad("context_notifications_test.html"); 2846 registerMockedHttpURLLoad("context_notifications_test_frame.html"); 2847 2848 ContextLifetimeTestWebFrameClient webFrameClient; 2849 FrameTestHelpers::WebViewHelper webViewHelper; 2850 webViewHelper.initializeAndLoad(m_baseURL + "context_notifications_test.html", true, &webFrameClient); 2851 2852 // Add an isolated world. 2853 webFrameClient.reset(); 2854 2855 int isolatedWorldId = 42; 2856 WebScriptSource scriptSource("hi!"); 2857 int numSources = 1; 2858 int extensionGroup = 0; 2859 webViewHelper.webView()->mainFrame()->executeScriptInIsolatedWorld(isolatedWorldId, &scriptSource, numSources, extensionGroup); 2860 2861 // We should now have a new create notification. 2862 ASSERT_EQ(1u, webFrameClient.createNotifications.size()); 2863 ContextLifetimeTestWebFrameClient::Notification* notification = webFrameClient.createNotifications[0]; 2864 ASSERT_EQ(isolatedWorldId, notification->worldId); 2865 ASSERT_EQ(webViewHelper.webView()->mainFrame(), notification->frame); 2866 2867 // We don't have an API to enumarate isolated worlds for a frame, but we can at least assert that the context we got is *not* the main world's context. 2868 ASSERT_NE(webViewHelper.webView()->mainFrame()->mainWorldScriptContext(), v8::Local<v8::Context>::New(isolate, notification->context)); 2869 2870 webViewHelper.reset(); 2871 2872 // We should have gotten three release notifications (one for each of the frames, plus one for the isolated context). 2873 ASSERT_EQ(3u, webFrameClient.releaseNotifications.size()); 2874 2875 // And one of them should be exactly the same as the create notification for the isolated context. 2876 int matchCount = 0; 2877 for (size_t i = 0; i < webFrameClient.releaseNotifications.size(); ++i) { 2878 if (webFrameClient.releaseNotifications[i]->Equals(webFrameClient.createNotifications[0])) 2879 ++matchCount; 2880 } 2881 EXPECT_EQ(1, matchCount); 2882 } 2883 2884 TEST_F(WebFrameTest, FindInPage) 2885 { 2886 registerMockedHttpURLLoad("find.html"); 2887 FrameTestHelpers::WebViewHelper webViewHelper; 2888 webViewHelper.initializeAndLoad(m_baseURL + "find.html"); 2889 WebFrame* frame = webViewHelper.webView()->mainFrame(); 2890 const int findIdentifier = 12345; 2891 WebFindOptions options; 2892 2893 // Find in a <div> element. 2894 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0)); 2895 frame->stopFinding(false); 2896 WebRange range = frame->selectionRange(); 2897 EXPECT_EQ(5, range.startOffset()); 2898 EXPECT_EQ(9, range.endOffset()); 2899 EXPECT_TRUE(frame->document().focusedNode().isNull()); 2900 2901 // Find in an <input> value. 2902 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0)); 2903 // Confirm stopFinding(false) sets the selection on the found text. 2904 frame->stopFinding(false); 2905 range = frame->selectionRange(); 2906 ASSERT_FALSE(range.isNull()); 2907 EXPECT_EQ(5, range.startOffset()); 2908 EXPECT_EQ(9, range.endOffset()); 2909 EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName()); 2910 2911 // Find in a <textarea> content. 2912 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0)); 2913 // Confirm stopFinding(false) sets the selection on the found text. 2914 frame->stopFinding(false); 2915 range = frame->selectionRange(); 2916 ASSERT_FALSE(range.isNull()); 2917 EXPECT_EQ(5, range.startOffset()); 2918 EXPECT_EQ(9, range.endOffset()); 2919 EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName()); 2920 2921 // Find in a contentEditable element. 2922 EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0)); 2923 // Confirm stopFinding(false) sets the selection on the found text. 2924 frame->stopFinding(false); 2925 range = frame->selectionRange(); 2926 ASSERT_FALSE(range.isNull()); 2927 EXPECT_EQ(0, range.startOffset()); 2928 EXPECT_EQ(4, range.endOffset()); 2929 // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>. 2930 EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName()); 2931 2932 // Find in <select> content. 2933 EXPECT_FALSE(frame->find(findIdentifier, WebString::fromUTF8("bar5"), options, false, 0)); 2934 // If there are any matches, stopFinding will set the selection on the found text. 2935 // However, we do not expect any matches, so check that the selection is null. 2936 frame->stopFinding(false); 2937 range = frame->selectionRange(); 2938 ASSERT_TRUE(range.isNull()); 2939 } 2940 2941 TEST_F(WebFrameTest, GetContentAsPlainText) 2942 { 2943 FrameTestHelpers::WebViewHelper webViewHelper; 2944 webViewHelper.initializeAndLoad("about:blank", true); 2945 // We set the size because it impacts line wrapping, which changes the 2946 // resulting text value. 2947 webViewHelper.webView()->resize(WebSize(640, 480)); 2948 WebFrame* frame = webViewHelper.webView()->mainFrame(); 2949 2950 // Generate a simple test case. 2951 const char simpleSource[] = "<div>Foo bar</div><div></div>baz"; 2952 WebCore::KURL testURL = toKURL("about:blank"); 2953 frame->loadHTMLString(simpleSource, testURL); 2954 runPendingTasks(); 2955 2956 // Make sure it comes out OK. 2957 const std::string expected("Foo bar\nbaz"); 2958 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max()); 2959 EXPECT_EQ(expected, text.utf8()); 2960 2961 // Try reading the same one with clipping of the text. 2962 const int length = 5; 2963 text = frame->contentAsText(length); 2964 EXPECT_EQ(expected.substr(0, length), text.utf8()); 2965 2966 // Now do a new test with a subframe. 2967 const char outerFrameSource[] = "Hello<iframe></iframe> world"; 2968 frame->loadHTMLString(outerFrameSource, testURL); 2969 runPendingTasks(); 2970 2971 // Load something into the subframe. 2972 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe")); 2973 ASSERT_TRUE(subframe); 2974 subframe->loadHTMLString("sub<p>text", testURL); 2975 runPendingTasks(); 2976 2977 text = frame->contentAsText(std::numeric_limits<size_t>::max()); 2978 EXPECT_EQ("Hello world\n\nsub\ntext", text.utf8()); 2979 2980 // Get the frame text where the subframe separator falls on the boundary of 2981 // what we'll take. There used to be a crash in this case. 2982 text = frame->contentAsText(12); 2983 EXPECT_EQ("Hello world", text.utf8()); 2984 } 2985 2986 TEST_F(WebFrameTest, GetFullHtmlOfPage) 2987 { 2988 FrameTestHelpers::WebViewHelper webViewHelper; 2989 webViewHelper.initializeAndLoad("about:blank", true); 2990 WebFrame* frame = webViewHelper.webView()->mainFrame(); 2991 2992 // Generate a simple test case. 2993 const char simpleSource[] = "<p>Hello</p><p>World</p>"; 2994 WebCore::KURL testURL = toKURL("about:blank"); 2995 frame->loadHTMLString(simpleSource, testURL); 2996 runPendingTasks(); 2997 2998 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max()); 2999 EXPECT_EQ("Hello\n\nWorld", text.utf8()); 3000 3001 const std::string html = frame->contentAsMarkup().utf8(); 3002 3003 // Load again with the output html. 3004 frame->loadHTMLString(WebData(html.c_str(), html.length()), testURL); 3005 runPendingTasks(); 3006 3007 EXPECT_EQ(html, frame->contentAsMarkup().utf8()); 3008 3009 text = frame->contentAsText(std::numeric_limits<size_t>::max()); 3010 EXPECT_EQ("Hello\n\nWorld", text.utf8()); 3011 3012 // Test selection check 3013 EXPECT_FALSE(frame->hasSelection()); 3014 frame->executeCommand(WebString::fromUTF8("SelectAll")); 3015 EXPECT_TRUE(frame->hasSelection()); 3016 frame->executeCommand(WebString::fromUTF8("Unselect")); 3017 EXPECT_FALSE(frame->hasSelection()); 3018 WebString selectionHtml = frame->selectionAsMarkup(); 3019 EXPECT_TRUE(selectionHtml.isEmpty()); 3020 } 3021 3022 class TestExecuteScriptDuringDidCreateScriptContext : public WebFrameClient { 3023 public: 3024 virtual void didCreateScriptContext(WebFrame* frame, v8::Handle<v8::Context> context, int extensionGroup, int worldId) OVERRIDE 3025 { 3026 frame->executeScript(WebScriptSource("window.history = 'replaced';")); 3027 } 3028 }; 3029 3030 TEST_F(WebFrameTest, ExecuteScriptDuringDidCreateScriptContext) 3031 { 3032 registerMockedHttpURLLoad("hello_world.html"); 3033 3034 TestExecuteScriptDuringDidCreateScriptContext webFrameClient; 3035 FrameTestHelpers::WebViewHelper webViewHelper; 3036 webViewHelper.initializeAndLoad(m_baseURL + "hello_world.html", true, &webFrameClient); 3037 3038 webViewHelper.webView()->mainFrame()->reload(); 3039 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 3040 } 3041 3042 class TestDidCreateFrameWebFrameClient : public WebFrameClient { 3043 public: 3044 TestDidCreateFrameWebFrameClient() : m_frameCount(0), m_parent(0) 3045 { 3046 } 3047 3048 virtual void didCreateFrame(WebFrame* parent, WebFrame* child) 3049 { 3050 m_frameCount++; 3051 if (!m_parent) 3052 m_parent = parent; 3053 } 3054 3055 int m_frameCount; 3056 WebFrame* m_parent; 3057 }; 3058 3059 TEST_F(WebFrameTest, DidCreateFrame) 3060 { 3061 registerMockedHttpURLLoad("iframes_test.html"); 3062 registerMockedHttpURLLoad("visible_iframe.html"); 3063 registerMockedHttpURLLoad("invisible_iframe.html"); 3064 registerMockedHttpURLLoad("zero_sized_iframe.html"); 3065 3066 TestDidCreateFrameWebFrameClient webFrameClient; 3067 FrameTestHelpers::WebViewHelper webViewHelper; 3068 webViewHelper.initializeAndLoad(m_baseURL + "iframes_test.html", false, &webFrameClient); 3069 3070 EXPECT_EQ(webFrameClient.m_frameCount, 3); 3071 EXPECT_EQ(webFrameClient.m_parent, webViewHelper.webView()->mainFrame()); 3072 } 3073 3074 class FindUpdateWebFrameClient : public WebFrameClient { 3075 public: 3076 FindUpdateWebFrameClient() 3077 : m_findResultsAreReady(false) 3078 , m_count(-1) 3079 { 3080 } 3081 3082 virtual void reportFindInPageMatchCount(int, int count, bool finalUpdate) OVERRIDE 3083 { 3084 m_count = count; 3085 if (finalUpdate) 3086 m_findResultsAreReady = true; 3087 } 3088 3089 bool findResultsAreReady() const { return m_findResultsAreReady; } 3090 int count() const { return m_count; } 3091 3092 private: 3093 bool m_findResultsAreReady; 3094 int m_count; 3095 }; 3096 3097 // This fails on Mac https://bugs.webkit.org/show_bug.cgi?id=108574 3098 #if OS(MACOSX) 3099 TEST_F(WebFrameTest, DISABLED_FindInPageMatchRects) 3100 #else 3101 TEST_F(WebFrameTest, FindInPageMatchRects) 3102 #endif 3103 { 3104 registerMockedHttpURLLoad("find_in_page.html"); 3105 registerMockedHttpURLLoad("find_in_page_frame.html"); 3106 3107 FindUpdateWebFrameClient client; 3108 FrameTestHelpers::WebViewHelper webViewHelper; 3109 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client); 3110 webViewHelper.webView()->resize(WebSize(640, 480)); 3111 webViewHelper.webView()->layout(); 3112 runPendingTasks(); 3113 3114 // Note that the 'result 19' in the <select> element is not expected to produce a match. 3115 static const char* kFindString = "result"; 3116 static const int kFindIdentifier = 12345; 3117 static const int kNumResults = 19; 3118 3119 WebFindOptions options; 3120 WebString searchText = WebString::fromUTF8(kFindString); 3121 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3122 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0)); 3123 3124 mainFrame->resetMatchCount(); 3125 3126 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3127 frame->scopeStringMatches(kFindIdentifier, searchText, options, true); 3128 3129 runPendingTasks(); 3130 EXPECT_TRUE(client.findResultsAreReady()); 3131 3132 WebVector<WebFloatRect> webMatchRects; 3133 mainFrame->findMatchRects(webMatchRects); 3134 ASSERT_EQ(webMatchRects.size(), static_cast<size_t>(kNumResults)); 3135 int rectsVersion = mainFrame->findMatchMarkersVersion(); 3136 3137 for (int resultIndex = 0; resultIndex < kNumResults; ++resultIndex) { 3138 FloatRect resultRect = static_cast<FloatRect>(webMatchRects[resultIndex]); 3139 3140 // Select the match by the center of its rect. 3141 EXPECT_EQ(mainFrame->selectNearestFindMatch(resultRect.center(), 0), resultIndex + 1); 3142 3143 // Check that the find result ordering matches with our expectations. 3144 Range* result = mainFrame->activeMatchFrame()->activeMatch(); 3145 ASSERT_TRUE(result); 3146 result->setEnd(result->endContainer(), result->endOffset() + 3); 3147 EXPECT_EQ(result->text(), String::format("%s %02d", kFindString, resultIndex)); 3148 3149 // Verify that the expected match rect also matches the currently active match. 3150 // Compare the enclosing rects to prevent precision issues caused by CSS transforms. 3151 FloatRect activeMatch = mainFrame->activeFindMatchRect(); 3152 EXPECT_EQ(enclosingIntRect(activeMatch), enclosingIntRect(resultRect)); 3153 3154 // The rects version should not have changed. 3155 EXPECT_EQ(mainFrame->findMatchMarkersVersion(), rectsVersion); 3156 } 3157 3158 // All results after the first two ones should be below between them in find-in-page coordinates. 3159 // This is because results 2 to 9 are inside an iframe located between results 0 and 1. This applies to the fixed div too. 3160 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[1].y); 3161 for (int resultIndex = 2; resultIndex < kNumResults; ++resultIndex) { 3162 EXPECT_TRUE(webMatchRects[0].y < webMatchRects[resultIndex].y); 3163 EXPECT_TRUE(webMatchRects[1].y > webMatchRects[resultIndex].y); 3164 } 3165 3166 // Result 3 should be below both 2 and 4. This is caused by the CSS transform in the containing div. 3167 // If the transform doesn't work then 3 will be between 2 and 4. 3168 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[2].y); 3169 EXPECT_TRUE(webMatchRects[3].y > webMatchRects[4].y); 3170 3171 // Results 6, 7, 8 and 9 should be one below the other in that same order. 3172 // If overflow:scroll is not properly handled then result 8 would be below result 9 or 3173 // result 7 above result 6 depending on the scroll. 3174 EXPECT_TRUE(webMatchRects[6].y < webMatchRects[7].y); 3175 EXPECT_TRUE(webMatchRects[7].y < webMatchRects[8].y); 3176 EXPECT_TRUE(webMatchRects[8].y < webMatchRects[9].y); 3177 3178 // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are inside the table. 3179 EXPECT_TRUE(webMatchRects[11].y > webMatchRects[10].y); 3180 EXPECT_TRUE(webMatchRects[12].y > webMatchRects[10].y); 3181 EXPECT_TRUE(webMatchRects[13].y > webMatchRects[10].y); 3182 EXPECT_TRUE(webMatchRects[14].y > webMatchRects[10].y); 3183 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[15].y); 3184 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[15].y); 3185 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[15].y); 3186 EXPECT_TRUE(webMatchRects[14].y < webMatchRects[15].y); 3187 3188 // Result 11 should be above 12, 13 and 14 as it's in the table header. 3189 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[12].y); 3190 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[13].y); 3191 EXPECT_TRUE(webMatchRects[11].y < webMatchRects[14].y); 3192 3193 // Result 11 should also be right to 12, 13 and 14 because of the colspan. 3194 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[12].x); 3195 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[13].x); 3196 EXPECT_TRUE(webMatchRects[11].x > webMatchRects[14].x); 3197 3198 // Result 12 should be left to results 11, 13 and 14 in the table layout. 3199 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[11].x); 3200 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[13].x); 3201 EXPECT_TRUE(webMatchRects[12].x < webMatchRects[14].x); 3202 3203 // Results 13, 12 and 14 should be one above the other in that order because of the rowspan 3204 // and vertical-align: middle by default. 3205 EXPECT_TRUE(webMatchRects[13].y < webMatchRects[12].y); 3206 EXPECT_TRUE(webMatchRects[12].y < webMatchRects[14].y); 3207 3208 // Result 16 should be below result 15. 3209 EXPECT_TRUE(webMatchRects[15].y > webMatchRects[14].y); 3210 3211 // Result 18 should be normalized with respect to the position:relative div, and not it's 3212 // immediate containing div. Consequently, result 18 should be above result 17. 3213 EXPECT_TRUE(webMatchRects[17].y > webMatchRects[18].y); 3214 3215 // Resizing should update the rects version. 3216 webViewHelper.webView()->resize(WebSize(800, 600)); 3217 runPendingTasks(); 3218 EXPECT_TRUE(mainFrame->findMatchMarkersVersion() != rectsVersion); 3219 } 3220 3221 TEST_F(WebFrameTest, FindInPageSkipsHiddenFrames) 3222 { 3223 registerMockedHttpURLLoad("find_in_hidden_frame.html"); 3224 3225 FindUpdateWebFrameClient client; 3226 FrameTestHelpers::WebViewHelper webViewHelper; 3227 webViewHelper.initializeAndLoad(m_baseURL + "find_in_hidden_frame.html", true, &client); 3228 webViewHelper.webView()->resize(WebSize(640, 480)); 3229 webViewHelper.webView()->layout(); 3230 runPendingTasks(); 3231 3232 static const char* kFindString = "hello"; 3233 static const int kFindIdentifier = 12345; 3234 static const int kNumResults = 1; 3235 3236 WebFindOptions options; 3237 WebString searchText = WebString::fromUTF8(kFindString); 3238 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3239 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0)); 3240 3241 mainFrame->resetMatchCount(); 3242 3243 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3244 frame->scopeStringMatches(kFindIdentifier, searchText, options, true); 3245 3246 runPendingTasks(); 3247 EXPECT_TRUE(client.findResultsAreReady()); 3248 EXPECT_EQ(kNumResults, client.count()); 3249 } 3250 3251 TEST_F(WebFrameTest, FindOnDetachedFrame) 3252 { 3253 registerMockedHttpURLLoad("find_in_page.html"); 3254 registerMockedHttpURLLoad("find_in_page_frame.html"); 3255 3256 FindUpdateWebFrameClient client; 3257 FrameTestHelpers::WebViewHelper webViewHelper; 3258 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client); 3259 webViewHelper.webView()->resize(WebSize(640, 480)); 3260 webViewHelper.webView()->layout(); 3261 runPendingTasks(); 3262 3263 static const char* kFindString = "result"; 3264 static const int kFindIdentifier = 12345; 3265 3266 WebFindOptions options; 3267 WebString searchText = WebString::fromUTF8(kFindString); 3268 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3269 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false)); 3270 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame(); 3271 3272 // Detach the frame before finding. 3273 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove()); 3274 3275 EXPECT_TRUE(mainFrame->find(kFindIdentifier, searchText, options, false, 0)); 3276 EXPECT_FALSE(secondFrame->find(kFindIdentifier, searchText, options, false, 0)); 3277 3278 runPendingTasks(); 3279 EXPECT_FALSE(client.findResultsAreReady()); 3280 3281 mainFrame->resetMatchCount(); 3282 3283 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3284 frame->scopeStringMatches(kFindIdentifier, searchText, options, true); 3285 3286 runPendingTasks(); 3287 EXPECT_TRUE(client.findResultsAreReady()); 3288 3289 holdSecondFrame.release(); 3290 } 3291 3292 TEST_F(WebFrameTest, FindDetachFrameBeforeScopeStrings) 3293 { 3294 registerMockedHttpURLLoad("find_in_page.html"); 3295 registerMockedHttpURLLoad("find_in_page_frame.html"); 3296 3297 FindUpdateWebFrameClient client; 3298 FrameTestHelpers::WebViewHelper webViewHelper; 3299 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client); 3300 webViewHelper.webView()->resize(WebSize(640, 480)); 3301 webViewHelper.webView()->layout(); 3302 runPendingTasks(); 3303 3304 static const char* kFindString = "result"; 3305 static const int kFindIdentifier = 12345; 3306 3307 WebFindOptions options; 3308 WebString searchText = WebString::fromUTF8(kFindString); 3309 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3310 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false)); 3311 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame(); 3312 3313 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3314 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0)); 3315 3316 runPendingTasks(); 3317 EXPECT_FALSE(client.findResultsAreReady()); 3318 3319 // Detach the frame between finding and scoping. 3320 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove()); 3321 3322 mainFrame->resetMatchCount(); 3323 3324 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3325 frame->scopeStringMatches(kFindIdentifier, searchText, options, true); 3326 3327 runPendingTasks(); 3328 EXPECT_TRUE(client.findResultsAreReady()); 3329 3330 holdSecondFrame.release(); 3331 } 3332 3333 TEST_F(WebFrameTest, FindDetachFrameWhileScopingStrings) 3334 { 3335 registerMockedHttpURLLoad("find_in_page.html"); 3336 registerMockedHttpURLLoad("find_in_page_frame.html"); 3337 3338 FindUpdateWebFrameClient client; 3339 FrameTestHelpers::WebViewHelper webViewHelper; 3340 webViewHelper.initializeAndLoad(m_baseURL + "find_in_page.html", true, &client); 3341 webViewHelper.webView()->resize(WebSize(640, 480)); 3342 webViewHelper.webView()->layout(); 3343 runPendingTasks(); 3344 3345 static const char* kFindString = "result"; 3346 static const int kFindIdentifier = 12345; 3347 3348 WebFindOptions options; 3349 WebString searchText = WebString::fromUTF8(kFindString); 3350 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3351 WebFrameImpl* secondFrame = toWebFrameImpl(mainFrame->traverseNext(false)); 3352 RefPtr<WebCore::Frame> holdSecondFrame = secondFrame->frame(); 3353 3354 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3355 EXPECT_TRUE(frame->find(kFindIdentifier, searchText, options, false, 0)); 3356 3357 runPendingTasks(); 3358 EXPECT_FALSE(client.findResultsAreReady()); 3359 3360 mainFrame->resetMatchCount(); 3361 3362 for (WebFrame* frame = mainFrame; frame; frame = frame->traverseNext(false)) 3363 frame->scopeStringMatches(kFindIdentifier, searchText, options, true); 3364 3365 // The first scopeStringMatches will have reset the state. Detach before it actually scopes. 3366 EXPECT_TRUE(mainFrame->document().getElementById("frame").remove()); 3367 3368 runPendingTasks(); 3369 EXPECT_TRUE(client.findResultsAreReady()); 3370 3371 holdSecondFrame.release(); 3372 } 3373 3374 static WebPoint topLeft(const WebRect& rect) 3375 { 3376 return WebPoint(rect.x, rect.y); 3377 } 3378 3379 static WebPoint bottomRightMinusOne(const WebRect& rect) 3380 { 3381 // FIXME: If we don't subtract 1 from the x- and y-coordinates of the 3382 // selection bounds, selectRange() will select the *next* element. That's 3383 // strictly correct, as hit-testing checks the pixel to the lower-right of 3384 // the input coordinate, but it's a wart on the API. 3385 return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1); 3386 } 3387 3388 static WebRect elementBounds(WebFrame* frame, const WebString& id) 3389 { 3390 return frame->document().getElementById(id).boundsInViewportSpace(); 3391 } 3392 3393 static std::string selectionAsString(WebFrame* frame) 3394 { 3395 return frame->selectionAsText().utf8(); 3396 } 3397 3398 TEST_F(WebFrameTest, SelectRange) 3399 { 3400 WebFrame* frame; 3401 WebRect startWebRect; 3402 WebRect endWebRect; 3403 3404 registerMockedHttpURLLoad("select_range_basic.html"); 3405 registerMockedHttpURLLoad("select_range_scroll.html"); 3406 3407 FrameTestHelpers::WebViewHelper webViewHelper; 3408 initializeTextSelectionWebView(m_baseURL + "select_range_basic.html", &webViewHelper); 3409 frame = webViewHelper.webView()->mainFrame(); 3410 EXPECT_EQ("Some test text for testing.", selectionAsString(frame)); 3411 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3412 frame->executeCommand(WebString::fromUTF8("Unselect")); 3413 EXPECT_EQ("", selectionAsString(frame)); 3414 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect)); 3415 EXPECT_EQ("Some test text for testing.", selectionAsString(frame)); 3416 3417 initializeTextSelectionWebView(m_baseURL + "select_range_scroll.html", &webViewHelper); 3418 frame = webViewHelper.webView()->mainFrame(); 3419 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame)); 3420 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3421 frame->executeCommand(WebString::fromUTF8("Unselect")); 3422 EXPECT_EQ("", selectionAsString(frame)); 3423 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect)); 3424 EXPECT_EQ("Some offscreen test text for testing.", selectionAsString(frame)); 3425 } 3426 3427 TEST_F(WebFrameTest, SelectRangeInIframe) 3428 { 3429 WebFrame* frame; 3430 WebRect startWebRect; 3431 WebRect endWebRect; 3432 3433 registerMockedHttpURLLoad("select_range_iframe.html"); 3434 registerMockedHttpURLLoad("select_range_basic.html"); 3435 3436 FrameTestHelpers::WebViewHelper webViewHelper; 3437 initializeTextSelectionWebView(m_baseURL + "select_range_iframe.html", &webViewHelper); 3438 frame = webViewHelper.webView()->mainFrame(); 3439 WebFrame* subframe = frame->findChildByExpression(WebString::fromUTF8("/html/body/iframe")); 3440 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe)); 3441 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3442 subframe->executeCommand(WebString::fromUTF8("Unselect")); 3443 EXPECT_EQ("", selectionAsString(subframe)); 3444 subframe->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect)); 3445 EXPECT_EQ("Some test text for testing.", selectionAsString(subframe)); 3446 } 3447 3448 TEST_F(WebFrameTest, SelectRangeDivContentEditable) 3449 { 3450 WebFrame* frame; 3451 WebRect startWebRect; 3452 WebRect endWebRect; 3453 3454 registerMockedHttpURLLoad("select_range_div_editable.html"); 3455 3456 // Select the middle of an editable element, then try to extend the selection to the top of the document. 3457 // The selection range should be clipped to the bounds of the editable element. 3458 FrameTestHelpers::WebViewHelper webViewHelper; 3459 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper); 3460 frame = webViewHelper.webView()->mainFrame(); 3461 EXPECT_EQ("This text is initially selected.", selectionAsString(frame)); 3462 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3463 3464 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0)); 3465 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame)); 3466 3467 // As above, but extending the selection to the bottom of the document. 3468 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper); 3469 frame = webViewHelper.webView()->mainFrame(); 3470 3471 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3472 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect)); 3473 EXPECT_EQ("This text is initially selected.", selectionAsString(frame)); 3474 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3475 3476 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3477 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480)); 3478 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame)); 3479 } 3480 3481 // positionForPoint returns the wrong values for contenteditable spans. See 3482 // http://crbug.com/238334. 3483 TEST_F(WebFrameTest, DISABLED_SelectRangeSpanContentEditable) 3484 { 3485 WebFrame* frame; 3486 WebRect startWebRect; 3487 WebRect endWebRect; 3488 3489 registerMockedHttpURLLoad("select_range_span_editable.html"); 3490 3491 // Select the middle of an editable element, then try to extend the selection to the top of the document. 3492 // The selection range should be clipped to the bounds of the editable element. 3493 FrameTestHelpers::WebViewHelper webViewHelper; 3494 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper); 3495 frame = webViewHelper.webView()->mainFrame(); 3496 EXPECT_EQ("This text is initially selected.", selectionAsString(frame)); 3497 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3498 3499 frame->selectRange(bottomRightMinusOne(endWebRect), WebPoint(0, 0)); 3500 EXPECT_EQ("16-char header. This text is initially selected.", selectionAsString(frame)); 3501 3502 // As above, but extending the selection to the bottom of the document. 3503 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper); 3504 frame = webViewHelper.webView()->mainFrame(); 3505 3506 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3507 frame->selectRange(topLeft(startWebRect), bottomRightMinusOne(endWebRect)); 3508 EXPECT_EQ("This text is initially selected.", selectionAsString(frame)); 3509 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3510 3511 EXPECT_EQ("This text is initially selected.", selectionAsString(frame)); 3512 webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); 3513 frame->selectRange(topLeft(startWebRect), WebPoint(640, 480)); 3514 EXPECT_EQ("This text is initially selected. 16-char footer.", selectionAsString(frame)); 3515 } 3516 3517 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart) 3518 { 3519 registerMockedHttpURLLoad("text_selection.html"); 3520 FrameTestHelpers::WebViewHelper webViewHelper; 3521 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper); 3522 WebFrame* frame = webViewHelper.webView()->mainFrame(); 3523 3524 // Select second span. We can move the start to include the first span. 3525 frame->executeScript(WebScriptSource("selectElement('header_2');")); 3526 EXPECT_EQ("Header 2.", selectionAsString(frame)); 3527 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1"))); 3528 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame)); 3529 3530 // We can move the start and end together. 3531 frame->executeScript(WebScriptSource("selectElement('header_1');")); 3532 EXPECT_EQ("Header 1.", selectionAsString(frame)); 3533 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_1"))); 3534 EXPECT_EQ("", selectionAsString(frame)); 3535 // Selection is a caret, not empty. 3536 EXPECT_FALSE(frame->selectionRange().isNull()); 3537 3538 // We can move the start across the end. 3539 frame->executeScript(WebScriptSource("selectElement('header_1');")); 3540 EXPECT_EQ("Header 1.", selectionAsString(frame)); 3541 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2"))); 3542 EXPECT_EQ(" Header 2.", selectionAsString(frame)); 3543 3544 // Can't extend the selection part-way into an editable element. 3545 frame->executeScript(WebScriptSource("selectElement('footer_2');")); 3546 EXPECT_EQ("Footer 2.", selectionAsString(frame)); 3547 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "editable_2"))); 3548 EXPECT_EQ(" [ Footer 1. Footer 2.", selectionAsString(frame)); 3549 3550 // Can extend the selection completely across editable elements. 3551 frame->executeScript(WebScriptSource("selectElement('footer_2');")); 3552 EXPECT_EQ("Footer 2.", selectionAsString(frame)); 3553 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "footer_2")), topLeft(elementBounds(frame, "header_2"))); 3554 EXPECT_EQ("Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1. Footer 2.", selectionAsString(frame)); 3555 3556 // If the selection is editable text, we can't extend it into non-editable text. 3557 frame->executeScript(WebScriptSource("selectElement('editable_2');")); 3558 EXPECT_EQ("Editable 2.", selectionAsString(frame)); 3559 frame->selectRange(bottomRightMinusOne(elementBounds(frame, "editable_2")), topLeft(elementBounds(frame, "header_2"))); 3560 // positionForPoint returns the wrong values for contenteditable spans. See 3561 // http://crbug.com/238334. 3562 // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame)); 3563 } 3564 3565 TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd) 3566 { 3567 registerMockedHttpURLLoad("text_selection.html"); 3568 FrameTestHelpers::WebViewHelper webViewHelper; 3569 initializeTextSelectionWebView(m_baseURL + "text_selection.html", &webViewHelper); 3570 WebFrame* frame = webViewHelper.webView()->mainFrame(); 3571 3572 // Select first span. We can move the end to include the second span. 3573 frame->executeScript(WebScriptSource("selectElement('header_1');")); 3574 EXPECT_EQ("Header 1.", selectionAsString(frame)); 3575 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "header_2"))); 3576 EXPECT_EQ("Header 1. Header 2.", selectionAsString(frame)); 3577 3578 // We can move the start and end together. 3579 frame->executeScript(WebScriptSource("selectElement('header_2');")); 3580 EXPECT_EQ("Header 2.", selectionAsString(frame)); 3581 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_2"))); 3582 EXPECT_EQ("", selectionAsString(frame)); 3583 // Selection is a caret, not empty. 3584 EXPECT_FALSE(frame->selectionRange().isNull()); 3585 3586 // We can move the end across the start. 3587 frame->executeScript(WebScriptSource("selectElement('header_2');")); 3588 EXPECT_EQ("Header 2.", selectionAsString(frame)); 3589 frame->selectRange(topLeft(elementBounds(frame, "header_2")), topLeft(elementBounds(frame, "header_1"))); 3590 EXPECT_EQ("Header 1. ", selectionAsString(frame)); 3591 3592 // Can't extend the selection part-way into an editable element. 3593 frame->executeScript(WebScriptSource("selectElement('header_1');")); 3594 EXPECT_EQ("Header 1.", selectionAsString(frame)); 3595 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "editable_1"))); 3596 EXPECT_EQ("Header 1. Header 2. ] ", selectionAsString(frame)); 3597 3598 // Can extend the selection completely across editable elements. 3599 frame->executeScript(WebScriptSource("selectElement('header_1');")); 3600 EXPECT_EQ("Header 1.", selectionAsString(frame)); 3601 frame->selectRange(topLeft(elementBounds(frame, "header_1")), bottomRightMinusOne(elementBounds(frame, "footer_1"))); 3602 EXPECT_EQ("Header 1. Header 2. ] [ Editable 1. Editable 2. ] [ Footer 1.", selectionAsString(frame)); 3603 3604 // If the selection is editable text, we can't extend it into non-editable text. 3605 frame->executeScript(WebScriptSource("selectElement('editable_1');")); 3606 EXPECT_EQ("Editable 1.", selectionAsString(frame)); 3607 frame->selectRange(topLeft(elementBounds(frame, "editable_1")), bottomRightMinusOne(elementBounds(frame, "footer_1"))); 3608 // positionForPoint returns the wrong values for contenteditable spans. See 3609 // http://crbug.com/238334. 3610 // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame)); 3611 } 3612 3613 static int computeOffset(WebCore::RenderObject* renderer, int x, int y) 3614 { 3615 return WebCore::VisiblePosition(renderer->positionForPoint(WebCore::LayoutPoint(x, y))).deepEquivalent().computeOffsetInContainerNode(); 3616 } 3617 3618 // positionForPoint returns the wrong values for contenteditable spans. See 3619 // http://crbug.com/238334. 3620 TEST_F(WebFrameTest, DISABLED_PositionForPointTest) 3621 { 3622 registerMockedHttpURLLoad("select_range_span_editable.html"); 3623 FrameTestHelpers::WebViewHelper webViewHelper; 3624 initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper); 3625 WebFrameImpl* mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3626 WebCore::RenderObject* renderer = mainFrame->frame()->selection().rootEditableElement()->renderer(); 3627 EXPECT_EQ(0, computeOffset(renderer, -1, -1)); 3628 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000)); 3629 3630 registerMockedHttpURLLoad("select_range_div_editable.html"); 3631 initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper); 3632 mainFrame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3633 renderer = mainFrame->frame()->selection().rootEditableElement()->renderer(); 3634 EXPECT_EQ(0, computeOffset(renderer, -1, -1)); 3635 EXPECT_EQ(64, computeOffset(renderer, 1000, 1000)); 3636 } 3637 3638 #if !OS(MACOSX) 3639 TEST_F(WebFrameTest, SelectRangeStaysHorizontallyAlignedWhenMoved) 3640 { 3641 registerMockedHttpURLLoad("move_caret.html"); 3642 3643 FrameTestHelpers::WebViewHelper webViewHelper; 3644 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper); 3645 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 3646 3647 WebRect initialStartRect; 3648 WebRect initialEndRect; 3649 WebRect startRect; 3650 WebRect endRect; 3651 3652 frame->executeScript(WebScriptSource("selectRange();")); 3653 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect); 3654 WebPoint movedStart(topLeft(initialStartRect)); 3655 3656 movedStart.y += 40; 3657 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect)); 3658 webViewHelper.webView()->selectionBounds(startRect, endRect); 3659 EXPECT_EQ(startRect, initialStartRect); 3660 EXPECT_EQ(endRect, initialEndRect); 3661 3662 movedStart.y -= 80; 3663 frame->selectRange(movedStart, bottomRightMinusOne(initialEndRect)); 3664 webViewHelper.webView()->selectionBounds(startRect, endRect); 3665 EXPECT_EQ(startRect, initialStartRect); 3666 EXPECT_EQ(endRect, initialEndRect); 3667 3668 WebPoint movedEnd(bottomRightMinusOne(initialEndRect)); 3669 3670 movedEnd.y += 40; 3671 frame->selectRange(topLeft(initialStartRect), movedEnd); 3672 webViewHelper.webView()->selectionBounds(startRect, endRect); 3673 EXPECT_EQ(startRect, initialStartRect); 3674 EXPECT_EQ(endRect, initialEndRect); 3675 3676 movedEnd.y -= 80; 3677 frame->selectRange(topLeft(initialStartRect), movedEnd); 3678 webViewHelper.webView()->selectionBounds(startRect, endRect); 3679 EXPECT_EQ(startRect, initialStartRect); 3680 EXPECT_EQ(endRect, initialEndRect); 3681 } 3682 3683 TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved) 3684 { 3685 WebFrameImpl* frame; 3686 registerMockedHttpURLLoad("move_caret.html"); 3687 3688 FrameTestHelpers::WebViewHelper webViewHelper; 3689 initializeTextSelectionWebView(m_baseURL + "move_caret.html", &webViewHelper); 3690 frame = (WebFrameImpl*)webViewHelper.webView()->mainFrame(); 3691 3692 WebRect initialStartRect; 3693 WebRect initialEndRect; 3694 WebRect startRect; 3695 WebRect endRect; 3696 3697 frame->executeScript(WebScriptSource("selectCaret();")); 3698 webViewHelper.webView()->selectionBounds(initialStartRect, initialEndRect); 3699 WebPoint moveTo(topLeft(initialStartRect)); 3700 3701 moveTo.y += 40; 3702 frame->moveCaretSelection(moveTo); 3703 webViewHelper.webView()->selectionBounds(startRect, endRect); 3704 EXPECT_EQ(startRect, initialStartRect); 3705 EXPECT_EQ(endRect, initialEndRect); 3706 3707 moveTo.y -= 80; 3708 frame->moveCaretSelection(moveTo); 3709 webViewHelper.webView()->selectionBounds(startRect, endRect); 3710 EXPECT_EQ(startRect, initialStartRect); 3711 EXPECT_EQ(endRect, initialEndRect); 3712 } 3713 #endif 3714 3715 class DisambiguationPopupTestWebViewClient : public WebViewClient { 3716 public: 3717 virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) OVERRIDE 3718 { 3719 EXPECT_GE(targetRects.size(), 2u); 3720 m_triggered = true; 3721 return true; 3722 } 3723 3724 bool triggered() const { return m_triggered; } 3725 void resetTriggered() { m_triggered = false; } 3726 bool m_triggered; 3727 }; 3728 3729 static WebGestureEvent fatTap(int x, int y) 3730 { 3731 WebGestureEvent event; 3732 event.type = WebInputEvent::GestureTap; 3733 event.x = x; 3734 event.y = y; 3735 event.data.tap.width = 50; 3736 event.data.tap.height = 50; 3737 return event; 3738 } 3739 3740 TEST_F(WebFrameTest, DisambiguationPopup) 3741 { 3742 const std::string htmlFile = "disambiguation_popup.html"; 3743 registerMockedHttpURLLoad(htmlFile); 3744 3745 DisambiguationPopupTestWebViewClient client; 3746 3747 // Make sure we initialize to minimum scale, even if the window size 3748 // only becomes available after the load begins. 3749 FrameTestHelpers::WebViewHelper webViewHelper; 3750 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client); 3751 webViewHelper.webView()->resize(WebSize(1000, 1000)); 3752 webViewHelper.webView()->layout(); 3753 3754 client.resetTriggered(); 3755 webViewHelper.webView()->handleInputEvent(fatTap(0, 0)); 3756 EXPECT_FALSE(client.triggered()); 3757 3758 client.resetTriggered(); 3759 webViewHelper.webView()->handleInputEvent(fatTap(200, 115)); 3760 EXPECT_FALSE(client.triggered()); 3761 3762 for (int i = 0; i <= 46; i++) { 3763 client.resetTriggered(); 3764 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5)); 3765 3766 int j = i % 10; 3767 if (j >= 7 && j <= 9) 3768 EXPECT_TRUE(client.triggered()); 3769 else 3770 EXPECT_FALSE(client.triggered()); 3771 } 3772 3773 for (int i = 0; i <= 46; i++) { 3774 client.resetTriggered(); 3775 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590)); 3776 3777 int j = i % 10; 3778 if (j >= 7 && j <= 9) 3779 EXPECT_TRUE(client.triggered()); 3780 else 3781 EXPECT_FALSE(client.triggered()); 3782 } 3783 } 3784 3785 TEST_F(WebFrameTest, DisambiguationPopupNoContainer) 3786 { 3787 registerMockedHttpURLLoad("disambiguation_popup_no_container.html"); 3788 3789 DisambiguationPopupTestWebViewClient client; 3790 3791 // Make sure we initialize to minimum scale, even if the window size 3792 // only becomes available after the load begins. 3793 FrameTestHelpers::WebViewHelper webViewHelper; 3794 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_no_container.html", true, 0, &client); 3795 webViewHelper.webView()->resize(WebSize(1000, 1000)); 3796 webViewHelper.webView()->layout(); 3797 3798 client.resetTriggered(); 3799 webViewHelper.webView()->handleInputEvent(fatTap(50, 50)); 3800 EXPECT_FALSE(client.triggered()); 3801 } 3802 3803 TEST_F(WebFrameTest, DisambiguationPopupMobileSite) 3804 { 3805 UseMockScrollbarSettings mockScrollbarSettings; 3806 const std::string htmlFile = "disambiguation_popup_mobile_site.html"; 3807 registerMockedHttpURLLoad(htmlFile); 3808 3809 DisambiguationPopupTestWebViewClient client; 3810 3811 // Make sure we initialize to minimum scale, even if the window size 3812 // only becomes available after the load begins. 3813 FrameTestHelpers::WebViewHelper webViewHelper; 3814 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings); 3815 webViewHelper.webView()->resize(WebSize(1000, 1000)); 3816 webViewHelper.webView()->layout(); 3817 3818 client.resetTriggered(); 3819 webViewHelper.webView()->handleInputEvent(fatTap(0, 0)); 3820 EXPECT_FALSE(client.triggered()); 3821 3822 client.resetTriggered(); 3823 webViewHelper.webView()->handleInputEvent(fatTap(200, 115)); 3824 EXPECT_FALSE(client.triggered()); 3825 3826 for (int i = 0; i <= 46; i++) { 3827 client.resetTriggered(); 3828 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5)); 3829 EXPECT_FALSE(client.triggered()); 3830 } 3831 3832 for (int i = 0; i <= 46; i++) { 3833 client.resetTriggered(); 3834 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590)); 3835 EXPECT_FALSE(client.triggered()); 3836 } 3837 } 3838 3839 TEST_F(WebFrameTest, DisambiguationPopupViewportSite) 3840 { 3841 UseMockScrollbarSettings mockScrollbarSettings; 3842 const std::string htmlFile = "disambiguation_popup_viewport_site.html"; 3843 registerMockedHttpURLLoad(htmlFile); 3844 3845 DisambiguationPopupTestWebViewClient client; 3846 3847 // Make sure we initialize to minimum scale, even if the window size 3848 // only becomes available after the load begins. 3849 FrameTestHelpers::WebViewHelper webViewHelper; 3850 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client, enableViewportSettings); 3851 webViewHelper.webView()->resize(WebSize(1000, 1000)); 3852 webViewHelper.webView()->layout(); 3853 3854 client.resetTriggered(); 3855 webViewHelper.webView()->handleInputEvent(fatTap(0, 0)); 3856 EXPECT_FALSE(client.triggered()); 3857 3858 client.resetTriggered(); 3859 webViewHelper.webView()->handleInputEvent(fatTap(200, 115)); 3860 EXPECT_FALSE(client.triggered()); 3861 3862 for (int i = 0; i <= 46; i++) { 3863 client.resetTriggered(); 3864 webViewHelper.webView()->handleInputEvent(fatTap(120, 230 + i * 5)); 3865 EXPECT_FALSE(client.triggered()); 3866 } 3867 3868 for (int i = 0; i <= 46; i++) { 3869 client.resetTriggered(); 3870 webViewHelper.webView()->handleInputEvent(fatTap(10 + i * 5, 590)); 3871 EXPECT_FALSE(client.triggered()); 3872 } 3873 } 3874 3875 TEST_F(WebFrameTest, DisambiguationPopupBlacklist) 3876 { 3877 const unsigned viewportWidth = 500; 3878 const unsigned viewportHeight = 1000; 3879 const unsigned divHeight = 100; 3880 const std::string htmlFile = "disambiguation_popup_blacklist.html"; 3881 registerMockedHttpURLLoad(htmlFile); 3882 3883 DisambiguationPopupTestWebViewClient client; 3884 3885 // Make sure we initialize to minimum scale, even if the window size 3886 // only becomes available after the load begins. 3887 FrameTestHelpers::WebViewHelper webViewHelper; 3888 webViewHelper.initializeAndLoad(m_baseURL + htmlFile, true, 0, &client); 3889 webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); 3890 webViewHelper.webView()->layout(); 3891 3892 // Click somewhere where the popup shouldn't appear. 3893 client.resetTriggered(); 3894 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, 0)); 3895 EXPECT_FALSE(client.triggered()); 3896 3897 // Click directly in between two container divs with click handlers, with children that don't handle clicks. 3898 client.resetTriggered(); 3899 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight)); 3900 EXPECT_TRUE(client.triggered()); 3901 3902 // The third div container should be blacklisted if you click on the link it contains. 3903 client.resetTriggered(); 3904 webViewHelper.webView()->handleInputEvent(fatTap(viewportWidth / 2, divHeight * 3.25)); 3905 EXPECT_FALSE(client.triggered()); 3906 } 3907 3908 TEST_F(WebFrameTest, DisambiguationPopupPageScale) 3909 { 3910 registerMockedHttpURLLoad("disambiguation_popup_page_scale.html"); 3911 3912 DisambiguationPopupTestWebViewClient client; 3913 3914 // Make sure we initialize to minimum scale, even if the window size 3915 // only becomes available after the load begins. 3916 FrameTestHelpers::WebViewHelper webViewHelper; 3917 webViewHelper.initializeAndLoad(m_baseURL + "disambiguation_popup_page_scale.html", true, 0, &client); 3918 webViewHelper.webView()->resize(WebSize(1000, 1000)); 3919 webViewHelper.webView()->layout(); 3920 3921 client.resetTriggered(); 3922 webViewHelper.webView()->handleInputEvent(fatTap(80, 80)); 3923 EXPECT_TRUE(client.triggered()); 3924 3925 client.resetTriggered(); 3926 webViewHelper.webView()->handleInputEvent(fatTap(230, 190)); 3927 EXPECT_TRUE(client.triggered()); 3928 3929 webViewHelper.webView()->setPageScaleFactor(3.0f, WebPoint(0, 0)); 3930 webViewHelper.webView()->layout(); 3931 3932 client.resetTriggered(); 3933 webViewHelper.webView()->handleInputEvent(fatTap(240, 240)); 3934 EXPECT_TRUE(client.triggered()); 3935 3936 client.resetTriggered(); 3937 webViewHelper.webView()->handleInputEvent(fatTap(690, 570)); 3938 EXPECT_FALSE(client.triggered()); 3939 } 3940 3941 class TestSubstituteDataWebFrameClient : public WebFrameClient { 3942 public: 3943 TestSubstituteDataWebFrameClient() 3944 : m_commitCalled(false) 3945 { 3946 } 3947 3948 virtual void didFailProvisionalLoad(WebFrame* frame, const WebURLError& error) 3949 { 3950 frame->loadHTMLString("This should appear", toKURL("data:text/html,chromewebdata"), error.unreachableURL, true); 3951 runPendingTasks(); 3952 } 3953 3954 virtual void didCommitProvisionalLoad(WebFrame* frame, bool) 3955 { 3956 if (frame->dataSource()->response().url() != WebURL(URLTestHelpers::toKURL("about:blank"))) 3957 m_commitCalled = true; 3958 } 3959 3960 bool commitCalled() const { return m_commitCalled; } 3961 3962 private: 3963 bool m_commitCalled; 3964 }; 3965 3966 TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation) 3967 { 3968 TestSubstituteDataWebFrameClient webFrameClient; 3969 3970 FrameTestHelpers::WebViewHelper webViewHelper; 3971 webViewHelper.initializeAndLoad("about:blank", true, &webFrameClient); 3972 runPendingTasks(); 3973 WebFrame* frame = webViewHelper.webView()->mainFrame(); 3974 3975 // Load a url as a history navigation that will return an error. TestSubstituteDataWebFrameClient 3976 // will start a SubstituteData load in response to the load failure, which should get fully committed. 3977 // Due to https://bugs.webkit.org/show_bug.cgi?id=91685, FrameLoader::didReceiveData() wasn't getting 3978 // called in this case, which resulted in the SubstituteData document not getting displayed. 3979 WebURLError error; 3980 error.reason = 1337; 3981 error.domain = "WebFrameTest"; 3982 std::string errorURL = "http://0.0.0.0"; 3983 WebURLResponse response; 3984 response.initialize(); 3985 response.setURL(URLTestHelpers::toKURL(errorURL)); 3986 response.setMIMEType("text/html"); 3987 response.setHTTPStatusCode(500); 3988 WebHistoryItem errorHistoryItem; 3989 errorHistoryItem.initialize(); 3990 errorHistoryItem.setURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length())); 3991 errorHistoryItem.setOriginalURLString(WebString::fromUTF8(errorURL.c_str(), errorURL.length())); 3992 Platform::current()->unitTestSupport()->registerMockedErrorURL(URLTestHelpers::toKURL(errorURL), response, error); 3993 frame->loadHistoryItem(errorHistoryItem); 3994 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 3995 3996 WebString text = frame->contentAsText(std::numeric_limits<size_t>::max()); 3997 EXPECT_EQ("This should appear", text.utf8()); 3998 EXPECT_TRUE(webFrameClient.commitCalled()); 3999 } 4000 4001 class TestWillInsertBodyWebFrameClient : public WebFrameClient { 4002 public: 4003 TestWillInsertBodyWebFrameClient() : m_numBodies(0), m_didLoad(false) 4004 { 4005 } 4006 4007 virtual void didCommitProvisionalLoad(WebFrame*, bool) OVERRIDE 4008 { 4009 m_numBodies = 0; 4010 m_didLoad = true; 4011 } 4012 4013 virtual void didCreateDocumentElement(WebFrame*) OVERRIDE 4014 { 4015 EXPECT_EQ(0, m_numBodies); 4016 } 4017 4018 virtual void willInsertBody(WebFrame*) OVERRIDE 4019 { 4020 m_numBodies++; 4021 } 4022 4023 int m_numBodies; 4024 bool m_didLoad; 4025 }; 4026 4027 TEST_F(WebFrameTest, HTMLDocument) 4028 { 4029 registerMockedHttpURLLoad("clipped-body.html"); 4030 4031 TestWillInsertBodyWebFrameClient webFrameClient; 4032 FrameTestHelpers::WebViewHelper webViewHelper; 4033 webViewHelper.initializeAndLoad(m_baseURL + "clipped-body.html", false, &webFrameClient); 4034 4035 EXPECT_TRUE(webFrameClient.m_didLoad); 4036 EXPECT_EQ(1, webFrameClient.m_numBodies); 4037 } 4038 4039 TEST_F(WebFrameTest, EmptyDocument) 4040 { 4041 registerMockedHttpURLLoad("pageserializer/green_rectangle.svg"); 4042 4043 TestWillInsertBodyWebFrameClient webFrameClient; 4044 FrameTestHelpers::WebViewHelper webViewHelper; 4045 webViewHelper.initialize(false, &webFrameClient); 4046 4047 EXPECT_FALSE(webFrameClient.m_didLoad); 4048 EXPECT_EQ(1, webFrameClient.m_numBodies); // The empty document that a new frame starts with triggers this. 4049 } 4050 4051 TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection) 4052 { 4053 FrameTestHelpers::WebViewHelper webViewHelper; 4054 webViewHelper.initializeAndLoad("about:blank", true); 4055 WebFrame* frame = webViewHelper.webView()->mainFrame(); 4056 4057 // This test passes if this doesn't crash. 4058 frame->moveCaretSelection(WebPoint(0, 0)); 4059 } 4060 4061 class SpellCheckClient : public WebSpellCheckClient { 4062 public: 4063 explicit SpellCheckClient(uint32_t hash = 0) : m_numberOfTimesChecked(0), m_hash(hash) { } 4064 virtual ~SpellCheckClient() { } 4065 virtual void requestCheckingOfText(const blink::WebString&, const blink::WebVector<uint32_t>&, const blink::WebVector<unsigned>&, blink::WebTextCheckingCompletion* completion) OVERRIDE 4066 { 4067 ++m_numberOfTimesChecked; 4068 Vector<WebTextCheckingResult> results; 4069 const int misspellingStartOffset = 1; 4070 const int misspellingLength = 8; 4071 results.append(WebTextCheckingResult(WebTextDecorationTypeSpelling, misspellingStartOffset, misspellingLength, WebString(), m_hash)); 4072 completion->didFinishCheckingText(results); 4073 } 4074 int numberOfTimesChecked() const { return m_numberOfTimesChecked; } 4075 private: 4076 int m_numberOfTimesChecked; 4077 uint32_t m_hash; 4078 }; 4079 4080 TEST_F(WebFrameTest, ReplaceMisspelledRange) 4081 { 4082 registerMockedHttpURLLoad("spell.html"); 4083 FrameTestHelpers::WebViewHelper webViewHelper; 4084 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4085 SpellCheckClient spellcheck; 4086 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4087 4088 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4089 Document* document = frame->frame()->document(); 4090 Element* element = document->getElementById("data"); 4091 4092 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4093 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4094 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4095 4096 element->focus(); 4097 document->execCommand("InsertText", false, "_wellcome_."); 4098 4099 const int allTextBeginOffset = 0; 4100 const int allTextLength = 11; 4101 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength)); 4102 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange(); 4103 4104 EXPECT_EQ(1, spellcheck.numberOfTimesChecked()); 4105 EXPECT_EQ(1U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size()); 4106 4107 frame->replaceMisspelledRange("welcome"); 4108 EXPECT_EQ("_welcome_.", frame->contentAsText(std::numeric_limits<size_t>::max()).utf8()); 4109 } 4110 4111 TEST_F(WebFrameTest, RemoveSpellingMarkers) 4112 { 4113 registerMockedHttpURLLoad("spell.html"); 4114 FrameTestHelpers::WebViewHelper webViewHelper; 4115 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4116 SpellCheckClient spellcheck; 4117 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4118 4119 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4120 Document* document = frame->frame()->document(); 4121 Element* element = document->getElementById("data"); 4122 4123 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4124 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4125 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4126 4127 element->focus(); 4128 document->execCommand("InsertText", false, "_wellcome_."); 4129 4130 frame->removeSpellingMarkers(); 4131 4132 const int allTextBeginOffset = 0; 4133 const int allTextLength = 11; 4134 frame->selectRange(WebRange::fromDocumentRange(frame, allTextBeginOffset, allTextLength)); 4135 RefPtr<Range> selectionRange = frame->frame()->selection().toNormalizedRange(); 4136 4137 EXPECT_EQ(0U, document->markers()->markersInRange(selectionRange.get(), DocumentMarker::Spelling).size()); 4138 } 4139 4140 TEST_F(WebFrameTest, MarkerHashIdentifiers) { 4141 registerMockedHttpURLLoad("spell.html"); 4142 FrameTestHelpers::WebViewHelper webViewHelper; 4143 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4144 4145 static const uint32_t kHash = 42; 4146 SpellCheckClient spellcheck(kHash); 4147 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4148 4149 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4150 Document* document = frame->frame()->document(); 4151 Element* element = document->getElementById("data"); 4152 4153 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4154 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4155 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4156 4157 element->focus(); 4158 document->execCommand("InsertText", false, "wellcome."); 4159 4160 WebVector<uint32_t> documentMarkers; 4161 webViewHelper.webView()->spellingMarkers(&documentMarkers); 4162 EXPECT_EQ(1U, documentMarkers.size()); 4163 EXPECT_EQ(kHash, documentMarkers[0]); 4164 } 4165 4166 class StubbornSpellCheckClient : public WebSpellCheckClient { 4167 public: 4168 StubbornSpellCheckClient() : m_completion(0) { } 4169 virtual ~StubbornSpellCheckClient() { } 4170 4171 virtual void requestCheckingOfText( 4172 const blink::WebString&, 4173 const blink::WebVector<uint32_t>&, 4174 const blink::WebVector<unsigned>&, 4175 blink::WebTextCheckingCompletion* completion) OVERRIDE 4176 { 4177 m_completion = completion; 4178 } 4179 4180 void kickNoResults() 4181 { 4182 kick(-1, -1, WebTextDecorationTypeSpelling); 4183 } 4184 4185 void kick() 4186 { 4187 kick(1, 8, WebTextDecorationTypeSpelling); 4188 } 4189 4190 void kickGrammar() 4191 { 4192 kick(1, 8, WebTextDecorationTypeGrammar); 4193 } 4194 4195 void kickInvisibleSpellcheck() 4196 { 4197 kick(1, 8, WebTextDecorationTypeInvisibleSpellcheck); 4198 } 4199 4200 private: 4201 void kick(int misspellingStartOffset, int misspellingLength, WebTextDecorationType type) 4202 { 4203 if (!m_completion) 4204 return; 4205 Vector<WebTextCheckingResult> results; 4206 if (misspellingStartOffset >= 0 && misspellingLength > 0) 4207 results.append(WebTextCheckingResult(type, misspellingStartOffset, misspellingLength)); 4208 m_completion->didFinishCheckingText(results); 4209 m_completion = 0; 4210 } 4211 4212 blink::WebTextCheckingCompletion* m_completion; 4213 }; 4214 4215 TEST_F(WebFrameTest, SlowSpellcheckMarkerPosition) 4216 { 4217 registerMockedHttpURLLoad("spell.html"); 4218 FrameTestHelpers::WebViewHelper webViewHelper; 4219 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4220 4221 StubbornSpellCheckClient spellcheck; 4222 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4223 4224 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4225 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>(); 4226 Document* document = frame->frame()->document(); 4227 Element* element = document->getElementById("data"); 4228 4229 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4230 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4231 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4232 4233 element->focus(); 4234 document->execCommand("InsertText", false, "wellcome "); 4235 webInputElement.setSelectionRange(0, 0); 4236 document->execCommand("InsertText", false, "he"); 4237 4238 spellcheck.kick(); 4239 4240 WebVector<uint32_t> documentMarkers; 4241 webViewHelper.webView()->spellingMarkers(&documentMarkers); 4242 EXPECT_EQ(0U, documentMarkers.size()); 4243 } 4244 4245 // This test verifies that cancelling spelling request does not cause a 4246 // write-after-free when there's no spellcheck client set. 4247 TEST_F(WebFrameTest, CancelSpellingRequestCrash) 4248 { 4249 registerMockedHttpURLLoad("spell.html"); 4250 FrameTestHelpers::WebViewHelper webViewHelper; 4251 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4252 webViewHelper.webView()->setSpellCheckClient(0); 4253 4254 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4255 Document* document = frame->frame()->document(); 4256 Element* element = document->getElementById("data"); 4257 4258 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4259 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4260 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4261 4262 element->focus(); 4263 frame->frame()->editor().replaceSelectionWithText("A", false, false); 4264 frame->frame()->spellChecker().cancelCheck(); 4265 } 4266 4267 TEST_F(WebFrameTest, SpellcheckResultErasesMarkers) 4268 { 4269 registerMockedHttpURLLoad("spell.html"); 4270 FrameTestHelpers::WebViewHelper webViewHelper; 4271 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4272 4273 StubbornSpellCheckClient spellcheck; 4274 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4275 4276 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4277 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>(); 4278 Document* document = frame->frame()->document(); 4279 Element* element = document->getElementById("data"); 4280 4281 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4282 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4283 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4284 4285 element->focus(); 4286 document->execCommand("InsertText", false, "welcome "); 4287 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Spelling); 4288 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::Grammar); 4289 document->markers()->addMarker(rangeOfContents(element->toNode()).get(), DocumentMarker::InvisibleSpellcheck); 4290 EXPECT_EQ(3U, document->markers()->markers().size()); 4291 4292 spellcheck.kickNoResults(); 4293 EXPECT_EQ(0U, document->markers()->markers().size()); 4294 } 4295 4296 TEST_F(WebFrameTest, SpellcheckResultsSavedInDocument) 4297 { 4298 registerMockedHttpURLLoad("spell.html"); 4299 FrameTestHelpers::WebViewHelper webViewHelper; 4300 webViewHelper.initializeAndLoad(m_baseURL + "spell.html"); 4301 4302 StubbornSpellCheckClient spellcheck; 4303 webViewHelper.webView()->setSpellCheckClient(&spellcheck); 4304 4305 WebFrameImpl* frame = toWebFrameImpl(webViewHelper.webView()->mainFrame()); 4306 WebInputElement webInputElement = frame->document().getElementById("data").to<WebInputElement>(); 4307 Document* document = frame->frame()->document(); 4308 Element* element = document->getElementById("data"); 4309 4310 webViewHelper.webView()->settings()->setAsynchronousSpellCheckingEnabled(true); 4311 webViewHelper.webView()->settings()->setUnifiedTextCheckerEnabled(true); 4312 webViewHelper.webView()->settings()->setEditingBehavior(WebSettings::EditingBehaviorWin); 4313 4314 element->focus(); 4315 document->execCommand("InsertText", false, "wellcome "); 4316 4317 spellcheck.kick(); 4318 ASSERT_EQ(1U, document->markers()->markers().size()); 4319 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]); 4320 EXPECT_EQ(DocumentMarker::Spelling, document->markers()->markers()[0]->type()); 4321 4322 document->execCommand("InsertText", false, "wellcome "); 4323 4324 spellcheck.kickGrammar(); 4325 ASSERT_EQ(1U, document->markers()->markers().size()); 4326 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]); 4327 EXPECT_EQ(DocumentMarker::Grammar, document->markers()->markers()[0]->type()); 4328 4329 document->execCommand("InsertText", false, "wellcome "); 4330 4331 spellcheck.kickInvisibleSpellcheck(); 4332 ASSERT_EQ(1U, document->markers()->markers().size()); 4333 ASSERT_NE(static_cast<DocumentMarker*>(0), document->markers()->markers()[0]); 4334 EXPECT_EQ(DocumentMarker::InvisibleSpellcheck, document->markers()->markers()[0]->type()); 4335 } 4336 4337 class TestAccessInitialDocumentWebFrameClient : public WebFrameClient { 4338 public: 4339 TestAccessInitialDocumentWebFrameClient() : m_didAccessInitialDocument(false) 4340 { 4341 } 4342 4343 virtual void didAccessInitialDocument(WebFrame* frame) 4344 { 4345 EXPECT_TRUE(!m_didAccessInitialDocument); 4346 m_didAccessInitialDocument = true; 4347 } 4348 4349 bool m_didAccessInitialDocument; 4350 }; 4351 4352 TEST_F(WebFrameTest, DidAccessInitialDocumentBody) 4353 { 4354 TestAccessInitialDocumentWebFrameClient webFrameClient; 4355 FrameTestHelpers::WebViewHelper webViewHelper; 4356 webViewHelper.initialize(true, &webFrameClient); 4357 runPendingTasks(); 4358 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4359 4360 // Create another window that will try to access it. 4361 FrameTestHelpers::WebViewHelper newWebViewHelper; 4362 WebView* newView = newWebViewHelper.initialize(true); 4363 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame()); 4364 runPendingTasks(); 4365 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4366 4367 // Access the initial document by modifying the body. 4368 newView->mainFrame()->executeScript( 4369 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';")); 4370 runPendingTasks(); 4371 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4372 4373 // Access the initial document again, to ensure we don't notify twice. 4374 newView->mainFrame()->executeScript( 4375 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';")); 4376 runPendingTasks(); 4377 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4378 } 4379 4380 TEST_F(WebFrameTest, DidAccessInitialDocumentNavigator) 4381 { 4382 TestAccessInitialDocumentWebFrameClient webFrameClient; 4383 FrameTestHelpers::WebViewHelper webViewHelper; 4384 webViewHelper.initialize(true, &webFrameClient); 4385 runPendingTasks(); 4386 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4387 4388 // Create another window that will try to access it. 4389 FrameTestHelpers::WebViewHelper newWebViewHelper; 4390 WebView* newView = newWebViewHelper.initialize(true); 4391 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame()); 4392 runPendingTasks(); 4393 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4394 4395 // Access the initial document to get to the navigator object. 4396 newView->mainFrame()->executeScript( 4397 WebScriptSource("console.log(window.opener.navigator);")); 4398 runPendingTasks(); 4399 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4400 } 4401 4402 TEST_F(WebFrameTest, DidAccessInitialDocumentViaJavascriptUrl) 4403 { 4404 TestAccessInitialDocumentWebFrameClient webFrameClient; 4405 FrameTestHelpers::WebViewHelper webViewHelper; 4406 webViewHelper.initialize(true, &webFrameClient); 4407 runPendingTasks(); 4408 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4409 4410 // Access the initial document from a javascript: URL. 4411 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.body.appendChild(document.createTextNode('Modified'))"); 4412 runPendingTasks(); 4413 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4414 } 4415 4416 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192 4417 #if OS(WIN) 4418 TEST_F(WebFrameTest, DISABLED_DidAccessInitialDocumentBodyBeforeModalDialog) 4419 #else 4420 TEST_F(WebFrameTest, DidAccessInitialDocumentBodyBeforeModalDialog) 4421 #endif 4422 { 4423 TestAccessInitialDocumentWebFrameClient webFrameClient; 4424 FrameTestHelpers::WebViewHelper webViewHelper; 4425 webViewHelper.initialize(true, &webFrameClient); 4426 runPendingTasks(); 4427 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4428 4429 // Create another window that will try to access it. 4430 FrameTestHelpers::WebViewHelper newWebViewHelper; 4431 WebView* newView = newWebViewHelper.initialize(true); 4432 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame()); 4433 runPendingTasks(); 4434 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4435 4436 // Access the initial document by modifying the body. We normally set a 4437 // timer to notify the client. 4438 newView->mainFrame()->executeScript( 4439 WebScriptSource("window.opener.document.body.innerHTML += 'Modified';")); 4440 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4441 4442 // Make sure that a modal dialog forces us to notify right away. 4443 newView->mainFrame()->executeScript( 4444 WebScriptSource("window.opener.confirm('Modal');")); 4445 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4446 4447 // Ensure that we don't notify again later. 4448 runPendingTasks(); 4449 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4450 } 4451 4452 // Fails on the WebKit XP (deps) bot. http://crbug.com/312192 4453 #if OS(WIN) 4454 TEST_F(WebFrameTest, DISABLED_DidWriteToInitialDocumentBeforeModalDialog) 4455 #else 4456 TEST_F(WebFrameTest, DidWriteToInitialDocumentBeforeModalDialog) 4457 #endif 4458 { 4459 TestAccessInitialDocumentWebFrameClient webFrameClient; 4460 FrameTestHelpers::WebViewHelper webViewHelper; 4461 webViewHelper.initialize(true, &webFrameClient); 4462 runPendingTasks(); 4463 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4464 4465 // Create another window that will try to access it. 4466 FrameTestHelpers::WebViewHelper newWebViewHelper; 4467 WebView* newView = newWebViewHelper.initialize(true); 4468 newView->mainFrame()->setOpener(webViewHelper.webView()->mainFrame()); 4469 runPendingTasks(); 4470 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4471 4472 // Access the initial document with document.write, which moves us past the 4473 // initial empty document state of the state machine. We normally set a 4474 // timer to notify the client. 4475 newView->mainFrame()->executeScript( 4476 WebScriptSource("window.opener.document.write('Modified');")); 4477 EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument); 4478 4479 // Make sure that a modal dialog forces us to notify right away. 4480 newView->mainFrame()->executeScript( 4481 WebScriptSource("window.opener.confirm('Modal');")); 4482 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4483 4484 // Ensure that we don't notify again later. 4485 runPendingTasks(); 4486 EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument); 4487 } 4488 4489 class TestMainFrameUserOrProgrammaticScrollFrameClient : public WebFrameClient { 4490 public: 4491 TestMainFrameUserOrProgrammaticScrollFrameClient() { reset(); } 4492 void reset() 4493 { 4494 m_didScrollMainFrame = false; 4495 m_wasProgrammaticScroll = false; 4496 } 4497 bool wasUserScroll() const { return m_didScrollMainFrame && !m_wasProgrammaticScroll; } 4498 bool wasProgrammaticScroll() const { return m_didScrollMainFrame && m_wasProgrammaticScroll; } 4499 4500 // WebFrameClient: 4501 virtual void didChangeScrollOffset(WebFrame* frame) OVERRIDE 4502 { 4503 if (frame->parent()) 4504 return; 4505 EXPECT_FALSE(m_didScrollMainFrame); 4506 WebCore::FrameView* view = toWebFrameImpl(frame)->frameView(); 4507 // FrameView can be scrolled in FrameView::setFixedVisibleContentRect 4508 // which is called from Frame::createView (before the frame is associated 4509 // with the the view). 4510 if (view) { 4511 m_didScrollMainFrame = true; 4512 m_wasProgrammaticScroll = view->inProgrammaticScroll(); 4513 } 4514 } 4515 private: 4516 bool m_didScrollMainFrame; 4517 bool m_wasProgrammaticScroll; 4518 }; 4519 4520 TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) 4521 { 4522 registerMockedHttpURLLoad("long_scroll.html"); 4523 TestMainFrameUserOrProgrammaticScrollFrameClient client; 4524 4525 // Make sure we initialize to minimum scale, even if the window size 4526 // only becomes available after the load begins. 4527 FrameTestHelpers::WebViewHelper webViewHelper; 4528 webViewHelper.initializeAndLoad(m_baseURL + "long_scroll.html", true, &client); 4529 webViewHelper.webView()->resize(WebSize(1000, 1000)); 4530 webViewHelper.webView()->layout(); 4531 4532 EXPECT_FALSE(client.wasUserScroll()); 4533 EXPECT_FALSE(client.wasProgrammaticScroll()); 4534 4535 // Do a compositor scroll, verify that this is counted as a user scroll. 4536 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.1f); 4537 EXPECT_TRUE(client.wasUserScroll()); 4538 client.reset(); 4539 4540 EXPECT_FALSE(client.wasUserScroll()); 4541 EXPECT_FALSE(client.wasProgrammaticScroll()); 4542 4543 // The page scale 1.0f and scroll. 4544 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(0, 1), 1.0f); 4545 EXPECT_TRUE(client.wasUserScroll()); 4546 client.reset(); 4547 4548 // No scroll event if there is no scroll delta. 4549 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(), 1.0f); 4550 EXPECT_FALSE(client.wasUserScroll()); 4551 EXPECT_FALSE(client.wasProgrammaticScroll()); 4552 client.reset(); 4553 4554 // Non zero page scale and scroll. 4555 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 0.6f); 4556 EXPECT_TRUE(client.wasUserScroll()); 4557 client.reset(); 4558 4559 // Programmatic scroll. 4560 WebFrameImpl* frameImpl = webViewHelper.webViewImpl()->mainFrameImpl(); 4561 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);")); 4562 EXPECT_FALSE(client.wasUserScroll()); 4563 EXPECT_TRUE(client.wasProgrammaticScroll()); 4564 client.reset(); 4565 4566 // Programmatic scroll to same offset. No scroll event should be generated. 4567 frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);")); 4568 EXPECT_FALSE(client.wasProgrammaticScroll()); 4569 EXPECT_FALSE(client.wasUserScroll()); 4570 client.reset(); 4571 } 4572 4573 TEST_F(WebFrameTest, CompositorScrollIsUserScrollShortPage) 4574 { 4575 registerMockedHttpURLLoad("short_scroll.html"); 4576 4577 TestMainFrameUserOrProgrammaticScrollFrameClient client; 4578 4579 // Short page tests. 4580 FrameTestHelpers::WebViewHelper webViewHelper; 4581 webViewHelper.initializeAndLoad(m_baseURL + "short_scroll.html", true, &client); 4582 4583 webViewHelper.webView()->resize(WebSize(1000, 1000)); 4584 webViewHelper.webView()->layout(); 4585 4586 EXPECT_FALSE(client.wasUserScroll()); 4587 EXPECT_FALSE(client.wasProgrammaticScroll()); 4588 4589 // Non zero page scale and scroll. 4590 webViewHelper.webViewImpl()->applyScrollAndScale(WebSize(9, 13), 2.0f); 4591 EXPECT_FALSE(client.wasProgrammaticScroll()); 4592 EXPECT_TRUE(client.wasUserScroll()); 4593 client.reset(); 4594 } 4595 4596 TEST_F(WebFrameTest, FirstPartyForCookiesForRedirect) 4597 { 4598 WTF::String filePath = Platform::current()->unitTestSupport()->webKitRootDir(); 4599 filePath.append("/Source/web/tests/data/first_party.html"); 4600 4601 WebURL testURL(toKURL("http://www.test.com/first_party_redirect.html")); 4602 char redirect[] = "http://www.test.com/first_party.html"; 4603 WebURL redirectURL(toKURL(redirect)); 4604 WebURLResponse redirectResponse; 4605 redirectResponse.initialize(); 4606 redirectResponse.setMIMEType("text/html"); 4607 redirectResponse.setHTTPStatusCode(302); 4608 redirectResponse.setHTTPHeaderField("Location", redirect); 4609 Platform::current()->unitTestSupport()->registerMockedURL(testURL, redirectResponse, filePath); 4610 4611 WebURLResponse finalResponse; 4612 finalResponse.initialize(); 4613 finalResponse.setMIMEType("text/html"); 4614 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, finalResponse, filePath); 4615 4616 FrameTestHelpers::WebViewHelper webViewHelper; 4617 webViewHelper.initializeAndLoad(m_baseURL + "first_party_redirect.html", true); 4618 EXPECT_TRUE(webViewHelper.webView()->mainFrame()->document().firstPartyForCookies() == redirectURL); 4619 } 4620 4621 class TestNavigationPolicyWebFrameClient : public WebFrameClient { 4622 public: 4623 4624 virtual void didNavigateWithinPage(WebFrame*, bool) 4625 { 4626 EXPECT_TRUE(false); 4627 } 4628 }; 4629 4630 TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick) 4631 { 4632 registerMockedHttpURLLoad("fragment_middle_click.html"); 4633 TestNavigationPolicyWebFrameClient client; 4634 FrameTestHelpers::WebViewHelper webViewHelper; 4635 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true, &client); 4636 4637 WebCore::Document* document = webViewHelper.webViewImpl()->page()->mainFrame()->document(); 4638 WebCore::KURL destination = document->url(); 4639 destination.setFragmentIdentifier("test"); 4640 4641 RefPtr<WebCore::Event> event = WebCore::MouseEvent::create(WebCore::EventTypeNames::click, false, false, 4642 document->domWindow(), 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 1, 0, 0); 4643 WebCore::FrameLoadRequest frameRequest(document, WebCore::ResourceRequest(destination)); 4644 frameRequest.setTriggeringEvent(event); 4645 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest); 4646 } 4647 4648 TEST_F(WebFrameTest, BackToReload) 4649 { 4650 registerMockedHttpURLLoad("fragment_middle_click.html"); 4651 FrameTestHelpers::WebViewHelper webViewHelper; 4652 webViewHelper.initializeAndLoad(m_baseURL + "fragment_middle_click.html", true); 4653 WebFrame* frame = webViewHelper.webView()->mainFrame(); 4654 WebHistoryItem firstItem = frame->currentHistoryItem(); 4655 EXPECT_FALSE(firstItem.isNull()); 4656 4657 registerMockedHttpURLLoad("white-1x1.png"); 4658 FrameTestHelpers::loadFrame(frame, m_baseURL + "white-1x1.png"); 4659 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4660 EXPECT_FALSE(frame->previousHistoryItem().isNull()); 4661 EXPECT_EQ(firstItem.urlString(), frame->previousHistoryItem().urlString()); 4662 4663 frame->loadHistoryItem(frame->previousHistoryItem()); 4664 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4665 EXPECT_EQ(firstItem.urlString(), frame->currentHistoryItem().urlString()); 4666 4667 frame->reload(); 4668 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4669 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy()); 4670 } 4671 4672 TEST_F(WebFrameTest, BackDuringChildFrameReload) 4673 { 4674 registerMockedHttpURLLoad("page_with_blank_iframe.html"); 4675 FrameTestHelpers::WebViewHelper webViewHelper; 4676 webViewHelper.initializeAndLoad(m_baseURL + "page_with_blank_iframe.html", true); 4677 WebFrame* mainFrame = webViewHelper.webView()->mainFrame(); 4678 WebFrame* childFrame = mainFrame->firstChild(); 4679 ASSERT_TRUE(childFrame); 4680 4681 // Start a history navigation, then have a different frame commit a navigation. 4682 // In this case, reload an about:blank frame, which will commit synchronously. 4683 // After the history navigation completes, both the appropriate document url and 4684 // the current history item should reflect the history navigation. 4685 registerMockedHttpURLLoad("white-1x1.png"); 4686 WebHistoryItem item; 4687 item.initialize(); 4688 WebURL historyURL(toKURL(m_baseURL + "white-1x1.png")); 4689 item.setURLString(historyURL.string()); 4690 mainFrame->loadHistoryItem(item); 4691 4692 childFrame->reload(); 4693 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4694 EXPECT_EQ(item.urlString(), mainFrame->document().url().string()); 4695 EXPECT_EQ(item.urlString(), mainFrame->currentHistoryItem().urlString()); 4696 } 4697 4698 TEST_F(WebFrameTest, ReloadPost) 4699 { 4700 registerMockedHttpURLLoad("reload_post.html"); 4701 FrameTestHelpers::WebViewHelper webViewHelper; 4702 webViewHelper.initializeAndLoad(m_baseURL + "reload_post.html", true); 4703 WebFrame* frame = webViewHelper.webView()->mainFrame(); 4704 4705 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascript:document.forms[0].submit()"); 4706 runPendingTasks(); 4707 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4708 EXPECT_FALSE(frame->previousHistoryItem().isNull()); 4709 EXPECT_EQ(WebString::fromUTF8("POST"), frame->dataSource()->request().httpMethod()); 4710 4711 frame->reload(); 4712 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4713 EXPECT_EQ(WebURLRequest::ReloadIgnoringCacheData, frame->dataSource()->request().cachePolicy()); 4714 EXPECT_EQ(WebNavigationTypeFormResubmitted, frame->dataSource()->navigationType()); 4715 } 4716 4717 4718 class TestCachePolicyWebFrameClient : public WebFrameClient { 4719 public: 4720 TestCachePolicyWebFrameClient() 4721 : m_policy(WebURLRequest::UseProtocolCachePolicy) 4722 , m_client(0) 4723 , m_willSendRequestCallCount(0) 4724 , m_childFrameCreationCount(0) 4725 { 4726 } 4727 4728 void setChildWebFrameClient(WebFrameClient* client) { m_client = client; } 4729 WebURLRequest::CachePolicy cachePolicy() const { return m_policy; } 4730 int willSendRequestCallCount() const { return m_willSendRequestCallCount; } 4731 int childFrameCreationCount() const { return m_childFrameCreationCount; } 4732 4733 virtual WebFrame* createChildFrame(WebFrame*, const WebString&) 4734 { 4735 m_childFrameCreationCount++; 4736 return WebFrame::create(m_client); 4737 } 4738 4739 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&) 4740 { 4741 m_policy = request.cachePolicy(); 4742 m_willSendRequestCallCount++; 4743 } 4744 4745 private: 4746 WebURLRequest::CachePolicy m_policy; 4747 WebFrameClient* m_client; 4748 int m_willSendRequestCallCount; 4749 int m_childFrameCreationCount; 4750 }; 4751 4752 TEST_F(WebFrameTest, ReloadIframe) 4753 { 4754 registerMockedHttpURLLoad("iframe_reload.html"); 4755 registerMockedHttpURLLoad("visible_iframe.html"); 4756 TestCachePolicyWebFrameClient mainClient; 4757 TestCachePolicyWebFrameClient childClient; 4758 mainClient.setChildWebFrameClient(&childClient); 4759 4760 FrameTestHelpers::WebViewHelper webViewHelper; 4761 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient); 4762 4763 WebFrameImpl* mainFrame = webViewHelper.webViewImpl()->mainFrameImpl(); 4764 WebFrameImpl* childFrame = toWebFrameImpl(mainFrame->firstChild()); 4765 ASSERT_EQ(childFrame->client(), &childClient); 4766 EXPECT_EQ(mainClient.childFrameCreationCount(), 1); 4767 EXPECT_EQ(childClient.willSendRequestCallCount(), 1); 4768 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::UseProtocolCachePolicy); 4769 4770 mainFrame->reload(false); 4771 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4772 4773 // A new WebFrame should have been created, but the child WebFrameClient should be reused. 4774 ASSERT_FALSE(childFrame == toWebFrameImpl(mainFrame->firstChild())); 4775 ASSERT_EQ(toWebFrameImpl(mainFrame->firstChild())->client(), &childClient); 4776 4777 EXPECT_EQ(mainClient.childFrameCreationCount(), 2); 4778 EXPECT_EQ(childClient.willSendRequestCallCount(), 2); 4779 EXPECT_EQ(childClient.cachePolicy(), WebURLRequest::ReloadIgnoringCacheData); 4780 } 4781 4782 TEST_F(WebFrameTest, ExportHistoryItemFromChildFrame) 4783 { 4784 registerMockedHttpURLLoad("iframe_reload.html"); 4785 registerMockedHttpURLLoad("visible_iframe.html"); 4786 TestCachePolicyWebFrameClient mainClient; 4787 TestCachePolicyWebFrameClient childClient; 4788 mainClient.setChildWebFrameClient(&childClient); 4789 4790 FrameTestHelpers::WebViewHelper webViewHelper; 4791 webViewHelper.initializeAndLoad(m_baseURL + "iframe_reload.html", true, &mainClient); 4792 4793 WebFrame* childFrame = webViewHelper.webViewImpl()->mainFrameImpl()->firstChild(); 4794 WebHistoryItem item = childFrame->currentHistoryItem(); 4795 EXPECT_EQ(item.urlString(), WebString::fromUTF8(m_baseURL + "iframe_reload.html")); 4796 } 4797 4798 class TestSameDocumentWebFrameClient : public WebFrameClient { 4799 public: 4800 TestSameDocumentWebFrameClient() 4801 : m_frameLoadTypeSameSeen(false) 4802 { 4803 } 4804 4805 virtual void willSendRequest(WebFrame* frame, unsigned, WebURLRequest&, const WebURLResponse&) 4806 { 4807 if (toWebFrameImpl(frame)->frame()->loader().loadType() == WebCore::FrameLoadTypeSame) 4808 m_frameLoadTypeSameSeen = true; 4809 } 4810 4811 bool frameLoadTypeSameSeen() const { return m_frameLoadTypeSameSeen; } 4812 4813 private: 4814 bool m_frameLoadTypeSameSeen; 4815 }; 4816 4817 TEST_F(WebFrameTest, NavigateToSame) 4818 { 4819 registerMockedHttpURLLoad("navigate_to_same.html"); 4820 TestSameDocumentWebFrameClient client; 4821 FrameTestHelpers::WebViewHelper webViewHelper; 4822 webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true, &client); 4823 EXPECT_FALSE(client.frameLoadTypeSameSeen()); 4824 4825 WebCore::FrameLoadRequest frameRequest(0, WebCore::ResourceRequest(webViewHelper.webViewImpl()->page()->mainFrame()->document()->url())); 4826 webViewHelper.webViewImpl()->page()->mainFrame()->loader().load(frameRequest); 4827 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4828 4829 EXPECT_TRUE(client.frameLoadTypeSameSeen()); 4830 } 4831 4832 TEST_F(WebFrameTest, WebNodeImageContents) 4833 { 4834 FrameTestHelpers::WebViewHelper webViewHelper; 4835 webViewHelper.initializeAndLoad("about:blank", true); 4836 WebFrame* frame = webViewHelper.webView()->mainFrame(); 4837 4838 static const char bluePNG[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGElEQVQYV2NkYPj/n4EIwDiqEF8oUT94AFIQE/cCn90IAAAAAElFTkSuQmCC\">"; 4839 4840 // Load up the image and test that we can extract the contents. 4841 WebCore::KURL testURL = toKURL("about:blank"); 4842 frame->loadHTMLString(bluePNG, testURL); 4843 runPendingTasks(); 4844 4845 WebNode node = frame->document().body().firstChild(); 4846 EXPECT_TRUE(node.isElementNode()); 4847 WebElement element = node.to<WebElement>(); 4848 WebImage image = element.imageContents(); 4849 ASSERT_FALSE(image.isNull()); 4850 EXPECT_EQ(image.size().width, 10); 4851 EXPECT_EQ(image.size().height, 10); 4852 // FIXME: The rest of this test is disabled since the ImageDecodeCache state may be inconsistent when this test runs. 4853 // crbug.com/266088 4854 // SkBitmap bitmap = image.getSkBitmap(); 4855 // SkAutoLockPixels locker(bitmap); 4856 // EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE); 4857 } 4858 4859 class TestStartStopCallbackWebViewClient : public WebViewClient { 4860 public: 4861 TestStartStopCallbackWebViewClient() 4862 : m_startLoadingCount(0) 4863 , m_stopLoadingCount(0) 4864 { 4865 } 4866 4867 virtual void didStartLoading() 4868 { 4869 m_startLoadingCount++; 4870 } 4871 4872 virtual void didStopLoading() 4873 { 4874 m_stopLoadingCount++; 4875 } 4876 4877 int startLoadingCount() const { return m_startLoadingCount; } 4878 int stopLoadingCount() const { return m_stopLoadingCount; } 4879 4880 private: 4881 int m_startLoadingCount; 4882 int m_stopLoadingCount; 4883 }; 4884 4885 TEST_F(WebFrameTest, PushStateStartsAndStops) 4886 { 4887 registerMockedHttpURLLoad("push_state.html"); 4888 TestStartStopCallbackWebViewClient client; 4889 FrameTestHelpers::WebViewHelper webViewHelper; 4890 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, 0, &client); 4891 runPendingTasks(); 4892 4893 EXPECT_EQ(client.startLoadingCount(), 2); 4894 EXPECT_EQ(client.stopLoadingCount(), 2); 4895 } 4896 4897 class TestHistoryWebFrameClient : public WebFrameClient { 4898 public: 4899 TestHistoryWebFrameClient() 4900 { 4901 m_replacesCurrentHistoryItem = false; 4902 m_frame = 0; 4903 } 4904 void didStartProvisionalLoad(WebFrame* frame) 4905 { 4906 WebDataSource* ds = frame->provisionalDataSource(); 4907 m_replacesCurrentHistoryItem = ds->replacesCurrentHistoryItem(); 4908 m_frame = frame; 4909 } 4910 4911 bool replacesCurrentHistoryItem() { return m_replacesCurrentHistoryItem; } 4912 WebFrame* frame() { return m_frame; } 4913 4914 private: 4915 bool m_replacesCurrentHistoryItem; 4916 WebFrame* m_frame; 4917 }; 4918 4919 // Test which ensures that the first navigation in a subframe will always 4920 // result in history entry being replaced and not a new one added. 4921 TEST_F(WebFrameTest, DISABLED_FirstFrameNavigationReplacesHistory) 4922 { 4923 registerMockedHttpURLLoad("history.html"); 4924 registerMockedHttpURLLoad("find.html"); 4925 4926 FrameTestHelpers::WebViewHelper webViewHelper; 4927 TestHistoryWebFrameClient client; 4928 webViewHelper.initializeAndLoad("about:blank", true, &client); 4929 runPendingTasks(); 4930 EXPECT_TRUE(client.replacesCurrentHistoryItem()); 4931 4932 WebFrame* frame = webViewHelper.webView()->mainFrame(); 4933 4934 FrameTestHelpers::loadFrame(frame, 4935 "javascript:document.body.appendChild(document.createElement('iframe'))"); 4936 // Need to call runPendingTasks in order for the JavaScript above to be 4937 // evaluated and executed. 4938 runPendingTasks(); 4939 WebFrame* iframe = frame->firstChild(); 4940 EXPECT_EQ(client.frame(), iframe); 4941 EXPECT_TRUE(client.replacesCurrentHistoryItem()); 4942 4943 FrameTestHelpers::loadFrame(frame, 4944 "javascript:window.frames[0].location.assign('" + m_baseURL + "history.html')"); 4945 runPendingTasks(); 4946 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4947 EXPECT_EQ(client.frame(), iframe); 4948 EXPECT_TRUE(client.replacesCurrentHistoryItem()); 4949 4950 FrameTestHelpers::loadFrame(frame, 4951 "javascript:window.frames[0].location.assign('" + m_baseURL + "find.html')"); 4952 runPendingTasks(); 4953 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4954 EXPECT_EQ(client.frame(), iframe); 4955 EXPECT_FALSE(client.replacesCurrentHistoryItem()); 4956 4957 // Repeat the test, but start out the iframe with initial URL, which is not 4958 // "about:blank". 4959 FrameTestHelpers::loadFrame(frame, 4960 "javascript:var f = document.createElement('iframe'); " 4961 "f.src = '" + m_baseURL + "history.html';" 4962 "document.body.appendChild(f)"); 4963 runPendingTasks(); 4964 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4965 4966 iframe = frame->firstChild()->nextSibling(); 4967 EXPECT_EQ(client.frame(), iframe); 4968 EXPECT_TRUE(client.replacesCurrentHistoryItem()); 4969 4970 FrameTestHelpers::loadFrame(frame, 4971 "javascript:window.frames[1].location.assign('" + m_baseURL + "find.html')"); 4972 runPendingTasks(); 4973 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 4974 EXPECT_EQ(client.frame(), iframe); 4975 EXPECT_FALSE(client.replacesCurrentHistoryItem()); 4976 } 4977 4978 // This tests the restore case where the first load in a page is 4979 // via loadHistoryItem(). If multiple pages are in the same process 4980 // and are restoring around the same time, they may not restore in 4981 // the order they were created and may end up with different names 4982 // than they were given when they were saved. If the initial item 4983 // has a child with url "about:blank", we should still navigate the 4984 // main frame to the parent, rather than incorrectly matching the 4985 // blank child to the main frame. 4986 TEST_F(WebFrameTest, firstNavigationIsHistoryWithBlankChild) 4987 { 4988 registerMockedHttpURLLoad("history.html"); 4989 FrameTestHelpers::WebViewHelper webViewHelper; 4990 WebViewImpl* webView = webViewHelper.initialize(); 4991 ASSERT_TRUE(webView->mainFrame()->currentHistoryItem().isNull()); 4992 4993 WebHistoryItem item; 4994 item.initialize(); 4995 WebURL destinationURL(toKURL(m_baseURL + "history.html")); 4996 item.setURLString(destinationURL.string()); 4997 item.setTarget(WebString::fromUTF8("expectedButMissingMainFrameName")); 4998 4999 WebHistoryItem childItem; 5000 childItem.initialize(); 5001 childItem.setURLString("about:blank"); 5002 item.appendToChildren(childItem); 5003 5004 webView->mainFrame()->loadHistoryItem(item); 5005 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 5006 EXPECT_EQ(destinationURL, webView->mainFrame()->document().url()); 5007 } 5008 5009 // Test verifies that layout will change a layer's scrollable attibutes 5010 TEST_F(WebFrameTest, overflowHiddenRewrite) 5011 { 5012 registerMockedHttpURLLoad("non-scrollable.html"); 5013 TestMainFrameUserOrProgrammaticScrollFrameClient client; 5014 OwnPtr<FakeCompositingWebViewClient> fakeCompositingWebViewClient = adoptPtr(new FakeCompositingWebViewClient()); 5015 FrameTestHelpers::WebViewHelper webViewHelper; 5016 webViewHelper.initialize(true, &fakeCompositingWebViewClient->m_fakeWebFrameClient, fakeCompositingWebViewClient.get(), &configueCompositingWebView); 5017 5018 webViewHelper.webView()->resize(WebSize(100, 100)); 5019 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "non-scrollable.html"); 5020 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 5021 webViewHelper.webView()->layout(); 5022 5023 WebCore::RenderLayerCompositor* compositor = webViewHelper.webViewImpl()->compositor(); 5024 ASSERT_TRUE(compositor->scrollLayer()); 5025 5026 // Verify that the WebLayer is not scrollable initially. 5027 WebCore::GraphicsLayer* scrollLayer = compositor->scrollLayer(); 5028 WebLayer* webScrollLayer = scrollLayer->platformLayer(); 5029 ASSERT_FALSE(webScrollLayer->userScrollableHorizontal()); 5030 ASSERT_FALSE(webScrollLayer->userScrollableVertical()); 5031 5032 // Call javascript to make the layer scrollable, and verify it. 5033 WebFrameImpl* frame = (WebFrameImpl*)webViewHelper.webView()->mainFrame(); 5034 frame->executeScript(WebScriptSource("allowScroll();")); 5035 webViewHelper.webView()->layout(); 5036 ASSERT_TRUE(webScrollLayer->userScrollableHorizontal()); 5037 ASSERT_TRUE(webScrollLayer->userScrollableVertical()); 5038 } 5039 5040 } // namespace 5041