selectors should match attribute name with case sensitivity based on element & docume...
[WebKit-https.git] / Source / WebCore / css / SelectorChecker.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.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.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@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.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 "CSSSelector.h"
32 #include "InspectorInstrumentation.h"
33 #include "SpaceSplitString.h"
34 #include <wtf/HashSet.h>
35 #include <wtf/Vector.h>
36
37 namespace WebCore {
38
39 class CSSSelector;
40 class Element;
41 class RenderScrollbar;
42 class RenderStyle;
43
44 class SelectorChecker {
45     WTF_MAKE_NONCOPYABLE(SelectorChecker);
46 public:
47     enum Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely };
48     enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled };
49     enum Mode { ResolvingStyle = 0, CollectingRules, QueryingRules, SharingRules };
50     explicit SelectorChecker(Document*, Mode);
51     enum BehaviorAtBoundary { DoesNotCrossBoundary, CrossesBoundary, StaysWithinTreeScope };
52
53     struct SelectorCheckingContext {
54         // Initial selector constructor
55         SelectorCheckingContext(const CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType)
56             : selector(selector)
57             , element(element)
58             , scope(0)
59             , visitedMatchType(visitedMatchType)
60             , pseudoId(NOPSEUDO)
61             , elementStyle(0)
62             , scrollbar(0)
63             , scrollbarPart(NoPart)
64             , isSubSelector(false)
65             , hasScrollbarPseudo(false)
66             , hasSelectionPseudo(false)
67             , behaviorAtBoundary(DoesNotCrossBoundary)
68         { }
69
70         const CSSSelector* selector;
71         Element* element;
72         const ContainerNode* scope;
73         VisitedMatchType visitedMatchType;
74         PseudoId pseudoId;
75         RenderStyle* elementStyle;
76         RenderScrollbar* scrollbar;
77         ScrollbarPart scrollbarPart;
78         bool isSubSelector;
79         bool hasScrollbarPseudo;
80         bool hasSelectionPseudo;
81         BehaviorAtBoundary behaviorAtBoundary;
82     };
83
84     Match match(const SelectorCheckingContext&, PseudoId&) const;
85     bool checkOne(const SelectorCheckingContext&) const;
86
87     bool strictParsing() const { return m_strictParsing; }
88
89     Mode mode() const { return m_mode; }
90
91     static bool tagMatches(const Element*, const QualifiedName&);
92     static bool isCommonPseudoClassSelector(const CSSSelector*);
93     static bool matchesFocusPseudoClass(const Element*);
94     static bool checkExactAttribute(const Element*, const CSSSelector*, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value);
95
96     enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
97     static unsigned determineLinkMatchType(const CSSSelector*);
98
99 private:
100     bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector*) const;
101
102     static bool isFrameFocused(const Element*);
103
104     bool m_strictParsing;
105     bool m_documentIsHTML;
106     Mode m_mode;
107 };
108
109 inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector)
110 {
111     if (selector->m_match != CSSSelector::PseudoClass)
112         return false;
113     CSSSelector::PseudoType pseudoType = selector->pseudoType();
114     return pseudoType == CSSSelector::PseudoLink
115         || pseudoType == CSSSelector::PseudoAnyLink
116         || pseudoType == CSSSelector::PseudoVisited
117         || pseudoType == CSSSelector::PseudoFocus;
118 }
119
120 inline bool SelectorChecker::tagMatches(const Element* element, const QualifiedName& tagQName)
121 {
122     if (tagQName == anyQName())
123         return true;
124     const AtomicString& localName = tagQName.localName();
125     if (localName != starAtom && localName != element->localName())
126         return false;
127     const AtomicString& namespaceURI = tagQName.namespaceURI();
128     return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
129 }
130
131 inline bool SelectorChecker::checkExactAttribute(const Element* element, const CSSSelector* selector, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value)
132 {
133     if (!element->hasAttributesWithoutUpdate())
134         return false;
135     const AtomicString& localName = element->isHTMLElement() ? selector->attributeCanonicalLocalName() : selectorAttributeName.localName();
136     unsigned size = element->attributeCount();
137     for (unsigned i = 0; i < size; ++i) {
138         const Attribute* attribute = element->attributeItem(i);
139         if (attribute->matches(selectorAttributeName.prefix(), localName, selectorAttributeName.namespaceURI()) && (!value || attribute->value().impl() == value))
140             return true;
141     }
142     return false;
143 }
144
145 }
146
147 #endif