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

Side by Side Diff: Source/core/css/SelectorChecker.cpp

Issue 23819007: Have Node::document() return a reference instead of a pointer (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase on master Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 return SelectorFailsLocally; 147 return SelectorFailsLocally;
148 } else if (context.selector->isContentPseudoElement()) { 148 } else if (context.selector->isContentPseudoElement()) {
149 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint()) 149 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint())
150 return SelectorFailsLocally; 150 return SelectorFailsLocally;
151 } else { 151 } else {
152 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules) 152 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules)
153 return SelectorFailsLocally; 153 return SelectorFailsLocally;
154 154
155 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy pe()); 155 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy pe());
156 if (pseudoId == FIRST_LETTER) 156 if (pseudoId == FIRST_LETTER)
157 context.element->document()->styleSheetCollections()->setUsesFir stLetterRules(true); 157 context.element->document().styleSheetCollections()->setUsesFirs tLetterRules(true);
158 if (pseudoId != NOPSEUDO && m_mode != SharingRules) 158 if (pseudoId != NOPSEUDO && m_mode != SharingRules)
159 dynamicPseudo = pseudoId; 159 dynamicPseudo = pseudoId;
160 } 160 }
161 } 161 }
162 162
163 // The rest of the selectors has to match 163 // The rest of the selectors has to match
164 CSSSelector::Relation relation = context.selector->relation(); 164 CSSSelector::Relation relation = context.selector->relation();
165 165
166 // Prepare next selector 166 // Prepare next selector
167 const CSSSelector* historySelector = context.selector->tagHistory(); 167 const CSSSelector* historySelector = context.selector->tagHistory();
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoN ot); 428 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoN ot);
429 // We select between :visited and :link when applying. We don't know which one applied (or not) yet. 429 // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
430 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisi ted || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subConte xt.visitedMatchType == VisitedMatchEnabled)) 430 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisi ted || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subConte xt.visitedMatchType == VisitedMatchEnabled))
431 return true; 431 return true;
432 if (!checkOne(subContext, DOMSiblingTraversalStrategy())) 432 if (!checkOne(subContext, DOMSiblingTraversalStrategy()))
433 return true; 433 return true;
434 } 434 }
435 } else if (context.hasScrollbarPseudo) { 435 } else if (context.hasScrollbarPseudo) {
436 // CSS scrollbars match a specific subset of pseudo classes, and the y have specialized rules for each 436 // CSS scrollbars match a specific subset of pseudo classes, and the y have specialized rules for each
437 // (since there are no elements involved). 437 // (since there are no elements involved).
438 return checkScrollbarPseudoClass(context, element->document(), selec tor); 438 return checkScrollbarPseudoClass(context, &element->document(), sele ctor);
439 } else if (context.hasSelectionPseudo) { 439 } else if (context.hasSelectionPseudo) {
440 if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) 440 if (selector->pseudoType() == CSSSelector::PseudoWindowInactive)
441 return !element->document()->page()->focusController().isActive( ); 441 return !element->document().page()->focusController().isActive() ;
442 } 442 }
443 443
444 // Normal element pseudo class checking. 444 // Normal element pseudo class checking.
445 switch (selector->pseudoType()) { 445 switch (selector->pseudoType()) {
446 // Pseudo classes: 446 // Pseudo classes:
447 case CSSSelector::PseudoNot: 447 case CSSSelector::PseudoNot:
448 break; // Already handled up above. 448 break; // Already handled up above.
449 case CSSSelector::PseudoEmpty: 449 case CSSSelector::PseudoEmpty:
450 { 450 {
451 bool result = true; 451 bool result = true;
452 for (Node* n = element->firstChild(); n; n = n->nextSibling()) { 452 for (Node* n = element->firstChild(); n; n = n->nextSibling()) {
453 if (n->isElementNode()) { 453 if (n->isElementNode()) {
454 result = false; 454 result = false;
455 break; 455 break;
456 } 456 }
457 if (n->isTextNode()) { 457 if (n->isTextNode()) {
458 Text* textNode = toText(n); 458 Text* textNode = toText(n);
459 if (!textNode->data().isEmpty()) { 459 if (!textNode->data().isEmpty()) {
460 result = false; 460 result = false;
461 break; 461 break;
462 } 462 }
463 } 463 }
464 } 464 }
465 if (m_mode == ResolvingStyle) { 465 if (m_mode == ResolvingStyle) {
466 element->setStyleAffectedByEmpty(); 466 element->setStyleAffectedByEmpty();
467 if (context.elementStyle) 467 if (context.elementStyle)
468 context.elementStyle->setEmptyState(result); 468 context.elementStyle->setEmptyState(result);
469 else if (element->renderStyle() && (element->document()->sty leSheetCollections()->usesSiblingRules() || element->renderStyle()->unique())) 469 else if (element->renderStyle() && (element->document().styl eSheetCollections()->usesSiblingRules() || element->renderStyle()->unique()))
470 element->renderStyle()->setEmptyState(result); 470 element->renderStyle()->setEmptyState(result);
471 } 471 }
472 return result; 472 return result;
473 } 473 }
474 case CSSSelector::PseudoFirstChild: 474 case CSSSelector::PseudoFirstChild:
475 // first-child matches the first child that is an element 475 // first-child matches the first child that is an element
476 if (Element* parent = element->parentElement()) { 476 if (Element* parent = element->parentElement()) {
477 bool result = siblingTraversalStrategy.isFirstChild(element); 477 bool result = siblingTraversalStrategy.isFirstChild(element);
478 if (m_mode == ResolvingStyle) { 478 if (m_mode == ResolvingStyle) {
479 RenderStyle* childStyle = context.elementStyle ? context.ele mentStyle : element->renderStyle(); 479 RenderStyle* childStyle = context.elementStyle ? context.ele mentStyle : element->renderStyle();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 parent->setChildrenAffectedByBackwardPositionalRules(); 594 parent->setChildrenAffectedByBackwardPositionalRules();
595 if (!parent->isFinishedParsingChildren()) 595 if (!parent->isFinishedParsingChildren())
596 return false; 596 return false;
597 597
598 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte r(element, element->tagQName()); 598 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte r(element, element->tagQName());
599 if (selector->matchNth(count)) 599 if (selector->matchNth(count))
600 return true; 600 return true;
601 } 601 }
602 break; 602 break;
603 case CSSSelector::PseudoTarget: 603 case CSSSelector::PseudoTarget:
604 if (element == element->document()->cssTarget()) 604 if (element == element->document().cssTarget())
605 return true; 605 return true;
606 break; 606 break;
607 case CSSSelector::PseudoAny: 607 case CSSSelector::PseudoAny:
608 { 608 {
609 SelectorCheckingContext subContext(context); 609 SelectorCheckingContext subContext(context);
610 subContext.isSubSelector = true; 610 subContext.isSubSelector = true;
611 PseudoId ignoreDynamicPseudo = NOPSEUDO; 611 PseudoId ignoreDynamicPseudo = NOPSEUDO;
612 for (subContext.selector = selector->selectorList()->first(); su bContext.selector; subContext.selector = CSSSelectorList::next(subContext.select or)) { 612 for (subContext.selector = selector->selectorList()->first(); su bContext.selector; subContext.selector = CSSSelectorList::next(subContext.select or)) {
613 if (match(subContext, ignoreDynamicPseudo, siblingTraversalS trategy) == SelectorMatches) 613 if (match(subContext, ignoreDynamicPseudo, siblingTraversalS trategy) == SelectorMatches)
614 return true; 614 return true;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 } 666 }
667 if (element->active() || InspectorInstrumentation::forcePseudoSt ate(element, CSSSelector::PseudoActive)) 667 if (element->active() || InspectorInstrumentation::forcePseudoSt ate(element, CSSSelector::PseudoActive))
668 return true; 668 return true;
669 } 669 }
670 break; 670 break;
671 case CSSSelector::PseudoEnabled: 671 case CSSSelector::PseudoEnabled:
672 if (element && (element->isFormControlElement() || element->hasTagNa me(optionTag) || isHTMLOptGroupElement(element))) 672 if (element && (element->isFormControlElement() || element->hasTagNa me(optionTag) || isHTMLOptGroupElement(element)))
673 return !element->isDisabledFormControl(); 673 return !element->isDisabledFormControl();
674 break; 674 break;
675 case CSSSelector::PseudoFullPageMedia: 675 case CSSSelector::PseudoFullPageMedia:
676 return element && element->document()->isMediaDocument(); 676 return element && element->document().isMediaDocument();
677 break; 677 break;
678 case CSSSelector::PseudoDefault: 678 case CSSSelector::PseudoDefault:
679 return element && element->isDefaultButtonForForm(); 679 return element && element->isDefaultButtonForForm();
680 case CSSSelector::PseudoDisabled: 680 case CSSSelector::PseudoDisabled:
681 if (element && (element->isFormControlElement() || element->hasTagNa me(optionTag) || isHTMLOptGroupElement(element))) 681 if (element && (element->isFormControlElement() || element->hasTagNa me(optionTag) || isHTMLOptGroupElement(element)))
682 return element->isDisabledFormControl(); 682 return element->isDisabledFormControl();
683 break; 683 break;
684 case CSSSelector::PseudoReadOnly: 684 case CSSSelector::PseudoReadOnly:
685 return element && element->matchesReadOnlyPseudoClass(); 685 return element && element->matchesReadOnlyPseudoClass();
686 case CSSSelector::PseudoReadWrite: 686 case CSSSelector::PseudoReadWrite:
687 return element && element->matchesReadWritePseudoClass(); 687 return element && element->matchesReadWritePseudoClass();
688 case CSSSelector::PseudoOptional: 688 case CSSSelector::PseudoOptional:
689 return element && element->isOptionalFormControl(); 689 return element && element->isOptionalFormControl();
690 case CSSSelector::PseudoRequired: 690 case CSSSelector::PseudoRequired:
691 return element && element->isRequiredFormControl(); 691 return element && element->isRequiredFormControl();
692 case CSSSelector::PseudoValid: 692 case CSSSelector::PseudoValid:
693 if (!element) 693 if (!element)
694 return false; 694 return false;
695 element->document()->setContainsValidityStyleRules(); 695 element->document().setContainsValidityStyleRules();
696 return element->willValidate() && element->isValidFormControlElement (); 696 return element->willValidate() && element->isValidFormControlElement ();
697 case CSSSelector::PseudoInvalid: 697 case CSSSelector::PseudoInvalid:
698 if (!element) 698 if (!element)
699 return false; 699 return false;
700 element->document()->setContainsValidityStyleRules(); 700 element->document().setContainsValidityStyleRules();
701 return element->willValidate() && !element->isValidFormControlElemen t(); 701 return element->willValidate() && !element->isValidFormControlElemen t();
702 case CSSSelector::PseudoChecked: 702 case CSSSelector::PseudoChecked:
703 { 703 {
704 if (!element) 704 if (!element)
705 break; 705 break;
706 if (element->hasTagName(inputTag)) { 706 if (element->hasTagName(inputTag)) {
707 HTMLInputElement* inputElement = toHTMLInputElement(element) ; 707 HTMLInputElement* inputElement = toHTMLInputElement(element) ;
708 // Even though WinIE allows checked and indeterminate to 708 // Even though WinIE allows checked and indeterminate to
709 // co-exist, the CSS selector spec says that you can't be 709 // co-exist, the CSS selector spec says that you can't be
710 // both checked and indeterminate. We will behave like WinIE 710 // both checked and indeterminate. We will behave like WinIE
711 // behind the scenes and just obey the CSS spec here in the 711 // behind the scenes and just obey the CSS spec here in the
712 // test for matching the pseudo. 712 // test for matching the pseudo.
713 if (inputElement->shouldAppearChecked() && !inputElement->sh ouldAppearIndeterminate()) 713 if (inputElement->shouldAppearChecked() && !inputElement->sh ouldAppearIndeterminate())
714 return true; 714 return true;
715 } else if (element->hasTagName(optionTag) && toHTMLOptionElement (element)->selected()) 715 } else if (element->hasTagName(optionTag) && toHTMLOptionElement (element)->selected())
716 return true; 716 return true;
717 break; 717 break;
718 } 718 }
719 case CSSSelector::PseudoIndeterminate: 719 case CSSSelector::PseudoIndeterminate:
720 return element && element->shouldAppearIndeterminate(); 720 return element && element->shouldAppearIndeterminate();
721 case CSSSelector::PseudoRoot: 721 case CSSSelector::PseudoRoot:
722 if (element == element->document()->documentElement()) 722 if (element == element->document().documentElement())
723 return true; 723 return true;
724 break; 724 break;
725 case CSSSelector::PseudoLang: 725 case CSSSelector::PseudoLang:
726 { 726 {
727 AtomicString value; 727 AtomicString value;
728 if (element->isWebVTTElement()) 728 if (element->isWebVTTElement())
729 value = toWebVTTElement(element)->language(); 729 value = toWebVTTElement(element)->language();
730 else 730 else
731 value = element->computeInheritedLanguage(); 731 value = element->computeInheritedLanguage();
732 const AtomicString& argument = selector->argument(); 732 const AtomicString& argument = selector->argument();
733 if (value.isEmpty() || !value.startsWith(argument, false)) 733 if (value.isEmpty() || !value.startsWith(argument, false))
734 break; 734 break;
735 if (value.length() != argument.length() && value[argument.length ()] != '-') 735 if (value.length() != argument.length() && value[argument.length ()] != '-')
736 break; 736 break;
737 return true; 737 return true;
738 } 738 }
739 case CSSSelector::PseudoFullScreen: 739 case CSSSelector::PseudoFullScreen:
740 // While a Document is in the fullscreen state, and the document's c urrent fullscreen 740 // While a Document is in the fullscreen state, and the document's c urrent fullscreen
741 // element is an element in the document, the 'full-screen' pseudocl ass applies to 741 // element is an element in the document, the 'full-screen' pseudocl ass applies to
742 // that element. Also, an <iframe>, <object> or <embed> element whos e child browsing 742 // that element. Also, an <iframe>, <object> or <embed> element whos e child browsing
743 // context's Document is in the fullscreen state has the 'full-scree n' pseudoclass applied. 743 // context's Document is in the fullscreen state has the 'full-scree n' pseudoclass applied.
744 if (element->isFrameElementBase() && element->containsFullScreenElem ent()) 744 if (element->isFrameElementBase() && element->containsFullScreenElem ent())
745 return true; 745 return true;
746 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fro mIfExists(element->document())) { 746 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fro mIfExists(&element->document())) {
747 if (!fullscreen->webkitIsFullScreen()) 747 if (!fullscreen->webkitIsFullScreen())
748 return false; 748 return false;
749 return element == fullscreen->webkitCurrentFullScreenElement(); 749 return element == fullscreen->webkitCurrentFullScreenElement();
750 } 750 }
751 return false; 751 return false;
752 case CSSSelector::PseudoFullScreenAncestor: 752 case CSSSelector::PseudoFullScreenAncestor:
753 return element->containsFullScreenElement(); 753 return element->containsFullScreenElement();
754 case CSSSelector::PseudoFullScreenDocument: 754 case CSSSelector::PseudoFullScreenDocument:
755 // While a Document is in the fullscreen state, the 'full-screen-doc ument' pseudoclass applies 755 // While a Document is in the fullscreen state, the 'full-screen-doc ument' pseudoclass applies
756 // to all elements of that Document. 756 // to all elements of that Document.
757 if (!FullscreenElementStack::isFullScreen(element->document())) 757 if (!FullscreenElementStack::isFullScreen(&element->document()))
758 return false; 758 return false;
759 return true; 759 return true;
760 case CSSSelector::PseudoSeamlessDocument: 760 case CSSSelector::PseudoSeamlessDocument:
761 // While a document is rendered in a seamless iframe, the 'seamless- document' pseudoclass applies 761 // While a document is rendered in a seamless iframe, the 'seamless- document' pseudoclass applies
762 // to all elements of that Document. 762 // to all elements of that Document.
763 return element->document()->shouldDisplaySeamlesslyWithParent(); 763 return element->document().shouldDisplaySeamlesslyWithParent();
764 case CSSSelector::PseudoInRange: 764 case CSSSelector::PseudoInRange:
765 if (!element) 765 if (!element)
766 return false; 766 return false;
767 element->document()->setContainsValidityStyleRules(); 767 element->document().setContainsValidityStyleRules();
768 return element->isInRange(); 768 return element->isInRange();
769 case CSSSelector::PseudoOutOfRange: 769 case CSSSelector::PseudoOutOfRange:
770 if (!element) 770 if (!element)
771 return false; 771 return false;
772 element->document()->setContainsValidityStyleRules(); 772 element->document().setContainsValidityStyleRules();
773 return element->isOutOfRange(); 773 return element->isOutOfRange();
774 case CSSSelector::PseudoFutureCue: 774 case CSSSelector::PseudoFutureCue:
775 return (element->isWebVTTElement() && !toWebVTTElement(element)->isP astNode()); 775 return (element->isWebVTTElement() && !toWebVTTElement(element)->isP astNode());
776 case CSSSelector::PseudoPastCue: 776 case CSSSelector::PseudoPastCue:
777 return (element->isWebVTTElement() && toWebVTTElement(element)->isPa stNode()); 777 return (element->isWebVTTElement() && toWebVTTElement(element)->isPa stNode());
778 778
779 case CSSSelector::PseudoScope: 779 case CSSSelector::PseudoScope:
780 { 780 {
781 const Node* contextualReferenceNode = !context.scope || (context .behaviorAtBoundary & BoundaryBehaviorMask) == CrossesBoundary ? element->docume nt()->documentElement() : context.scope; 781 const Node* contextualReferenceNode = !context.scope || (context .behaviorAtBoundary & BoundaryBehaviorMask) == CrossesBoundary ? element->docume nt().documentElement() : context.scope;
782 if (element == contextualReferenceNode) 782 if (element == contextualReferenceNode)
783 return true; 783 return true;
784 break; 784 break;
785 } 785 }
786 786
787 case CSSSelector::PseudoUnresolved: 787 case CSSSelector::PseudoUnresolved:
788 if (element->isUnresolvedCustomElement()) 788 if (element->isUnresolvedCustomElement())
789 return true; 789 return true;
790 break; 790 break;
791 791
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 if (relation != CSSSelector::Descendant && relation != CSSSelector::Chil d) 975 if (relation != CSSSelector::Descendant && relation != CSSSelector::Chil d)
976 return linkMatchType; 976 return linkMatchType;
977 if (linkMatchType != MatchAll) 977 if (linkMatchType != MatchAll)
978 return linkMatchType; 978 return linkMatchType;
979 } 979 }
980 return linkMatchType; 980 return linkMatchType;
981 } 981 }
982 982
983 bool SelectorChecker::isFrameFocused(const Element* element) 983 bool SelectorChecker::isFrameFocused(const Element* element)
984 { 984 {
985 return element->document()->frame() && element->document()->frame()->selecti on()->isFocusedAndActive(); 985 return element->document().frame() && element->document().frame()->selection ()->isFocusedAndActive();
986 } 986 }
987 987
988 bool SelectorChecker::matchesFocusPseudoClass(const Element* element) 988 bool SelectorChecker::matchesFocusPseudoClass(const Element* element)
989 { 989 {
990 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(element) , CSSSelector::PseudoFocus)) 990 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(element) , CSSSelector::PseudoFocus))
991 return true; 991 return true;
992 return element->focused() && isFrameFocused(element); 992 return element->focused() && isFrameFocused(element);
993 } 993 }
994 994
995 template 995 template
996 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, Ps eudoId&, const DOMSiblingTraversalStrategy&) const; 996 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, Ps eudoId&, const DOMSiblingTraversalStrategy&) const;
997 997
998 template 998 template
999 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, Ps eudoId&, const ShadowDOMSiblingTraversalStrategy&) const; 999 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, Ps eudoId&, const ShadowDOMSiblingTraversalStrategy&) const;
1000 1000
1001 } 1001 }
OLDNEW
« no previous file with comments | « Source/core/css/SVGCSSComputedStyleDeclaration.cpp ('k') | Source/core/css/StyleSheetContents.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698