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 37namespace WebCore { 38 39class CSSSelector; 40class Element; 41class RenderScrollbar; 42class RenderStyle; 43 44class SelectorChecker { 45 WTF_MAKE_NONCOPYABLE(SelectorChecker); 46public: 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 QualifiedName& selectorAttributeName, const AtomicStringImpl* value); 95 96 enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; 97 static unsigned determineLinkMatchType(const CSSSelector*); 98 99private: 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 109inline 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 120inline 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 131inline bool SelectorChecker::checkExactAttribute(const Element* element, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value) 132{ 133 if (!element->hasAttributesWithoutUpdate()) 134 return false; 135 unsigned size = element->attributeCount(); 136 for (unsigned i = 0; i < size; ++i) { 137 const Attribute* attribute = element->attributeItem(i); 138 if (attribute->matches(selectorAttributeName) && (!value || attribute->value().impl() == value)) 139 return true; 140 } 141 return false; 142} 143 144} 145 146#endif 147