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 "RuntimeEnabledFeatures.h" | 38 #include "RuntimeEnabledFeatures.h" |
38 #include "SkBitmap.h" | 39 #include "SkBitmap.h" |
39 #include "SkCanvas.h" | 40 #include "SkCanvas.h" |
40 #include "URLTestHelpers.h" | 41 #include "URLTestHelpers.h" |
41 #include "WebDataSource.h" | 42 #include "WebDataSource.h" |
42 #include "WebDocument.h" | 43 #include "WebDocument.h" |
43 #include "WebFindOptions.h" | 44 #include "WebFindOptions.h" |
44 #include "WebFormElement.h" | 45 #include "WebFormElement.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 #include "core/rendering/RenderView.h" | 79 #include "core/rendering/RenderView.h" |
79 #include "core/rendering/TextAutosizer.h" | 80 #include "core/rendering/TextAutosizer.h" |
80 #include "v8.h" | 81 #include "v8.h" |
81 #include "public/platform/Platform.h" | 82 #include "public/platform/Platform.h" |
82 #include "public/platform/WebFloatRect.h" | 83 #include "public/platform/WebFloatRect.h" |
83 #include "public/platform/WebThread.h" | 84 #include "public/platform/WebThread.h" |
84 #include "public/platform/WebUnitTestSupport.h" | 85 #include "public/platform/WebUnitTestSupport.h" |
85 #include "public/platform/WebURLResponse.h" | 86 #include "public/platform/WebURLResponse.h" |
86 #include "wtf/dtoa/utils.h" | 87 #include "wtf/dtoa/utils.h" |
87 #include "wtf/Forward.h" | 88 #include "wtf/Forward.h" |
| 89 #include <map> |
88 | 90 |
89 using namespace WebKit; | 91 using namespace WebKit; |
90 using WebCore::Document; | 92 using WebCore::Document; |
91 using WebCore::DocumentMarker; | 93 using WebCore::DocumentMarker; |
92 using WebCore::Element; | 94 using WebCore::Element; |
93 using WebCore::FloatRect; | 95 using WebCore::FloatRect; |
94 using WebCore::HitTestRequest; | 96 using WebCore::HitTestRequest; |
95 using WebCore::Range; | 97 using WebCore::Range; |
96 using WebKit::URLTestHelpers::toKURL; | 98 using WebKit::URLTestHelpers::toKURL; |
97 using WebKit::FrameTestHelpers::runPendingTasks; | 99 using WebKit::FrameTestHelpers::runPendingTasks; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascrip
t:document.body.appendChild(document.createTextNode('Clobbered'))"); | 280 FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), "javascrip
t:document.body.appendChild(document.createTextNode('Clobbered'))"); |
279 | 281 |
280 // Required to see any updates in contentAsText. | 282 // Required to see any updates in contentAsText. |
281 webViewHelper.webView()->layout(); | 283 webViewHelper.webView()->layout(); |
282 | 284 |
283 // Now retrieve the frame's text and ensure it wasn't modified by running ja
vascript. | 285 // Now retrieve the frame's text and ensure it wasn't modified by running ja
vascript. |
284 std::string content = std::string(webViewHelper.webView()->mainFrame()->cont
entAsText(1024).utf8().data()); | 286 std::string content = std::string(webViewHelper.webView()->mainFrame()->cont
entAsText(1024).utf8().data()); |
285 EXPECT_EQ(std::string::npos, content.find("Clobbered")); | 287 EXPECT_EQ(std::string::npos, content.find("Clobbered")); |
286 } | 288 } |
287 | 289 |
| 290 class CSSCallbackWebFrameClient : public WebFrameClient { |
| 291 public: |
| 292 CSSCallbackWebFrameClient() : m_updateCount(0) { } |
| 293 virtual void didMatchCSS(WebFrame*, const WebVector<WebString>& newlyMatchin
gSelectors, const WebVector<WebString>& stoppedMatchingSelectors) OVERRIDE; |
| 294 |
| 295 std::map<WebFrame*, std::set<std::string> > m_matchedSelectors; |
| 296 int m_updateCount; |
| 297 }; |
| 298 |
| 299 void CSSCallbackWebFrameClient::didMatchCSS(WebFrame* frame, const WebVector<Web
String>& newlyMatchingSelectors, const WebVector<WebString>& stoppedMatchingSele
ctors) |
| 300 { |
| 301 ++m_updateCount; |
| 302 std::set<std::string>& frameSelectors = m_matchedSelectors[frame]; |
| 303 for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) { |
| 304 std::string selector = newlyMatchingSelectors[i].utf8(); |
| 305 EXPECT_EQ(0U, frameSelectors.count(selector)) << selector; |
| 306 frameSelectors.insert(selector); |
| 307 } |
| 308 for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) { |
| 309 std::string selector = stoppedMatchingSelectors[i].utf8(); |
| 310 EXPECT_EQ(1U, frameSelectors.count(selector)) << selector; |
| 311 frameSelectors.erase(selector); |
| 312 } |
| 313 } |
| 314 |
| 315 class WebFrameCSSCallbackTest : public testing::Test { |
| 316 protected: |
| 317 WebFrameCSSCallbackTest() |
| 318 { |
| 319 |
| 320 m_frame = m_helper.initializeAndLoad("about:blank", true, &m_client)->ma
inFrame(); |
| 321 } |
| 322 |
| 323 ~WebFrameCSSCallbackTest() |
| 324 { |
| 325 EXPECT_EQ(1U, m_client.m_matchedSelectors.size()); |
| 326 } |
| 327 |
| 328 WebDocument doc() const |
| 329 { |
| 330 return m_frame->document(); |
| 331 } |
| 332 |
| 333 int updateCount() const |
| 334 { |
| 335 return m_client.m_updateCount; |
| 336 } |
| 337 |
| 338 const std::set<std::string>& matchedSelectors() |
| 339 { |
| 340 return m_client.m_matchedSelectors[m_frame]; |
| 341 } |
| 342 |
| 343 void loadHTML(const WebData& html) |
| 344 { |
| 345 m_frame->loadHTMLString(html, toKURL("about:blank")); |
| 346 runPendingTasks(); |
| 347 } |
| 348 |
| 349 void executeScript(const WebString& code) |
| 350 { |
| 351 m_frame->executeScript(WebScriptSource(code)); |
| 352 runPendingTasks(); |
| 353 } |
| 354 |
| 355 CSSCallbackWebFrameClient m_client; |
| 356 FrameTestHelpers::WebViewHelper m_helper; |
| 357 WebFrame* m_frame; |
| 358 }; |
| 359 |
| 360 TEST_F(WebFrameCSSCallbackTest, AuthorStyleSheet) |
| 361 { |
| 362 loadHTML( |
| 363 "<style>" |
| 364 // This stylesheet checks that the internal property and value can't be |
| 365 // set by a stylesheet, only WebDocument::watchCSSSelectors(). |
| 366 "div.initial_on { -internal-callback: none; }" |
| 367 "div.initial_off { -internal-callback: -internal-presence; }" |
| 368 "</style>" |
| 369 "<div class=\"initial_on\"></div>" |
| 370 "<div class=\"initial_off\"></div>"); |
| 371 |
| 372 std::vector<WebString> selectors; |
| 373 selectors.push_back(WebString::fromUTF8("div.initial_on")); |
| 374 m_frame->document().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 375 runPendingTasks(); |
| 376 EXPECT_EQ(1, updateCount()); |
| 377 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_on")); |
| 378 |
| 379 // Check that adding a watched selector calls back for already-present nodes
. |
| 380 selectors.push_back(WebString::fromUTF8("div.initial_off")); |
| 381 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 382 runPendingTasks(); |
| 383 EXPECT_EQ(2, updateCount()); |
| 384 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("div.initial_off", "div
.initial_on")); |
| 385 |
| 386 // Check that we can turn off callbacks for certain selectors. |
| 387 doc().watchCSSSelectors(WebVector<WebString>()); |
| 388 runPendingTasks(); |
| 389 EXPECT_EQ(3, updateCount()); |
| 390 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 391 } |
| 392 |
| 393 TEST_F(WebFrameCSSCallbackTest, SharedRenderStyle) |
| 394 { |
| 395 // Check that adding an element calls back when it matches an existing rule. |
| 396 std::vector<WebString> selectors; |
| 397 selectors.push_back(WebString::fromUTF8("span")); |
| 398 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 399 |
| 400 executeScript( |
| 401 "i1 = document.createElement('span');" |
| 402 "i1.id = 'first_span';" |
| 403 "document.body.appendChild(i1)"); |
| 404 EXPECT_EQ(1, updateCount()); |
| 405 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 406 |
| 407 // Adding a second element that shares a RenderStyle shouldn't call back. |
| 408 // We use <span>s to avoid default style rules that can set |
| 409 // RenderStyle::unique(). |
| 410 executeScript( |
| 411 "i2 = document.createElement('span');" |
| 412 "i2.id = 'second_span';" |
| 413 "i1 = document.getElementById('first_span');" |
| 414 "i1.parentNode.insertBefore(i2, i1.nextSibling);"); |
| 415 EXPECT_EQ(1, updateCount()); |
| 416 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 417 |
| 418 // Removing the first element shouldn't call back. |
| 419 executeScript( |
| 420 "i1 = document.getElementById('first_span');" |
| 421 "i1.parentNode.removeChild(i1);"); |
| 422 EXPECT_EQ(1, updateCount()); |
| 423 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 424 |
| 425 // But removing the second element *should* call back. |
| 426 executeScript( |
| 427 "i2 = document.getElementById('second_span');" |
| 428 "i2.parentNode.removeChild(i2);"); |
| 429 EXPECT_EQ(2, updateCount()); |
| 430 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 431 } |
| 432 |
| 433 TEST_F(WebFrameCSSCallbackTest, CatchesAttributeChange) |
| 434 { |
| 435 loadHTML("<span></span>"); |
| 436 |
| 437 std::vector<WebString> selectors; |
| 438 selectors.push_back(WebString::fromUTF8("span[attr=\"value\"]")); |
| 439 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 440 runPendingTasks(); |
| 441 |
| 442 EXPECT_EQ(0, updateCount()); |
| 443 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 444 |
| 445 executeScript( |
| 446 "document.querySelector('span').setAttribute('attr', 'value');"); |
| 447 EXPECT_EQ(1, updateCount()); |
| 448 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span[attr=\"value\"]")
); |
| 449 } |
| 450 |
| 451 TEST_F(WebFrameCSSCallbackTest, DisplayNone) |
| 452 { |
| 453 loadHTML("<div style='display:none'><span></span></div>"); |
| 454 |
| 455 std::vector<WebString> selectors; |
| 456 selectors.push_back(WebString::fromUTF8("span")); |
| 457 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 458 runPendingTasks(); |
| 459 |
| 460 EXPECT_EQ(0, updateCount()) << "Don't match elements in display:none trees."
; |
| 461 |
| 462 executeScript( |
| 463 "d = document.querySelector('div');" |
| 464 "d.style.display = 'block';"); |
| 465 EXPECT_EQ(1, updateCount()) << "Match elements when they become displayed."; |
| 466 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 467 |
| 468 executeScript( |
| 469 "d = document.querySelector('div');" |
| 470 "d.style.display = 'none';"); |
| 471 EXPECT_EQ(2, updateCount()) << "Unmatch elements when they become undisplaye
d."; |
| 472 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 473 |
| 474 executeScript( |
| 475 "s = document.querySelector('span');" |
| 476 "s.style.display = 'none';"); |
| 477 EXPECT_EQ(2, updateCount()) << "No effect from no-display'ing a span that's
already undisplayed."; |
| 478 |
| 479 executeScript( |
| 480 "d = document.querySelector('div');" |
| 481 "d.style.display = 'block';"); |
| 482 EXPECT_EQ(2, updateCount()) << "No effect from displaying a div whose span i
s display:none."; |
| 483 |
| 484 executeScript( |
| 485 "s = document.querySelector('span');" |
| 486 "s.style.display = 'inline';"); |
| 487 EXPECT_EQ(3, updateCount()) << "Now the span is visible and produces a callb
ack."; |
| 488 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 489 |
| 490 executeScript( |
| 491 "s = document.querySelector('span');" |
| 492 "s.style.display = 'none';"); |
| 493 EXPECT_EQ(4, updateCount()) << "Undisplaying the span directly should produc
e another callback."; |
| 494 EXPECT_THAT(matchedSelectors(), testing::ElementsAre()); |
| 495 } |
| 496 |
| 497 TEST_F(WebFrameCSSCallbackTest, Reparenting) |
| 498 { |
| 499 loadHTML( |
| 500 "<div id='d1'><span></span></div>" |
| 501 "<div id='d2'></div>"); |
| 502 |
| 503 std::vector<WebString> selectors; |
| 504 selectors.push_back(WebString::fromUTF8("span")); |
| 505 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 506 runPendingTasks(); |
| 507 |
| 508 EXPECT_EQ(1, updateCount()); |
| 509 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 510 |
| 511 executeScript( |
| 512 "s = document.querySelector('span');" |
| 513 "d2 = document.getElementById('d2');" |
| 514 "d2.appendChild(s);"); |
| 515 EXPECT_EQ(1, updateCount()) << "Just moving an element that continues to mat
ch shouldn't send a spurious callback."; |
| 516 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")); |
| 517 } |
| 518 |
| 519 TEST_F(WebFrameCSSCallbackTest, MultiSelector) |
| 520 { |
| 521 loadHTML("<span></span>"); |
| 522 |
| 523 // Check that selector lists match as the whole list, not as each element |
| 524 // independently. |
| 525 std::vector<WebString> selectors; |
| 526 selectors.push_back(WebString::fromUTF8("span")); |
| 527 selectors.push_back(WebString::fromUTF8("span,p")); |
| 528 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 529 |
| 530 runPendingTasks(); |
| 531 EXPECT_EQ(1, updateCount()); |
| 532 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span", "span, p")); |
| 533 } |
| 534 |
| 535 TEST_F(WebFrameCSSCallbackTest, InvalidSelector) |
| 536 { |
| 537 loadHTML("<p><span></span></p>"); |
| 538 |
| 539 // Build a list with one valid selector and one invalid. |
| 540 std::vector<WebString> selectors; |
| 541 selectors.push_back(WebString::fromUTF8("span")); |
| 542 selectors.push_back(WebString::fromUTF8("[")); // Invalid. |
| 543 selectors.push_back(WebString::fromUTF8("p span")); // Not compound. |
| 544 doc().watchCSSSelectors(WebVector<WebString>(selectors)); |
| 545 |
| 546 runPendingTasks(); |
| 547 EXPECT_EQ(1, updateCount()); |
| 548 EXPECT_THAT(matchedSelectors(), testing::ElementsAre("span")) |
| 549 << "An invalid selector shouldn't prevent other selectors from matching.
"; |
| 550 } |
| 551 |
288 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) | 552 TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) |
289 { | 553 { |
290 registerMockedHttpURLLoad("postmessage_test.html"); | 554 registerMockedHttpURLLoad("postmessage_test.html"); |
291 | 555 |
292 // Pass true to enable JavaScript. | 556 // Pass true to enable JavaScript. |
293 FrameTestHelpers::WebViewHelper webViewHelper; | 557 FrameTestHelpers::WebViewHelper webViewHelper; |
294 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true); | 558 webViewHelper.initializeAndLoad(m_baseURL + "postmessage_test.html", true); |
295 | 559 |
296 // Send a message with the correct origin. | 560 // Send a message with the correct origin. |
297 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL))
); | 561 WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL))
); |
(...skipping 3761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4059 TestStartStopCallbackWebViewClient client; | 4323 TestStartStopCallbackWebViewClient client; |
4060 FrameTestHelpers::WebViewHelper webViewHelper; | 4324 FrameTestHelpers::WebViewHelper webViewHelper; |
4061 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, 0, &cli
ent); | 4325 webViewHelper.initializeAndLoad(m_baseURL + "push_state.html", true, 0, &cli
ent); |
4062 runPendingTasks(); | 4326 runPendingTasks(); |
4063 | 4327 |
4064 EXPECT_EQ(client.startLoadingCount(), 2); | 4328 EXPECT_EQ(client.startLoadingCount(), 2); |
4065 EXPECT_EQ(client.stopLoadingCount(), 2); | 4329 EXPECT_EQ(client.stopLoadingCount(), 2); |
4066 } | 4330 } |
4067 | 4331 |
4068 } // namespace | 4332 } // namespace |
OLD | NEW |