|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
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 * representation of media lists used when linking to style sheets or by |
|
9 * @media rules |
|
10 */ |
|
11 |
|
12 #ifndef nsIMediaList_h_ |
|
13 #define nsIMediaList_h_ |
|
14 |
|
15 #include "nsIDOMMediaList.h" |
|
16 #include "nsTArray.h" |
|
17 #include "nsIAtom.h" |
|
18 #include "nsCSSValue.h" |
|
19 #include "nsWrapperCache.h" |
|
20 #include "mozilla/Attributes.h" |
|
21 #include "mozilla/ErrorResult.h" |
|
22 |
|
23 class nsPresContext; |
|
24 class nsCSSStyleSheet; |
|
25 class nsAString; |
|
26 struct nsMediaFeature; |
|
27 |
|
28 struct nsMediaExpression { |
|
29 enum Range { eMin, eMax, eEqual }; |
|
30 |
|
31 const nsMediaFeature *mFeature; |
|
32 Range mRange; |
|
33 nsCSSValue mValue; |
|
34 |
|
35 // aActualValue must be obtained from mFeature->mGetter |
|
36 bool Matches(nsPresContext* aPresContext, |
|
37 const nsCSSValue& aActualValue) const; |
|
38 }; |
|
39 |
|
40 /** |
|
41 * An nsMediaQueryResultCacheKey records what feature/value combinations |
|
42 * a set of media query results are valid for. This allows the caller |
|
43 * to quickly learn whether a prior result of media query evaluation is |
|
44 * still valid (e.g., due to a window size change) without rerunning all |
|
45 * of the evaluation and rebuilding the list of rules. |
|
46 * |
|
47 * This object may not be used after any media rules in any of the |
|
48 * sheets it was given to have been modified. However, this is |
|
49 * generally not a problem since ClearRuleCascades is called on the |
|
50 * sheet whenever this happens, and these objects are stored inside the |
|
51 * rule cascades. (FIXME: We're not actually doing this all the time.) |
|
52 * |
|
53 * The implementation could be further optimized in the future to store |
|
54 * ranges (combinations of less-than, less-than-or-equal, greater-than, |
|
55 * greater-than-or-equal, equal, not-equal, present, not-present) for |
|
56 * each feature rather than simply storing the list of expressions. |
|
57 * However, this requires combining any such ranges. |
|
58 */ |
|
59 class nsMediaQueryResultCacheKey { |
|
60 public: |
|
61 nsMediaQueryResultCacheKey(nsIAtom* aMedium) |
|
62 : mMedium(aMedium) |
|
63 {} |
|
64 |
|
65 /** |
|
66 * Record that aExpression was tested while building the cached set |
|
67 * that this cache key is for, and that aExpressionMatches was whether |
|
68 * it matched. |
|
69 */ |
|
70 void AddExpression(const nsMediaExpression* aExpression, |
|
71 bool aExpressionMatches); |
|
72 bool Matches(nsPresContext* aPresContext) const; |
|
73 private: |
|
74 struct ExpressionEntry { |
|
75 // FIXME: if we were better at maintaining invariants about clearing |
|
76 // rule cascades when media lists change, this could be a |const |
|
77 // nsMediaExpression*| instead. |
|
78 nsMediaExpression mExpression; |
|
79 bool mExpressionMatches; |
|
80 }; |
|
81 struct FeatureEntry { |
|
82 const nsMediaFeature *mFeature; |
|
83 InfallibleTArray<ExpressionEntry> mExpressions; |
|
84 }; |
|
85 nsCOMPtr<nsIAtom> mMedium; |
|
86 nsTArray<FeatureEntry> mFeatureCache; |
|
87 }; |
|
88 |
|
89 class nsMediaQuery { |
|
90 public: |
|
91 nsMediaQuery() |
|
92 : mNegated(false) |
|
93 , mHasOnly(false) |
|
94 , mTypeOmitted(false) |
|
95 , mHadUnknownExpression(false) |
|
96 { |
|
97 } |
|
98 |
|
99 private: |
|
100 // for Clone only |
|
101 nsMediaQuery(const nsMediaQuery& aOther) |
|
102 : mNegated(aOther.mNegated) |
|
103 , mHasOnly(aOther.mHasOnly) |
|
104 , mTypeOmitted(aOther.mTypeOmitted) |
|
105 , mHadUnknownExpression(aOther.mHadUnknownExpression) |
|
106 , mMediaType(aOther.mMediaType) |
|
107 , mExpressions(aOther.mExpressions) |
|
108 { |
|
109 MOZ_ASSERT(mExpressions.Length() == aOther.mExpressions.Length()); |
|
110 } |
|
111 |
|
112 public: |
|
113 |
|
114 void SetNegated() { mNegated = true; } |
|
115 void SetHasOnly() { mHasOnly = true; } |
|
116 void SetTypeOmitted() { mTypeOmitted = true; } |
|
117 void SetHadUnknownExpression() { mHadUnknownExpression = true; } |
|
118 void SetType(nsIAtom* aMediaType) { |
|
119 NS_ASSERTION(aMediaType, |
|
120 "expected non-null"); |
|
121 mMediaType = aMediaType; |
|
122 } |
|
123 |
|
124 // Return a new nsMediaExpression in the array for the caller to fill |
|
125 // in. The caller must either fill it in completely, or call |
|
126 // SetHadUnknownExpression on this nsMediaQuery. |
|
127 // Returns null on out-of-memory. |
|
128 nsMediaExpression* NewExpression() { return mExpressions.AppendElement(); } |
|
129 |
|
130 void AppendToString(nsAString& aString) const; |
|
131 |
|
132 nsMediaQuery* Clone() const; |
|
133 |
|
134 // Does this query apply to the presentation? |
|
135 // If |aKey| is non-null, add cache information to it. |
|
136 bool Matches(nsPresContext* aPresContext, |
|
137 nsMediaQueryResultCacheKey* aKey) const; |
|
138 |
|
139 private: |
|
140 bool mNegated; |
|
141 bool mHasOnly; // only needed for serialization |
|
142 bool mTypeOmitted; // only needed for serialization |
|
143 bool mHadUnknownExpression; |
|
144 nsCOMPtr<nsIAtom> mMediaType; |
|
145 nsTArray<nsMediaExpression> mExpressions; |
|
146 }; |
|
147 |
|
148 class nsMediaList MOZ_FINAL : public nsIDOMMediaList |
|
149 , public nsWrapperCache |
|
150 { |
|
151 public: |
|
152 typedef mozilla::ErrorResult ErrorResult; |
|
153 |
|
154 nsMediaList(); |
|
155 |
|
156 virtual JSObject* |
|
157 WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
|
158 nsISupports* GetParentObject() const |
|
159 { |
|
160 return nullptr; |
|
161 } |
|
162 |
|
163 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
164 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsMediaList) |
|
165 |
|
166 NS_DECL_NSIDOMMEDIALIST |
|
167 |
|
168 void GetText(nsAString& aMediaText); |
|
169 void SetText(const nsAString& aMediaText); |
|
170 |
|
171 // Does this query apply to the presentation? |
|
172 // If |aKey| is non-null, add cache information to it. |
|
173 bool Matches(nsPresContext* aPresContext, |
|
174 nsMediaQueryResultCacheKey* aKey); |
|
175 |
|
176 nsresult SetStyleSheet(nsCSSStyleSheet* aSheet); |
|
177 void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) { |
|
178 // Takes ownership of aQuery |
|
179 mArray.AppendElement(aQuery.forget()); |
|
180 } |
|
181 |
|
182 already_AddRefed<nsMediaList> Clone(); |
|
183 |
|
184 nsMediaQuery* MediumAt(int32_t aIndex) { return mArray[aIndex]; } |
|
185 void Clear() { mArray.Clear(); } |
|
186 |
|
187 // WebIDL |
|
188 // XPCOM GetMediaText and SetMediaText are fine. |
|
189 uint32_t Length() { return mArray.Length(); } |
|
190 void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aReturn); |
|
191 // XPCOM Item is fine. |
|
192 void DeleteMedium(const nsAString& aMedium, ErrorResult& aRv) |
|
193 { |
|
194 aRv = DeleteMedium(aMedium); |
|
195 } |
|
196 void AppendMedium(const nsAString& aMedium, ErrorResult& aRv) |
|
197 { |
|
198 aRv = AppendMedium(aMedium); |
|
199 } |
|
200 |
|
201 protected: |
|
202 ~nsMediaList(); |
|
203 |
|
204 nsresult Delete(const nsAString & aOldMedium); |
|
205 nsresult Append(const nsAString & aOldMedium); |
|
206 |
|
207 InfallibleTArray<nsAutoPtr<nsMediaQuery> > mArray; |
|
208 // not refcounted; sheet will let us know when it goes away |
|
209 // mStyleSheet is the sheet that needs to be dirtied when this medialist |
|
210 // changes |
|
211 nsCSSStyleSheet* mStyleSheet; |
|
212 }; |
|
213 #endif /* !defined(nsIMediaList_h_) */ |