Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : // vim:cindent:tabstop=2:expandtab:shiftwidth=2:
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * style rule processor for CSS style sheets, responsible for selector
9 : * matching and cascading
10 : */
11 :
12 : #ifndef nsCSSRuleProcessor_h_
13 : #define nsCSSRuleProcessor_h_
14 :
15 : #include "mozilla/Attributes.h"
16 : #include "mozilla/EventStates.h"
17 : #include "mozilla/MemoryReporting.h"
18 : #include "mozilla/RefCountType.h"
19 : #include "mozilla/SheetType.h"
20 : #include "mozilla/UniquePtr.h"
21 : #include "nsExpirationTracker.h"
22 : #include "nsMediaList.h"
23 : #include "nsIStyleRuleProcessor.h"
24 : #include "nsRuleWalker.h"
25 : #include "nsTArray.h"
26 :
27 : struct CascadeEnumData;
28 : struct ElementDependentRuleProcessorData;
29 : struct nsCSSSelector;
30 : struct nsCSSSelectorList;
31 : struct nsFontFaceRuleContainer;
32 : struct RuleCascadeData;
33 : struct TreeMatchContext;
34 : class nsCSSKeyframesRule;
35 : class nsCSSPageRule;
36 : class nsCSSFontFeatureValuesRule;
37 : class nsCSSCounterStyleRule;
38 :
39 : namespace mozilla {
40 : class CSSStyleSheet;
41 : enum class CSSPseudoElementType : uint8_t;
42 : enum class CSSPseudoClassType : uint8_t;
43 : namespace css {
44 : class DocumentRule;
45 : } // namespace css
46 : } // namespace mozilla
47 :
48 : /**
49 : * The CSS style rule processor provides a mechanism for sibling style
50 : * sheets to combine their rule processing in order to allow proper
51 : * cascading to happen.
52 : *
53 : * CSS style rule processors keep a live reference on all style sheets
54 : * bound to them. The CSS style sheets keep a weak reference to all the
55 : * processors that they are bound to (many to many). The CSS style sheet
56 : * is told when the rule processor is going away (via DropRuleProcessor).
57 : */
58 :
59 : class nsCSSRuleProcessor: public nsIStyleRuleProcessor {
60 : public:
61 : typedef nsTArray<RefPtr<mozilla::CSSStyleSheet>> sheet_array_type;
62 :
63 : // aScopeElement must be non-null iff aSheetType is
64 : // SheetType::ScopedDoc.
65 : // aPreviousCSSRuleProcessor is the rule processor (if any) that this
66 : // one is replacing.
67 : nsCSSRuleProcessor(const sheet_array_type& aSheets,
68 : mozilla::SheetType aSheetType,
69 : mozilla::dom::Element* aScopeElement,
70 : nsCSSRuleProcessor* aPreviousCSSRuleProcessor,
71 : bool aIsShared = false);
72 : nsCSSRuleProcessor(sheet_array_type&& aSheets,
73 : mozilla::SheetType aSheetType,
74 : mozilla::dom::Element* aScopeElement,
75 : nsCSSRuleProcessor* aPreviousCSSRuleProcessor,
76 : bool aIsShared = false);
77 :
78 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
79 385 : NS_DECL_CYCLE_COLLECTION_CLASS(nsCSSRuleProcessor)
80 :
81 : public:
82 : nsresult ClearRuleCascades();
83 :
84 : static void Startup();
85 : static void InitSystemMetrics();
86 : static void Shutdown();
87 : static void FreeSystemMetrics();
88 : static bool HasSystemMetric(nsIAtom* aMetric);
89 :
90 : /*
91 : * Returns true if the given aElement matches one of the
92 : * selectors in aSelectorList. Note that this method will assume
93 : * the given aElement is not a relevant link. aSelectorList must not
94 : * include any pseudo-element selectors. aSelectorList is allowed
95 : * to be null; in this case false will be returned.
96 : */
97 : static bool SelectorListMatches(mozilla::dom::Element* aElement,
98 : TreeMatchContext& aTreeMatchContext,
99 : nsCSSSelectorList* aSelectorList);
100 :
101 : /*
102 : * Helper to get the content state for a content node. This may be
103 : * slightly adjusted from IntrinsicState().
104 : */
105 : static mozilla::EventStates GetContentState(
106 : mozilla::dom::Element* aElement,
107 : bool aUsingPrivateBrowsing);
108 : static mozilla::EventStates GetContentState(
109 : mozilla::dom::Element* aElement,
110 : const TreeMatchContext& aTreeMatchContext);
111 : static mozilla::EventStates GetContentState(
112 : mozilla::dom::Element* aElement);
113 :
114 : /*
115 : * Helper to get the content state for :visited handling for an element
116 : */
117 : static mozilla::EventStates GetContentStateForVisitedHandling(
118 : mozilla::dom::Element* aElement,
119 : nsRuleWalker::VisitedHandlingType aVisitedHandling,
120 : bool aIsRelevantLink);
121 :
122 : /*
123 : * Helper to test whether a node is a link
124 : */
125 : static bool IsLink(const mozilla::dom::Element* aElement);
126 :
127 : /**
128 : * Returns true if the given aElement matches aSelector.
129 : * Like nsCSSRuleProcessor.cpp's SelectorMatches (and unlike
130 : * SelectorMatchesTree), this does not check an entire selector list
131 : * separated by combinators.
132 : *
133 : * :visited and :link will match both visited and non-visited links,
134 : * as if aTreeMatchContext->mVisitedHandling were eLinksVisitedOrUnvisited.
135 : *
136 : * aSelector is restricted to not containing pseudo-elements.
137 : */
138 : static bool RestrictedSelectorMatches(mozilla::dom::Element* aElement,
139 : nsCSSSelector* aSelector,
140 : TreeMatchContext& aTreeMatchContext);
141 : /**
142 : * Checks if a function-like ident-containing pseudo (:pseudo(ident))
143 : * matches a given element.
144 : *
145 : * Returns true if it parses and matches, Some(false) if it
146 : * parses but does not match. Asserts if it fails to parse; only
147 : * call this when you're sure it's a string-like pseudo.
148 : *
149 : * In Servo mode, please ensure that UpdatePossiblyStaleDocumentState()
150 : * has been called first.
151 : *
152 : * @param aElement The element we are trying to match
153 : * @param aPseudo The name of the pseudoselector
154 : * @param aString The identifier inside the pseudoselector (cannot be null)
155 : * @param aDocument The document
156 : * @param aForStyling Is this matching operation for the creation of a style context?
157 : * (For setting the slow selector flag)
158 : * @param aStateMask Mask containing states which we should exclude.
159 : * Ignored if aDependence is null
160 : * @param aSetSlowSelectorFlag Outparam, set if the caller is
161 : * supposed to set the slow selector flag.
162 : * @param aDependence Pointer to be set to true if we ignored a state due to
163 : * aStateMask. Can be null.
164 : */
165 : static bool StringPseudoMatches(const mozilla::dom::Element* aElement,
166 : mozilla::CSSPseudoClassType aPseudo,
167 : const char16_t* aString,
168 : const nsIDocument* aDocument,
169 : bool aForStyling,
170 : mozilla::EventStates aStateMask,
171 : bool* aSetSlowSelectorFlag,
172 : bool* const aDependence = nullptr);
173 :
174 : static bool LangPseudoMatches(const mozilla::dom::Element* aElement,
175 : const nsIAtom* aOverrideLang,
176 : bool aHasOverrideLang,
177 : const char16_t* aString,
178 : const nsIDocument* aDocument);
179 :
180 : // nsIStyleRuleProcessor
181 : virtual void RulesMatching(ElementRuleProcessorData* aData) override;
182 :
183 : virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override;
184 :
185 : virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
186 :
187 : #ifdef MOZ_XUL
188 : virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
189 : #endif
190 :
191 : virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
192 : virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
193 :
194 : virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
195 :
196 : virtual nsRestyleHint
197 : HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
198 : mozilla::RestyleHintData& aRestyleHintDataResult)
199 : override;
200 :
201 : virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
202 :
203 : /**
204 : * If this rule processor currently has a substantive media query
205 : * result cache key, return a copy of it.
206 : */
207 : mozilla::UniquePtr<nsMediaQueryResultCacheKey> CloneMQCacheKey();
208 :
209 : virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
210 : const MOZ_MUST_OVERRIDE override;
211 : virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
212 : const MOZ_MUST_OVERRIDE override;
213 :
214 : // Append all the currently-active font face rules to aArray. Return
215 : // true for success and false for failure.
216 : bool AppendFontFaceRules(nsPresContext* aPresContext,
217 : nsTArray<nsFontFaceRuleContainer>& aArray);
218 :
219 : nsCSSKeyframesRule* KeyframesRuleForName(nsPresContext* aPresContext,
220 : const nsString& aName);
221 :
222 : nsCSSCounterStyleRule* CounterStyleRuleForName(nsPresContext* aPresContext,
223 : nsIAtom* aName);
224 :
225 : bool AppendPageRules(nsPresContext* aPresContext,
226 : nsTArray<nsCSSPageRule*>& aArray);
227 :
228 : bool AppendFontFeatureValuesRules(nsPresContext* aPresContext,
229 : nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
230 :
231 : /**
232 : * Returns the scope element for the scoped style sheets this rule
233 : * processor is for. If this is not a rule processor for scoped style
234 : * sheets, it returns null.
235 : */
236 0 : mozilla::dom::Element* GetScopeElement() const { return mScopeElement; }
237 :
238 : void TakeDocumentRulesAndCacheKey(
239 : nsPresContext* aPresContext,
240 : nsTArray<mozilla::css::DocumentRule*>& aDocumentRules,
241 : nsDocumentRuleResultCacheKey& aDocumentRuleResultCacheKey);
242 :
243 30 : bool IsShared() const { return mIsShared; }
244 :
245 13 : nsExpirationState* GetExpirationState() { return &mExpirationState; }
246 : void AddStyleSetRef();
247 : void ReleaseStyleSetRef();
248 10 : void SetInRuleProcessorCache(bool aVal) {
249 10 : MOZ_ASSERT(mIsShared);
250 10 : mInRuleProcessorCache = aVal;
251 10 : }
252 10 : bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; }
253 0 : bool IsUsedByMultipleStyleSets() const { return mStyleSetRefCnt > 1; }
254 :
255 : #ifdef XP_WIN
256 : // Cached theme identifier for the moz-windows-theme media query.
257 : static uint8_t GetWindowsThemeIdentifier();
258 : static void SetWindowsThemeIdentifier(uint8_t aId) {
259 : sWinThemeId = aId;
260 : }
261 : #endif
262 :
263 : struct StateSelector {
264 1912 : StateSelector(mozilla::EventStates aStates, nsCSSSelector* aSelector)
265 1912 : : mStates(aStates),
266 1912 : mSelector(aSelector)
267 1912 : {}
268 :
269 : mozilla::EventStates mStates;
270 : nsCSSSelector* mSelector;
271 : };
272 :
273 : protected:
274 : virtual ~nsCSSRuleProcessor();
275 :
276 : private:
277 : static bool CascadeSheet(mozilla::CSSStyleSheet* aSheet,
278 : CascadeEnumData* aData);
279 :
280 : RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext);
281 : void RefreshRuleCascade(nsPresContext* aPresContext);
282 :
283 : nsRestyleHint HasStateDependentStyle(ElementDependentRuleProcessorData* aData,
284 : mozilla::dom::Element* aStatefulElement,
285 : mozilla::CSSPseudoElementType aPseudoType,
286 : mozilla::EventStates aStateMask);
287 :
288 : void ClearSheets();
289 :
290 : // The sheet order here is the same as in nsStyleSet::mSheets
291 : sheet_array_type mSheets;
292 :
293 : // active first, then cached (most recent first)
294 : RuleCascadeData* mRuleCascades;
295 :
296 : // If we cleared our mRuleCascades or replaced a previous rule
297 : // processor, this is the media query result cache key that was used
298 : // before we lost the old rule cascades.
299 : mozilla::UniquePtr<nsMediaQueryResultCacheKey> mPreviousCacheKey;
300 :
301 : // The last pres context for which GetRuleCascades was called.
302 : nsPresContext *mLastPresContext;
303 :
304 : // The scope element for this rule processor's scoped style sheets.
305 : // Only used if mSheetType == nsStyleSet::eScopedDocSheet.
306 : RefPtr<mozilla::dom::Element> mScopeElement;
307 :
308 : nsTArray<mozilla::css::DocumentRule*> mDocumentRules;
309 : nsDocumentRuleResultCacheKey mDocumentCacheKey;
310 :
311 : nsExpirationState mExpirationState;
312 : MozRefCountType mStyleSetRefCnt;
313 :
314 : // type of stylesheet using this processor
315 : mozilla::SheetType mSheetType;
316 :
317 : const bool mIsShared;
318 :
319 : // Whether we need to build up mDocumentCacheKey and mDocumentRules as
320 : // we build a RuleCascadeData. Is true only for shared rule processors
321 : // and only before we build the first RuleCascadeData. See comment in
322 : // RefreshRuleCascade for why.
323 : bool mMustGatherDocumentRules;
324 :
325 : bool mInRuleProcessorCache;
326 :
327 : #ifdef DEBUG
328 : bool mDocumentRulesAndCacheKeyValid;
329 : #endif
330 :
331 : #ifdef XP_WIN
332 : static uint8_t sWinThemeId;
333 : #endif
334 : };
335 :
336 : #endif /* nsCSSRuleProcessor_h_ */
|