Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: Source/web/tests/WebFrameTest.cpp

Issue 18371008: Add a WebDocument::watchCssSelectors(selectors) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@pinned
Patch Set: Add a test for watching dynamic attribute changes Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/web/WebDocument.cpp ('k') | public/web/WebDocument.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/web/WebDocument.cpp ('k') | public/web/WebDocument.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698