Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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/. */
7 /*
8 * representation of media lists used when linking to style sheets or by
9 * @media rules
10 */
12 #ifndef nsIMediaList_h_
13 #define nsIMediaList_h_
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"
23 class nsPresContext;
24 class nsCSSStyleSheet;
25 class nsAString;
26 struct nsMediaFeature;
28 struct nsMediaExpression {
29 enum Range { eMin, eMax, eEqual };
31 const nsMediaFeature *mFeature;
32 Range mRange;
33 nsCSSValue mValue;
35 // aActualValue must be obtained from mFeature->mGetter
36 bool Matches(nsPresContext* aPresContext,
37 const nsCSSValue& aActualValue) const;
38 };
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 {}
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 };
89 class nsMediaQuery {
90 public:
91 nsMediaQuery()
92 : mNegated(false)
93 , mHasOnly(false)
94 , mTypeOmitted(false)
95 , mHadUnknownExpression(false)
96 {
97 }
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 }
112 public:
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 }
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(); }
130 void AppendToString(nsAString& aString) const;
132 nsMediaQuery* Clone() const;
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;
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 };
148 class nsMediaList MOZ_FINAL : public nsIDOMMediaList
149 , public nsWrapperCache
150 {
151 public:
152 typedef mozilla::ErrorResult ErrorResult;
154 nsMediaList();
156 virtual JSObject*
157 WrapObject(JSContext* aCx) MOZ_OVERRIDE;
158 nsISupports* GetParentObject() const
159 {
160 return nullptr;
161 }
163 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
164 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsMediaList)
166 NS_DECL_NSIDOMMEDIALIST
168 void GetText(nsAString& aMediaText);
169 void SetText(const nsAString& aMediaText);
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);
176 nsresult SetStyleSheet(nsCSSStyleSheet* aSheet);
177 void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) {
178 // Takes ownership of aQuery
179 mArray.AppendElement(aQuery.forget());
180 }
182 already_AddRefed<nsMediaList> Clone();
184 nsMediaQuery* MediumAt(int32_t aIndex) { return mArray[aIndex]; }
185 void Clear() { mArray.Clear(); }
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 }
201 protected:
202 ~nsMediaList();
204 nsresult Delete(const nsAString & aOldMedium);
205 nsresult Append(const nsAString & aOldMedium);
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_) */