| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 | 32 |
| 33 #include "WebFrame.h" | 33 #include "WebFrame.h" |
| 34 | 34 |
| 35 #include <gmock/gmock.h> |
| 35 #include <gtest/gtest.h> | 36 #include <gtest/gtest.h> |
| 36 #include "FrameTestHelpers.h" | 37 #include "FrameTestHelpers.h" |
| 37 #include "SkBitmap.h" | 38 #include "SkBitmap.h" |
| 38 #include "SkCanvas.h" | 39 #include "SkCanvas.h" |
| 39 #include "URLTestHelpers.h" | 40 #include "URLTestHelpers.h" |
| 40 #include "WebDataSource.h" | 41 #include "WebDataSource.h" |
| 41 #include "WebDocument.h" | 42 #include "WebDocument.h" |
| 42 #include "WebFindOptions.h" | 43 #include "WebFindOptions.h" |
| 43 #include "WebFormElement.h" | 44 #include "WebFormElement.h" |
| 44 #include "WebFrameClient.h" | 45 #include "WebFrameClient.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 #include "core/rendering/RenderView.h" | 78 #include "core/rendering/RenderView.h" |
| 78 #include "core/rendering/TextAutosizer.h" | 79 #include "core/rendering/TextAutosizer.h" |
| 79 #include "v8.h" | 80 #include "v8.h" |
| 80 #include "public/platform/Platform.h" | 81 #include "public/platform/Platform.h" |
| 81 #include "public/platform/WebFloatRect.h" | 82 #include "public/platform/WebFloatRect.h" |
| 82 #include "public/platform/WebThread.h" | 83 #include "public/platform/WebThread.h" |
| 83 #include "public/platform/WebUnitTestSupport.h" | 84 #include "public/platform/WebUnitTestSupport.h" |
| 84 #include "public/platform/WebURLResponse.h" | 85 #include "public/platform/WebURLResponse.h" |
| 85 #include "wtf/dtoa/utils.h" | 86 #include "wtf/dtoa/utils.h" |
| 86 #include "wtf/Forward.h" | 87 #include "wtf/Forward.h" |
| 88 #include <map> |
| 87 | 89 |
| 88 using namespace WebKit; | 90 using namespace WebKit; |
| 89 using WebCore::Document; | 91 using WebCore::Document; |
| 90 using WebCore::DocumentMarker; | 92 using WebCore::DocumentMarker; |
| 91 using WebCore::Element; | 93 using WebCore::Element; |
| 92 using WebCore::FloatRect; | 94 using WebCore::FloatRect; |
| 93 using WebCore::HitTestRequest; | 95 using WebCore::HitTestRequest; |
| 94 using WebCore::Range; | 96 using WebCore::Range; |
| 95 using WebKit::URLTestHelpers::toKURL; | 97 using WebKit::URLTestHelpers::toKURL; |
| 96 using WebKit::FrameTestHelpers::runPendingTasks; | 98 using WebKit::FrameTestHelpers::runPendingTasks; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 FrameTestHelpers::loadFrame(m_webView->mainFrame(), "javascript:document.bod
y.appendChild(document.createTextNode('Clobbered'))"); | 270 FrameTestHelpers::loadFrame(m_webView->mainFrame(), "javascript:document.bod
y.appendChild(document.createTextNode('Clobbered'))"); |
| 269 | 271 |
| 270 // Required to see any updates in contentAsText. | 272 // Required to see any updates in contentAsText. |
| 271 m_webView->layout(); | 273 m_webView->layout(); |
| 272 | 274 |
| 273 // Now retrieve the frame's text and ensure it wasn't modified by running ja
vascript. | 275 // Now retrieve the frame's text and ensure it wasn't modified by running ja
vascript. |
| 274 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024
).utf8().data()); | 276 std::string content = std::string(m_webView->mainFrame()->contentAsText(1024
).utf8().data()); |
| 275 EXPECT_EQ(std::string::npos, content.find("Clobbered")); | 277 EXPECT_EQ(std::string::npos, content.find("Clobbered")); |
| 276 } | 278 } |
| 277 | 279 |
| 280 struct CSSCallbackWebFrameClient : public WebFrameClient { |
| 281 CSSCallbackWebFrameClient() : m_updateCount(0) { } |
| 282 virtual void didMatchCSS(WebFrame* frame, const WebVector<WebString>& newlyM
atchingSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE |
| 283 { |
| 284 ++m_updateCount; |
| 285 std::set<std::string>& frameSelectors = m_matchedSelectors[frame]; |
| 286 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) { |
| 287 std::string selector = newlyMatchingSelectors[i].utf8(); |
| 288 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector; |
| 289 frameSelectors.insert(selector); |
| 290 } |
| 291 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) { |
| 292 std::string selector = stoppedMatchingSelectors[i].utf8(); |
| 293 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector; |
| 294 frameSelectors.erase(selector); |
| 295 } |
| 296 } |
| 297 |
| 298 std::map<WebFrame*, std::set<std::string> > m_matchedSelectors; |
| 299 int m_updateCount; |
| 300 }; |
| 301 |
| 302 class WebFrameCSSCallbackTest : public testing::Test { |
| 303 protected: |
| 304 WebFrameCSSCallbackTest() |
| 305 { |
| 306 m_webView = FrameTestHelpers::createWebViewAndLoad("about:blank", true,
&m_client); |
| 307 m_frame = m_webView->mainFrame(); |
| 308 } |
| 309 |
| 310 ~WebFrameCSSCallbackTest() |
| 311 { |
| 312 EXPECT_EQ(1U, m_client.m_matchedSelectors.size()); |
| 313 m_webView->close(); |
| 314 } |
| 315 |
| 316 WebDocument doc() const |
| 317 { |
| 318 return m_frame->document(); |
| 319 } |
| 320 |
| 321 int updateCount() const |
| 322 { |
| 323 return m_client.m_updateCount; |
| 324 } |
| 325 |
| 326 const std::set<std::string>& matchedSelectors() |
| 327 { |
| 328 return m_client.m_matchedSelectors[m_frame]; |
| 329 } |
| 330 |
| 331 void loadHTML(const WebData& html) |
| 332 { |
| 333 m_frame->loadHTMLString(html, toKURL("about:blank")); |
| 334 runPendingTasks(); |
| 335 } |
| 336 |
| 337 void executeScript(const WebString& code) |
| 338 { |
| 339 m_frame->executeScript(WebScriptSource(code)); |
| 340 runPendingTasks(); |
| 341 } |
| 342 |
| 343 CSSCallbackWebFrameClient m_client; |
| 344 WebView* m_webView; |
| 345 WebFrame* m_frame; |
| 346 }; |
| 347 |
| 348 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet) |
| 349 { |
| 350 loadHTML( |
| 351 "<style>" |
| 352 // This stylesheet checks that the internal property and value can't be |
| 353 // set by a stylesheet, only WebDocument::watchCSSSelectors(). |
| 354 "div.initial_on { -internal-callback: none; }" |
| 355 "div.initial_off { -internal-callback: -internal-presence; }" |
| 356 "</style>" |
| 357 "<div class=\"initial_on\"></div>" |
| 358 "<div class=\"initial_off\"></div>"); |
| 359 |
| 360 std::vector<WebString> selectors; |
| 361 selectors.push_back(WebString::fromUTF8("div.initial_on")); |
| 362 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 363 runPendingTasks(); |
| 364 EXPECT_EQ(1, updateCount()); |
| 365 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on")); |
| 366 |
| 367 // Check that adding a watched selector calls back for already-present nodes
. |
| 368 selectors.push_back(WebString::fromUTF8("div.initial_off")); |
| 369 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 370 runPendingTasks(); |
| 371 EXPECT_EQ(2, updateCount()); |
| 372 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div
.initial_on")); |
| 373 |
| 374 // Check that we can turn off callbacks for certain selectors. |
| 375 doc().watchCSSSelectors(WebVector<WebString>()); |
| 376 runPendingTasks(); |
| 377 EXPECT_EQ(3, updateCount()); |
| 378 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 379 } |
| 380 |
| 381 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle) |
| 382 { |
| 383 // Check that adding an element calls back when it matches an existing rule. |
| 384 std::vector<WebString> selectors; |
| 385 selectors.push_back(WebString::fromUTF8("span")); |
| 386 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 387 |
| 388 executeScript( |
| 389 "i1 = document.createElement('span');" |
| 390 "i1.id = 'first_span';" |
| 391 "document.body.appendChild(i1)"); |
| 392 EXPECT_EQ(1, updateCount()); |
| 393 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 394 |
| 395 // Adding a second element that shares a RenderStyle shouldn't call back. |
| 396 // We use <span>s to avoid default style rules that can set |
| 397 // RenderStyle::unique(). |
| 398 executeScript( |
| 399 "i2 = document.createElement('span');" |
| 400 "i2.id = 'second_span';" |
| 401 "i1 = document.getElementById('first_span');" |
| 402 "i1.parentNode.insertBefore(i2, i1.nextSibling);"); |
| 403 EXPECT_EQ(1, updateCount()); |
| 404 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 405 |
| 406 // Removing the first element shouldn't call back. |
| 407 executeScript( |
| 408 "i1 = document.getElementById('first_span');" |
| 409 "i1.parentNode.removeChild(i1);"); |
| 410 EXPECT_EQ(1, updateCount()); |
| 411 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 412 |
| 413 // But removing the second element *should* call back. |
| 414 executeScript( |
| 415 "i2 = document.getElementById('second_span');" |
| 416 "i2.parentNode.removeChild(i2);"); |
| 417 EXPECT_EQ(2, updateCount()); |
| 418 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 419 } |
| 420 |
| 421 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange) |
| 422 { |
| 423 loadHTML("<span></span>"); |
| 424 |
| 425 std::vector<WebString> selectors; |
| 426 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]")); |
| 427 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 428 runPendingTasks(); |
| 429 |
| 430 EXPECT_EQ(0, updateCount()); |
| 431 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 432 |
| 433 executeScript( |
| 434 "document.querySelector('span').setAttribute('attr', 'value');"); |
| 435 EXPECT_EQ(1, updateCount()); |
| 436 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]")
); |
| 437 } |
| 438 |
| 439 TEST_F(WebFrameCSSCallbackTest, DisplayNone) |
| 440 { |
| 441 loadHTML("<div style='display:none'><span></span></div>"); |
| 442 |
| 443 std::vector<WebString> selectors; |
| 444 selectors.push_back(WebString::fromUTF8("span")); |
| 445 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 446 runPendingTasks(); |
| 447 |
| 448 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees."
; |
| 449 |
| 450 executeScript( |
| 451 "d = document.querySelector('div');" |
| 452 "d.style.display = 'block';"); |
| 453 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed."; |
| 454 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 455 |
| 456 executeScript( |
| 457 "d = document.querySelector('div');" |
| 458 "d.style.display = 'none';"); |
| 459 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplaye
d."; |
| 460 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 461 |
| 462 executeScript( |
| 463 "s = document.querySelector('span');" |
| 464 "s.style.display = 'none';"); |
| 465 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's
already undisplayed."; |
| 466 |
| 467 executeScript( |
| 468 "d = document.querySelector('div');" |
| 469 "d.style.display = 'block';"); |
| 470 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span i
s display:none."; |
| 471 |
| 472 executeScript( |
| 473 "s = document.querySelector('span');" |
| 474 "s.style.display = 'inline';"); |
| 475 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callb
ack."; |
| 476 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 477 |
| 478 executeScript( |
| 479 "s = document.querySelector('span');" |
| 480 "s.style.display = 'none';"); |
| 481 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produc
e another callback."; |
| 482 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 483 } |
| 484 |
| 485 TEST_F(WebFrameCSSCallbackTest, Reparenting) |
| 486 { |
| 487 loadHTML( |
| 488 "<div id='d1'><span></span></div>" |
| 489 "<div id='d2'></div>"); |
| 490 |
| 491 std::vector<WebString> selectors; |
| 492 selectors.push_back(WebString::fromUTF8("span")); |
| 493 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 494 runPendingTasks(); |
| 495 |
| 496 EXPECT_EQ(1, updateCount()); |
| 497 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 498 |
| 499 executeScript( |
| 500 "s = document.querySelector('span');" |
| 501 "d2 = document.getElementById('d2');" |
| 502 "d2.appendChild(s);"); |
| 503 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to mat
ch shouldn't send a spurious callback."; |
| 504 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 505 } |
| 506 |
| 507 TEST_F(WebFrameCSSCallbackTest, MultiSelector) |
| 508 { |
| 509 loadHTML("<span></span>"); |
| 510 |
| 511 // Check that selector lists match as the whole list, not as each element |
| 512 // independently. |
| 513 std::vector<WebString> selectors; |
| 514 selectors.push_back(WebString::fromUTF8("span")); |
| 515 selectors.push_back(WebString::fromUTF8("span,p")); |
| 516 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 517 |
| 518 runPendingTasks(); |
| 519 EXPECT_EQ(1, updateCount()); |
| 520 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p")); |
| 521 } |
| 522 |
| 523 TEST_F(WebFrameCSSCallbackTest, InvalidSelector) |
| 524 { |
| 525 loadHTML("<p><span></span></p>"); |
| 526 |
| 527 // Build a list with one valid selector and one invalid. |
| 528 std::vector<WebString> selectors; |
| 529 selectors.push_back(WebString::fromUTF8("span")); |
| 530 selectors.push_back(WebString::fromUTF8("[")); // Invalid. |
| 531 selectors.push_back(WebString::fromUTF8("p span")); // Not compound. |
| 532 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 533 |
| 534 runPendingTasks(); |
| 535 EXPECT_EQ(1, updateCount()); |
| 536 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")) |
| 537 << "An invalid selector shouldn't prevent other selectors from matching.
"; |
| 538 } |
| 539 |
| 278 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) | 540 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) |
| 279 { | 541 { |
| 280 registerMockedHttpURLLoad("postmessage_test.html"); | 542 registerMockedHttpURLLoad("postmessage_test.html"); |
| 281 | 543 |
| 282 // Pass true to enable JavaScript. | 544 // Pass true to enable JavaScript. |
| 283 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "postmessage_
test.html", true); | 545 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "postmessage_
test.html", true); |
| 284 | 546 |
| 285 // Send a message with the correct origin. | 547 // Send a message with the correct origin. |
| 286 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL))
); | 548 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL))
); |
| 287 WebDOMEvent event = m_webView->mainFrame()->document().createEvent("MessageE
vent"); | 549 WebDOMEvent event = m_webView->mainFrame()->document().createEvent("MessageE
vent"); |
| (...skipping 3326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3614 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "push_state.h
tml", true, 0, &client); | 3876 m_webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "push_state.h
tml", true, 0, &client); |
| 3615 runPendingTasks(); | 3877 runPendingTasks(); |
| 3616 | 3878 |
| 3617 EXPECT_EQ(client.startLoadingCount(), 2); | 3879 EXPECT_EQ(client.startLoadingCount(), 2); |
| 3618 EXPECT_EQ(client.stopLoadingCount(), 2); | 3880 EXPECT_EQ(client.stopLoadingCount(), 2); |
| 3619 m_webView->close(); | 3881 m_webView->close(); |
| 3620 m_webView = 0; | 3882 m_webView = 0; |
| 3621 } | 3883 } |
| 3622 | 3884 |
| 3623 } // namespace | 3885 } // namespace |
| OLD | NEW |