Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 : * internal interface representing CSS style rules that contain other
8 : * rules, such as @media rules
9 : */
10 :
11 : #ifndef mozilla_css_GroupRule_h__
12 : #define mozilla_css_GroupRule_h__
13 :
14 : #include "mozilla/Attributes.h"
15 : #include "mozilla/ErrorResult.h"
16 : #include "mozilla/IncrementalClearCOMRuleArray.h"
17 : #include "mozilla/MemoryReporting.h"
18 : #include "mozilla/ServoCSSRuleList.h"
19 : #include "mozilla/Variant.h"
20 : #include "mozilla/css/Rule.h"
21 : #include "nsCycleCollectionParticipant.h"
22 :
23 : class nsPresContext;
24 : class nsMediaQueryResultCacheKey;
25 :
26 : namespace mozilla {
27 :
28 : class StyleSheet;
29 :
30 : namespace dom {
31 : class CSSRuleList;
32 : } // namespace dom
33 :
34 : namespace css {
35 :
36 : class GroupRule;
37 : class GroupRuleRuleList;
38 :
39 : struct GeckoGroupRuleRules
40 : {
41 : GeckoGroupRuleRules();
42 : GeckoGroupRuleRules(GeckoGroupRuleRules&& aOther);
43 : GeckoGroupRuleRules(const GeckoGroupRuleRules& aCopy);
44 : ~GeckoGroupRuleRules();
45 :
46 0 : void SetParentRule(GroupRule* aParentRule) {
47 0 : for (Rule* rule : mRules) {
48 0 : rule->SetParentRule(aParentRule);
49 : }
50 0 : }
51 81 : void SetStyleSheet(StyleSheet* aSheet) {
52 288 : for (Rule* rule : mRules) {
53 207 : rule->SetStyleSheet(aSheet);
54 : }
55 81 : }
56 :
57 : void Clear();
58 : void Traverse(nsCycleCollectionTraversalCallback& cb);
59 :
60 : #ifdef DEBUG
61 : void List(FILE* out, int32_t aIndent) const;
62 : #endif
63 :
64 0 : int32_t StyleRuleCount() const { return mRules.Count(); }
65 0 : Rule* GetStyleRuleAt(int32_t aIndex) const {
66 0 : return mRules.SafeObjectAt(aIndex);
67 : }
68 :
69 : nsresult DeleteStyleRuleAt(uint32_t aIndex);
70 :
71 : dom::CSSRuleList* CssRules(GroupRule* aParentRule);
72 :
73 : size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
74 :
75 : IncrementalClearCOMRuleArray mRules;
76 : RefPtr<GroupRuleRuleList> mRuleCollection; // lazily constructed
77 : };
78 :
79 0 : struct ServoGroupRuleRules
80 : {
81 0 : explicit ServoGroupRuleRules(already_AddRefed<ServoCssRules> aRawRules)
82 0 : : mRuleList(new ServoCSSRuleList(Move(aRawRules), nullptr)) {}
83 0 : ServoGroupRuleRules(ServoGroupRuleRules&& aOther)
84 0 : : mRuleList(Move(aOther.mRuleList)) {}
85 0 : ServoGroupRuleRules(const ServoGroupRuleRules& aCopy) {
86 : // Do we ever clone Servo rules?
87 0 : MOZ_ASSERT_UNREACHABLE("stylo: Cloning GroupRule not implemented");
88 : }
89 :
90 0 : void SetParentRule(GroupRule* aParentRule) {
91 0 : if (mRuleList) {
92 0 : mRuleList->SetParentRule(aParentRule);
93 : }
94 0 : }
95 0 : void SetStyleSheet(StyleSheet* aSheet) {
96 0 : if (mRuleList) {
97 0 : mRuleList->SetStyleSheet(aSheet);
98 : }
99 0 : }
100 :
101 0 : void Clear() {
102 0 : if (mRuleList) {
103 0 : mRuleList->DropReference();
104 0 : mRuleList = nullptr;
105 : }
106 0 : }
107 0 : void Traverse(nsCycleCollectionTraversalCallback& cb) {
108 0 : ImplCycleCollectionTraverse(cb, mRuleList, "mRuleList");
109 0 : }
110 :
111 : #ifdef DEBUG
112 : void List(FILE* out, int32_t aIndent) const;
113 : #endif
114 :
115 0 : int32_t StyleRuleCount() const { return mRuleList->Length(); }
116 0 : Rule* GetStyleRuleAt(int32_t aIndex) const {
117 0 : return mRuleList->GetRule(aIndex);
118 : }
119 :
120 0 : nsresult DeleteStyleRuleAt(uint32_t aIndex) {
121 0 : return mRuleList->DeleteRule(aIndex);
122 : }
123 :
124 0 : dom::CSSRuleList* CssRules(GroupRule* aParentRule) {
125 0 : return mRuleList;
126 : }
127 :
128 : size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
129 :
130 : RefPtr<ServoCSSRuleList> mRuleList;
131 : };
132 :
133 : #define REDIRECT_TO_INNER(call_) \
134 : if (mInner.is<GeckoGroupRuleRules>()) { \
135 : return mInner.as<GeckoGroupRuleRules>().call_; \
136 : } else { \
137 : return mInner.as<ServoGroupRuleRules>().call_; \
138 : } \
139 :
140 : // inherits from Rule so it can be shared between
141 : // MediaRule and DocumentRule
142 : class GroupRule : public Rule
143 : {
144 : protected:
145 : GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber);
146 : explicit GroupRule(already_AddRefed<ServoCssRules> aRules);
147 : GroupRule(const GroupRule& aCopy);
148 : virtual ~GroupRule();
149 : public:
150 :
151 33 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(GroupRule, Rule)
152 : NS_DECL_ISUPPORTS_INHERITED
153 : virtual bool IsCCLeaf() const override;
154 :
155 : #ifdef DEBUG
156 0 : void List(FILE* out = stdout, int32_t aIndent = 0) const override {
157 0 : REDIRECT_TO_INNER(List(out, aIndent))
158 : }
159 : #endif
160 : virtual void SetStyleSheet(StyleSheet* aSheet) override;
161 :
162 : public:
163 : void AppendStyleRule(Rule* aRule);
164 :
165 0 : int32_t StyleRuleCount() const {
166 0 : REDIRECT_TO_INNER(StyleRuleCount())
167 : }
168 0 : Rule* GetStyleRuleAt(uint32_t aIndex) const {
169 0 : REDIRECT_TO_INNER(GetStyleRuleAt(aIndex))
170 : }
171 :
172 : typedef bool (*RuleEnumFunc)(Rule* aElement, void* aData);
173 : bool EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const;
174 :
175 : /*
176 : * The next two methods should never be called unless you have first
177 : * called WillDirty() on the parent stylesheet. After they are
178 : * called, DidDirty() needs to be called on the sheet.
179 : */
180 0 : nsresult DeleteStyleRuleAt(uint32_t aIndex) {
181 0 : REDIRECT_TO_INNER(DeleteStyleRuleAt(aIndex));
182 : }
183 : nsresult InsertStyleRuleAt(uint32_t aIndex, Rule* aRule);
184 :
185 : virtual bool UseForPresentation(nsPresContext* aPresContext,
186 : nsMediaQueryResultCacheKey& aKey) = 0;
187 :
188 : // non-virtual -- it is only called by subclasses
189 0 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
190 0 : REDIRECT_TO_INNER(SizeOfExcludingThis(aMallocSizeOf))
191 : }
192 : virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override = 0;
193 :
194 : // WebIDL API
195 : dom::CSSRuleList* CssRules();
196 : uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
197 : ErrorResult& aRv);
198 : void DeleteRule(uint32_t aIndex, ErrorResult& aRv);
199 :
200 : protected:
201 : // to help implement nsIDOMCSSRule
202 : void AppendRulesToCssText(nsAString& aCssText) const;
203 :
204 : // to implement common methods on nsIDOMCSSMediaRule and
205 : // nsIDOMCSSMozDocumentRule
206 : nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList);
207 : nsresult InsertRule(const nsAString & aRule, uint32_t aIndex,
208 : uint32_t* _retval);
209 : nsresult DeleteRule(uint32_t aIndex);
210 :
211 : // Must only be called if this is a Gecko GroupRule.
212 207 : IncrementalClearCOMRuleArray& GeckoRules() {
213 207 : return mInner.as<GeckoGroupRuleRules>().mRules;
214 : }
215 140 : const IncrementalClearCOMRuleArray& GeckoRules() const {
216 140 : return mInner.as<GeckoGroupRuleRules>().mRules;
217 : }
218 :
219 : private:
220 : Variant<GeckoGroupRuleRules, ServoGroupRuleRules> mInner;
221 : };
222 :
223 : #undef REDIRECT_TO_INNER
224 :
225 : // Implementation of WebIDL CSSConditionRule.
226 0 : class ConditionRule : public GroupRule
227 : {
228 : protected:
229 50 : using GroupRule::GroupRule;
230 :
231 : public:
232 : // GetConditionText signature matches nsIDOMCSSConditionRule, so subclasses
233 : // can implement this easily. The implementations should never return
234 : // anything other than NS_OK.
235 : NS_IMETHOD GetConditionText(nsAString& aConditionText) = 0;
236 : virtual void SetConditionText(const nsAString& aConditionText,
237 : ErrorResult& aRv) = 0;
238 : };
239 :
240 : } // namespace css
241 : } // namespace mozilla
242 :
243 : #endif /* mozilla_css_GroupRule_h__ */
|