1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef RuleFeature_h
23#define RuleFeature_h
24
25#include "core/css/CSSSelector.h"
26#include "core/css/invalidation/StyleInvalidator.h"
27#include "wtf/Forward.h"
28#include "wtf/HashSet.h"
29#include "wtf/text/AtomicStringHash.h"
30
31namespace blink {
32
33class CSSSelectorList;
34class DescendantInvalidationSet;
35class QualifiedName;
36class RuleData;
37class SpaceSplitString;
38class StyleRule;
39
40struct RuleFeature {
41    ALLOW_ONLY_INLINE_ALLOCATION();
42public:
43    RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin);
44
45    void trace(Visitor*);
46
47    RawPtrWillBeMember<StyleRule> rule;
48    unsigned selectorIndex;
49    bool hasDocumentSecurityOrigin;
50};
51
52class RuleFeatureSet {
53    DISALLOW_ALLOCATION();
54public:
55    RuleFeatureSet();
56    ~RuleFeatureSet();
57
58    void add(const RuleFeatureSet&);
59    void clear();
60
61    void collectFeaturesFromRuleData(const RuleData&);
62
63    bool usesSiblingRules() const { return !siblingRules.isEmpty(); }
64    bool usesFirstLineRules() const { return m_metadata.usesFirstLineRules; }
65
66    unsigned maxDirectAdjacentSelectors() const { return m_metadata.maxDirectAdjacentSelectors; }
67    void setMaxDirectAdjacentSelectors(unsigned value)  { m_metadata.maxDirectAdjacentSelectors = std::max(value, m_metadata.maxDirectAdjacentSelectors); }
68
69    bool hasSelectorForAttribute(const AtomicString& attributeName) const
70    {
71        ASSERT(!attributeName.isEmpty());
72        return m_attributeInvalidationSets.contains(attributeName);
73    }
74
75    bool hasSelectorForClass(const AtomicString& classValue) const
76    {
77        ASSERT(!classValue.isEmpty());
78        return m_classInvalidationSets.contains(classValue);
79    }
80
81    bool hasSelectorForId(const AtomicString& idValue) const { return m_idInvalidationSets.contains(idValue); }
82    bool hasSelectorForPseudoType(CSSSelector::PseudoType pseudo) const { return m_pseudoInvalidationSets.contains(pseudo); }
83
84    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element&);
85    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element&);
86    void scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element&);
87    void scheduleStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, Element&);
88    void scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoType, Element&);
89
90    bool hasIdsInSelectors() const
91    {
92        return m_idInvalidationSets.size() > 0;
93    }
94
95    // Marks the given attribute name as "appearing in a selector". Used for
96    // CSS properties such as content: ... attr(...) ...
97    // FIXME: record these internally to this class instead calls from StyleResolver to here.
98    void addContentAttr(const AtomicString& attributeName);
99
100    StyleInvalidator& styleInvalidator();
101
102    void trace(Visitor*);
103
104    WillBeHeapVector<RuleFeature> siblingRules;
105    WillBeHeapVector<RuleFeature> uncommonAttributeRules;
106
107protected:
108    DescendantInvalidationSet* invalidationSetForSelector(const CSSSelector&);
109
110private:
111    typedef WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<DescendantInvalidationSet> > InvalidationSetMap;
112    typedef WillBeHeapHashMap<CSSSelector::PseudoType, RefPtrWillBeMember<DescendantInvalidationSet>, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > PseudoTypeInvalidationSetMap;
113
114    struct FeatureMetadata {
115        FeatureMetadata()
116            : usesFirstLineRules(false)
117            , foundSiblingSelector(false)
118            , maxDirectAdjacentSelectors(0)
119        { }
120        void add(const FeatureMetadata& other);
121        void clear();
122
123        bool usesFirstLineRules;
124        bool foundSiblingSelector;
125        unsigned maxDirectAdjacentSelectors;
126    };
127
128    enum InvalidationSetMode {
129        AddFeatures,
130        UseLocalStyleChange,
131        UseSubtreeStyleChange
132    };
133
134    static InvalidationSetMode invalidationSetModeForSelector(const CSSSelector&);
135
136    void collectFeaturesFromSelector(const CSSSelector&, FeatureMetadata&, InvalidationSetMode);
137    void collectFeaturesFromSelectorList(const CSSSelectorList*, FeatureMetadata&, InvalidationSetMode);
138
139    DescendantInvalidationSet& ensureClassInvalidationSet(const AtomicString& className);
140    DescendantInvalidationSet& ensureAttributeInvalidationSet(const AtomicString& attributeName);
141    DescendantInvalidationSet& ensureIdInvalidationSet(const AtomicString& attributeName);
142    DescendantInvalidationSet& ensurePseudoInvalidationSet(CSSSelector::PseudoType);
143
144    InvalidationSetMode updateInvalidationSets(const CSSSelector&);
145
146    struct InvalidationSetFeatures {
147        InvalidationSetFeatures()
148            : customPseudoElement(false)
149            , treeBoundaryCrossing(false)
150            , wholeSubtree(false)
151        { }
152        Vector<AtomicString> classes;
153        Vector<AtomicString> attributes;
154        AtomicString id;
155        AtomicString tagName;
156        bool customPseudoElement;
157        bool treeBoundaryCrossing;
158        bool wholeSubtree;
159    };
160
161    static void extractInvalidationSetFeature(const CSSSelector&, InvalidationSetFeatures&);
162    const CSSSelector* extractInvalidationSetFeatures(const CSSSelector&, InvalidationSetFeatures&, bool negated);
163    void addFeaturesToInvalidationSets(const CSSSelector&, InvalidationSetFeatures&);
164
165    void addClassToInvalidationSet(const AtomicString& className, Element&);
166
167    FeatureMetadata m_metadata;
168    InvalidationSetMap m_classInvalidationSets;
169    InvalidationSetMap m_attributeInvalidationSets;
170    InvalidationSetMap m_idInvalidationSets;
171    PseudoTypeInvalidationSetMap m_pseudoInvalidationSets;
172    StyleInvalidator m_styleInvalidator;
173};
174
175
176} // namespace blink
177
178namespace WTF {
179
180template <> struct VectorTraits<blink::RuleFeature> : VectorTraitsBase<blink::RuleFeature> {
181    static const bool needsDestruction = false;
182    static const bool canInitializeWithMemset = true;
183    static const bool canMoveWithMemcpy = true;
184};
185
186} // namespace WTF
187
188#endif // RuleFeature_h
189