Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / SelectorChecker.h
index fd98ccc..d192d48 100644 (file)
@@ -32,7 +32,7 @@
 #include "core/dom/Element.h"
 #include "platform/scroll/ScrollTypes.h"
 
-namespace WebCore {
+namespace blink {
 
 class CSSSelector;
 class ContainerNode;
@@ -47,29 +47,22 @@ public:
     enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled };
     enum Mode { ResolvingStyle = 0, CollectingStyleRules, CollectingCSSRules, QueryingRules, SharingRules };
     explicit SelectorChecker(Document&, Mode);
-    enum BehaviorAtBoundary {
-        DoesNotCrossBoundary = 0,
-        // FIXME: refactor to remove BoundaryBehavior (i.e. DoesNotCrossBoundary and StaysWithinTreeScope).
-        StaysWithinTreeScope = 2,
-        BoundaryBehaviorMask = 3, // 2bit for boundary behavior
-        ScopeContainsLastMatchedElement = 4,
-        ScopeIsShadowHost = 8,
-        TreatShadowHostAsNormalScope = 16,
-
-        ScopeIsShadowHostInPseudoHostParameter = ScopeIsShadowHost | TreatShadowHostAsNormalScope
-    };
-
-    enum MatchingTagType {
-        MatchingElement = 0,
-        MatchingHostInItsShadowTree
+    enum ContextFlags {
+        // FIXME: Revmoe DefaultBehavior.
+        DefaultBehavior = 0,
+        ScopeContainsLastMatchedElement = 1,
+        TreatShadowHostAsNormalScope = 2,
     };
 
     struct SelectorCheckingContext {
+        STACK_ALLOCATED();
+    public:
         // Initial selector constructor
         SelectorCheckingContext(const CSSSelector& selector, Element* element, VisitedMatchType visitedMatchType)
             : selector(&selector)
             , element(element)
-            , scope(0)
+            , previousElement(nullptr)
+            , scope(nullptr)
             , visitedMatchType(visitedMatchType)
             , pseudoId(NOPSEUDO)
             , elementStyle(0)
@@ -78,12 +71,15 @@ public:
             , isSubSelector(false)
             , hasScrollbarPseudo(false)
             , hasSelectionPseudo(false)
-            , behaviorAtBoundary(DoesNotCrossBoundary)
-        { }
+            , isUARule(false)
+            , contextFlags(DefaultBehavior)
+        {
+        }
 
         const CSSSelector* selector;
-        Element* element;
-        const ContainerNode* scope;
+        RawPtrWillBeMember<Element> element;
+        RawPtrWillBeMember<Element> previousElement;
+        RawPtrWillBeMember<const ContainerNode> scope;
         VisitedMatchType visitedMatchType;
         PseudoId pseudoId;
         RenderStyle* elementStyle;
@@ -92,7 +88,8 @@ public:
         bool isSubSelector;
         bool hasScrollbarPseudo;
         bool hasSelectionPseudo;
-        BehaviorAtBoundary behaviorAtBoundary;
+        bool isUARule;
+        ContextFlags contextFlags;
     };
 
     struct MatchResult {
@@ -114,15 +111,17 @@ public:
 
     Mode mode() const { return m_mode; }
 
-    static bool tagMatches(const Element&, const QualifiedName&, MatchingTagType = MatchingElement);
+    static bool tagMatches(const Element&, const QualifiedName&);
     static bool isCommonPseudoClassSelector(const CSSSelector&);
     static bool matchesFocusPseudoClass(const Element&);
+    static bool matchesSpatialNavigationFocusPseudoClass(const Element&);
+    static bool matchesListBoxPseudoClass(const Element&);
     static bool checkExactAttribute(const Element&, const QualifiedName& selectorAttributeName, const StringImpl* value);
 
     enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
     static unsigned determineLinkMatchType(const CSSSelector&);
 
-    static bool isHostInItsShadowTree(const Element&, BehaviorAtBoundary, const ContainerNode* scope);
+    static bool isHostInItsShadowTree(const Element&, const ContainerNode* scope);
 
 private:
     template<typename SiblingTraversalStrategy>
@@ -131,10 +130,10 @@ private:
     Match matchForRelation(const SelectorCheckingContext&, const SiblingTraversalStrategy&, MatchResult*) const;
     template<typename SiblingTraversalStrategy>
     Match matchForShadowDistributed(const Element*, const SiblingTraversalStrategy&, SelectorCheckingContext& nextContext, MatchResult* = 0) const;
+    template<typename SiblingTraversalStrategy>
+    Match matchForPseudoShadow(const ContainerNode*, const SelectorCheckingContext&, const SiblingTraversalStrategy&, MatchResult*) const;
 
     bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector&) const;
-    Element* parentElement(const SelectorCheckingContext&, bool allowToCrossBoundary = false) const;
-    bool scopeContainsLastMatchedElement(const SelectorCheckingContext&) const;
 
     static bool isFrameFocused(const Element&);
 
@@ -145,7 +144,7 @@ private:
 
 inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector& selector)
 {
-    if (selector.m_match != CSSSelector::PseudoClass)
+    if (selector.match() != CSSSelector::PseudoClass)
         return false;
     CSSSelector::PseudoType pseudoType = selector.pseudoType();
     return pseudoType == CSSSelector::PseudoLink
@@ -154,12 +153,12 @@ inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector& sele
         || pseudoType == CSSSelector::PseudoFocus;
 }
 
-inline bool SelectorChecker::tagMatches(const Element& element, const QualifiedName& tagQName, MatchingTagType matchingTagType)
+inline bool SelectorChecker::tagMatches(const Element& element, const QualifiedName& tagQName)
 {
     if (tagQName == anyQName())
         return true;
     const AtomicString& localName = tagQName.localName();
-    if (localName != starAtom && (localName != element.localName() || matchingTagType == MatchingHostInItsShadowTree))
+    if (localName != starAtom && localName != element.localName())
         return false;
     const AtomicString& namespaceURI = tagQName.namespaceURI();
     return namespaceURI == starAtom || namespaceURI == element.namespaceURI();
@@ -167,20 +166,18 @@ inline bool SelectorChecker::tagMatches(const Element& element, const QualifiedN
 
 inline bool SelectorChecker::checkExactAttribute(const Element& element, const QualifiedName& selectorAttributeName, const StringImpl* value)
 {
-    if (!element.hasAttributesWithoutUpdate())
-        return false;
-    unsigned size = element.attributeCount();
-    for (unsigned i = 0; i < size; ++i) {
-        const Attribute* attribute = element.attributeItem(i);
-        if (attribute->matches(selectorAttributeName) && (!value || attribute->value().impl() == value))
+    AttributeCollection attributes = element.attributesWithoutUpdate();
+    AttributeCollection::iterator end = attributes.end();
+    for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
+        if (it->matches(selectorAttributeName) && (!value || it->value().impl() == value))
             return true;
     }
     return false;
 }
 
-inline bool SelectorChecker::isHostInItsShadowTree(const Element& element, BehaviorAtBoundary behaviorAtBoundary, const ContainerNode* scope)
+inline bool SelectorChecker::isHostInItsShadowTree(const Element& element, const ContainerNode* scope)
 {
-    return (behaviorAtBoundary & (ScopeIsShadowHost | TreatShadowHostAsNormalScope)) == ScopeIsShadowHost && scope == element;
+    return scope && scope->isInShadowTree() && scope->shadowHost() == element;
 }
 
 }