• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 RuleSet_h
23 #define RuleSet_h
24 
25 #include "core/css/CSSKeyframesRule.h"
26 #include "core/css/MediaQueryEvaluator.h"
27 #include "core/css/RuleFeature.h"
28 #include "core/css/StyleRule.h"
29 #include "core/css/resolver/MediaQueryResult.h"
30 #include "wtf/Forward.h"
31 #include "wtf/HashMap.h"
32 #include "wtf/LinkedStack.h"
33 
34 namespace WebCore {
35 
36 enum AddRuleFlags {
37     RuleHasNoSpecialState         = 0,
38     RuleHasDocumentSecurityOrigin = 1,
39     RuleCanUseFastCheckSelector   = 1 << 1,
40     RuleIsInRegionRule            = 1 << 2,
41 };
42 
43 enum PropertyWhitelistType {
44     PropertyWhitelistNone   = 0,
45     PropertyWhitelistRegion,
46     PropertyWhitelistCue
47 };
48 
49 class CSSSelector;
50 class MediaQueryEvaluator;
51 class StyleRuleRegion;
52 class StyleSheetContents;
53 
54 struct MinimalRuleData {
MinimalRuleDataMinimalRuleData55     MinimalRuleData(StyleRule* rule, unsigned selectorIndex, AddRuleFlags flags)
56     : m_rule(rule)
57     , m_selectorIndex(selectorIndex)
58     , m_flags(flags)
59     {
60     }
61 
62     StyleRule* m_rule;
63     unsigned m_selectorIndex;
64     AddRuleFlags m_flags;
65 };
66 
67 class RuleData {
68     WTF_MAKE_FAST_ALLOCATED;
69 public:
70     RuleData(StyleRule*, unsigned selectorIndex, unsigned position, AddRuleFlags);
71 
position()72     unsigned position() const { return m_position; }
rule()73     StyleRule* rule() const { return m_rule; }
selector()74     const CSSSelector* selector() const { return m_rule->selectorList().selectorAt(m_selectorIndex); }
selectorIndex()75     unsigned selectorIndex() const { return m_selectorIndex; }
76 
isLastInArray()77     bool isLastInArray() const { return m_isLastInArray; }
setLastInArray(bool flag)78     void setLastInArray(bool flag) { m_isLastInArray = flag; }
79 
hasFastCheckableSelector()80     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
hasMultipartSelector()81     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
hasRightmostSelectorMatchingHTMLBasedOnRuleHash()82     bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
containsUncommonAttributeSelector()83     bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
specificity()84     unsigned specificity() const { return m_specificity; }
linkMatchType()85     unsigned linkMatchType() const { return m_linkMatchType; }
hasDocumentSecurityOrigin()86     bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
87     PropertyWhitelistType propertyWhitelistType(bool isMatchingUARules = false) const { return isMatchingUARules ? PropertyWhitelistNone : static_cast<PropertyWhitelistType>(m_propertyWhitelistType); }
88     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
89     static const unsigned maximumIdentifierCount = 4;
descendantSelectorIdentifierHashes()90     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
91 
92 private:
93     StyleRule* m_rule;
94     unsigned m_selectorIndex : 12;
95     unsigned m_isLastInArray : 1; // We store an array of RuleData objects in a primitive array.
96     // This number was picked fairly arbitrarily. We can probably lower it if we need to.
97     // Some simple testing showed <100,000 RuleData's on large sites.
98     unsigned m_position : 18;
99     unsigned m_hasFastCheckableSelector : 1;
100     unsigned m_specificity : 24;
101     unsigned m_hasMultipartSelector : 1;
102     unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
103     unsigned m_containsUncommonAttributeSelector : 1;
104     unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
105     unsigned m_hasDocumentSecurityOrigin : 1;
106     unsigned m_propertyWhitelistType : 2;
107     // Use plain array instead of a Vector to minimize memory overhead.
108     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
109 };
110 
111 struct SameSizeAsRuleData {
112     void* a;
113     unsigned b;
114     unsigned c;
115     unsigned d[4];
116 };
117 
118 COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
119 
120 class RuleSet {
121     WTF_MAKE_NONCOPYABLE(RuleSet); WTF_MAKE_FAST_ALLOCATED;
122 public:
create()123     static PassOwnPtr<RuleSet> create() { return adoptPtr(new RuleSet); }
124 
125     void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, AddRuleFlags = RuleHasNoSpecialState);
126     void addStyleRule(StyleRule*, AddRuleFlags);
127     void addRule(StyleRule*, unsigned selectorIndex, AddRuleFlags);
128 
features()129     const RuleFeatureSet& features() const { return m_features; }
130 
idRules(StringImpl * key)131     const RuleData* idRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_idRules.get(key); }
classRules(StringImpl * key)132     const RuleData* classRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_classRules.get(key); }
tagRules(StringImpl * key)133     const RuleData* tagRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_tagRules.get(key); }
shadowPseudoElementRules(StringImpl * key)134     const RuleData* shadowPseudoElementRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_shadowPseudoElementRules.get(key); }
linkPseudoClassRules()135     const Vector<RuleData>* linkPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_linkPseudoClassRules; }
cuePseudoRules()136     const Vector<RuleData>* cuePseudoRules() const { ASSERT(!m_pendingRules); return &m_cuePseudoRules; }
focusPseudoClassRules()137     const Vector<RuleData>* focusPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_focusPseudoClassRules; }
universalRules()138     const Vector<RuleData>* universalRules() const { ASSERT(!m_pendingRules); return &m_universalRules; }
pageRules()139     const Vector<StyleRulePage*>& pageRules() const { ASSERT(!m_pendingRules); return m_pageRules; }
viewportRules()140     const Vector<StyleRuleViewport*>& viewportRules() const { ASSERT(!m_pendingRules); return m_viewportRules; }
fontFaceRules()141     const Vector<StyleRuleFontFace*>& fontFaceRules() const { return m_fontFaceRules; }
keyframesRules()142     const Vector<StyleRuleKeyframes*>& keyframesRules() const { return m_keyframesRules; }
treeBoundaryCrossingRules()143     const Vector<MinimalRuleData>& treeBoundaryCrossingRules() const { return m_treeBoundaryCrossingRules; }
shadowDistributedRules()144     const Vector<MinimalRuleData>& shadowDistributedRules() const { return m_shadowDistributedRules; }
viewportDependentMediaQueryResults()145     const MediaQueryResultList& viewportDependentMediaQueryResults() const { return m_viewportDependentMediaQueryResults; }
146 
ruleCount()147     unsigned ruleCount() const { return m_ruleCount; }
148 
compactRulesIfNeeded()149     void compactRulesIfNeeded()
150     {
151         if (!m_pendingRules)
152             return;
153         compactRules();
154     }
155 
156     struct RuleSetSelectorPair {
RuleSetSelectorPairRuleSetSelectorPair157         RuleSetSelectorPair(const CSSSelector* selector, PassOwnPtr<RuleSet> ruleSet) : selector(selector), ruleSet(ruleSet) { }
RuleSetSelectorPairRuleSetSelectorPair158         RuleSetSelectorPair(const RuleSetSelectorPair& rs) : selector(rs.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&rs)->ruleSet.release()) { }
159 
160         const CSSSelector* selector;
161         OwnPtr<RuleSet> ruleSet;
162     };
163 
164     Vector<RuleSetSelectorPair> m_regionSelectorsAndRuleSets;
165 
166 private:
167     typedef HashMap<StringImpl*, OwnPtr<LinkedStack<RuleData> > > PendingRuleMap;
168     typedef HashMap<StringImpl*, OwnPtr<RuleData> > CompactRuleMap;
169 
RuleSet()170     RuleSet()
171         : m_ruleCount(0)
172     {
173     }
174 
175     void addToRuleSet(StringImpl* key, PendingRuleMap&, const RuleData&);
176     void addPageRule(StyleRulePage*);
177     void addViewportRule(StyleRuleViewport*);
178     void addFontFaceRule(StyleRuleFontFace*);
179     void addKeyframesRule(StyleRuleKeyframes*);
180     void addRegionRule(StyleRuleRegion*, bool hasDocumentSecurityOrigin);
181 
182     void addChildRules(const Vector<RefPtr<StyleRuleBase> >&, const MediaQueryEvaluator& medium, AddRuleFlags);
183     bool findBestRuleSetAndAdd(const CSSSelector*, RuleData&);
184 
185     void compactRules();
186     static void compactPendingRules(PendingRuleMap&, CompactRuleMap&);
187 
188     struct PendingRuleMaps {
189         PendingRuleMap idRules;
190         PendingRuleMap classRules;
191         PendingRuleMap tagRules;
192         PendingRuleMap shadowPseudoElementRules;
193     };
194 
ensurePendingRules()195     PendingRuleMaps* ensurePendingRules()
196     {
197         if (!m_pendingRules)
198             m_pendingRules = adoptPtr(new PendingRuleMaps);
199         return m_pendingRules.get();
200     }
201 
202     CompactRuleMap m_idRules;
203     CompactRuleMap m_classRules;
204     CompactRuleMap m_tagRules;
205     CompactRuleMap m_shadowPseudoElementRules;
206     Vector<RuleData> m_linkPseudoClassRules;
207     Vector<RuleData> m_cuePseudoRules;
208     Vector<RuleData> m_focusPseudoClassRules;
209     Vector<RuleData> m_universalRules;
210     RuleFeatureSet m_features;
211     Vector<StyleRulePage*> m_pageRules;
212     Vector<StyleRuleViewport*> m_viewportRules;
213     Vector<StyleRuleFontFace*> m_fontFaceRules;
214     Vector<StyleRuleKeyframes*> m_keyframesRules;
215     Vector<MinimalRuleData> m_treeBoundaryCrossingRules;
216     Vector<MinimalRuleData> m_shadowDistributedRules;
217 
218     MediaQueryResultList m_viewportDependentMediaQueryResults;
219 
220     unsigned m_ruleCount;
221     OwnPtr<PendingRuleMaps> m_pendingRules;
222 };
223 
224 } // namespace WebCore
225 
226 #endif // RuleSet_h
227