1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Library General Public 14 * License as published by the Free Software Foundation; either 15 * version 2 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * Library General Public License for more details. 21 * 22 * You should have received a copy of the GNU Library General Public License 23 * along with this library; see the file COPYING.LIB. If not, write to 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 * Boston, MA 02110-1301, USA. 26 */ 27 28 #ifndef SelectorChecker_h 29 #define SelectorChecker_h 30 31 #include "core/css/CSSSelector.h" 32 #include "core/inspector/InspectorInstrumentation.h" 33 34 namespace WebCore { 35 36 class CSSSelector; 37 class Element; 38 class RenderScrollbar; 39 class RenderStyle; 40 41 class SelectorChecker { 42 WTF_MAKE_NONCOPYABLE(SelectorChecker); 43 public: 44 enum Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely }; 45 enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled }; 46 enum Mode { ResolvingStyle = 0, CollectingRules, QueryingRules, SharingRules }; 47 explicit SelectorChecker(Document*, Mode); 48 enum BehaviorAtBoundary { 49 DoesNotCrossBoundary = 0, 50 CrossesBoundary = 1, 51 StaysWithinTreeScope = 2, 52 BoundaryBehaviorMask = 3, // 2bit for boundary behavior 53 ScopeContainsLastMatchedElement = 4, 54 ScopeIsShadowHost = 8 55 }; 56 57 struct SelectorCheckingContext { 58 // Initial selector constructor 59 SelectorCheckingContext(const CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType) 60 : selector(selector) 61 , element(element) 62 , scope(0) 63 , visitedMatchType(visitedMatchType) 64 , pseudoId(NOPSEUDO) 65 , elementStyle(0) 66 , scrollbar(0) 67 , scrollbarPart(NoPart) 68 , isSubSelector(false) 69 , hasScrollbarPseudo(false) 70 , hasSelectionPseudo(false) 71 , behaviorAtBoundary(DoesNotCrossBoundary) 72 { } 73 74 const CSSSelector* selector; 75 Element* element; 76 const ContainerNode* scope; 77 VisitedMatchType visitedMatchType; 78 PseudoId pseudoId; 79 RenderStyle* elementStyle; 80 RenderScrollbar* scrollbar; 81 ScrollbarPart scrollbarPart; 82 bool isSubSelector; 83 bool hasScrollbarPseudo; 84 bool hasSelectionPseudo; 85 BehaviorAtBoundary behaviorAtBoundary; 86 }; 87 88 template<typename SiblingTraversalStrategy> 89 Match match(const SelectorCheckingContext&, PseudoId&, const SiblingTraversalStrategy&) const; 90 91 template<typename SiblingTraversalStrategy> 92 Match matchForShadowDistributed(const Element*, const SiblingTraversalStrategy&, PseudoId&, SelectorCheckingContext& nextContext) const; 93 94 template<typename SiblingTraversalStrategy> 95 bool checkOne(const SelectorCheckingContext&, const SiblingTraversalStrategy&) const; 96 97 bool strictParsing() const { return m_strictParsing; } 98 99 Mode mode() const { return m_mode; } 100 101 static bool tagMatches(const Element*, const QualifiedName&); 102 static bool isCommonPseudoClassSelector(const CSSSelector*); 103 static bool matchesFocusPseudoClass(const Element*); 104 static bool checkExactAttribute(const Element*, const QualifiedName& selectorAttributeName, const StringImpl* value); 105 106 enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; 107 static unsigned determineLinkMatchType(const CSSSelector*); 108 109 private: 110 bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector*) const; 111 Element* parentElement(const SelectorCheckingContext&) const; 112 bool scopeContainsLastMatchedElement(const SelectorCheckingContext&) const; 113 114 static bool isFrameFocused(const Element*); 115 116 bool m_strictParsing; 117 bool m_documentIsHTML; 118 Mode m_mode; 119 }; 120 121 inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector) 122 { 123 if (selector->m_match != CSSSelector::PseudoClass) 124 return false; 125 CSSSelector::PseudoType pseudoType = selector->pseudoType(); 126 return pseudoType == CSSSelector::PseudoLink 127 || pseudoType == CSSSelector::PseudoAnyLink 128 || pseudoType == CSSSelector::PseudoVisited 129 || pseudoType == CSSSelector::PseudoFocus; 130 } 131 132 inline bool SelectorChecker::tagMatches(const Element* element, const QualifiedName& tagQName) 133 { 134 if (tagQName == anyQName()) 135 return true; 136 const AtomicString& localName = tagQName.localName(); 137 if (localName != starAtom && localName != element->localName()) 138 return false; 139 const AtomicString& namespaceURI = tagQName.namespaceURI(); 140 return namespaceURI == starAtom || namespaceURI == element->namespaceURI(); 141 } 142 143 inline bool SelectorChecker::checkExactAttribute(const Element* element, const QualifiedName& selectorAttributeName, const StringImpl* value) 144 { 145 if (!element->hasAttributesWithoutUpdate()) 146 return false; 147 unsigned size = element->attributeCount(); 148 for (unsigned i = 0; i < size; ++i) { 149 const Attribute* attribute = element->attributeItem(i); 150 if (attribute->matches(selectorAttributeName) && (!value || attribute->value().impl() == value)) 151 return true; 152 } 153 return false; 154 } 155 156 } 157 158 #endif 159