1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsIMediaList.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,213 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * representation of media lists used when linking to style sheets or by 1.12 + * @media rules 1.13 + */ 1.14 + 1.15 +#ifndef nsIMediaList_h_ 1.16 +#define nsIMediaList_h_ 1.17 + 1.18 +#include "nsIDOMMediaList.h" 1.19 +#include "nsTArray.h" 1.20 +#include "nsIAtom.h" 1.21 +#include "nsCSSValue.h" 1.22 +#include "nsWrapperCache.h" 1.23 +#include "mozilla/Attributes.h" 1.24 +#include "mozilla/ErrorResult.h" 1.25 + 1.26 +class nsPresContext; 1.27 +class nsCSSStyleSheet; 1.28 +class nsAString; 1.29 +struct nsMediaFeature; 1.30 + 1.31 +struct nsMediaExpression { 1.32 + enum Range { eMin, eMax, eEqual }; 1.33 + 1.34 + const nsMediaFeature *mFeature; 1.35 + Range mRange; 1.36 + nsCSSValue mValue; 1.37 + 1.38 + // aActualValue must be obtained from mFeature->mGetter 1.39 + bool Matches(nsPresContext* aPresContext, 1.40 + const nsCSSValue& aActualValue) const; 1.41 +}; 1.42 + 1.43 +/** 1.44 + * An nsMediaQueryResultCacheKey records what feature/value combinations 1.45 + * a set of media query results are valid for. This allows the caller 1.46 + * to quickly learn whether a prior result of media query evaluation is 1.47 + * still valid (e.g., due to a window size change) without rerunning all 1.48 + * of the evaluation and rebuilding the list of rules. 1.49 + * 1.50 + * This object may not be used after any media rules in any of the 1.51 + * sheets it was given to have been modified. However, this is 1.52 + * generally not a problem since ClearRuleCascades is called on the 1.53 + * sheet whenever this happens, and these objects are stored inside the 1.54 + * rule cascades. (FIXME: We're not actually doing this all the time.) 1.55 + * 1.56 + * The implementation could be further optimized in the future to store 1.57 + * ranges (combinations of less-than, less-than-or-equal, greater-than, 1.58 + * greater-than-or-equal, equal, not-equal, present, not-present) for 1.59 + * each feature rather than simply storing the list of expressions. 1.60 + * However, this requires combining any such ranges. 1.61 + */ 1.62 +class nsMediaQueryResultCacheKey { 1.63 +public: 1.64 + nsMediaQueryResultCacheKey(nsIAtom* aMedium) 1.65 + : mMedium(aMedium) 1.66 + {} 1.67 + 1.68 + /** 1.69 + * Record that aExpression was tested while building the cached set 1.70 + * that this cache key is for, and that aExpressionMatches was whether 1.71 + * it matched. 1.72 + */ 1.73 + void AddExpression(const nsMediaExpression* aExpression, 1.74 + bool aExpressionMatches); 1.75 + bool Matches(nsPresContext* aPresContext) const; 1.76 +private: 1.77 + struct ExpressionEntry { 1.78 + // FIXME: if we were better at maintaining invariants about clearing 1.79 + // rule cascades when media lists change, this could be a |const 1.80 + // nsMediaExpression*| instead. 1.81 + nsMediaExpression mExpression; 1.82 + bool mExpressionMatches; 1.83 + }; 1.84 + struct FeatureEntry { 1.85 + const nsMediaFeature *mFeature; 1.86 + InfallibleTArray<ExpressionEntry> mExpressions; 1.87 + }; 1.88 + nsCOMPtr<nsIAtom> mMedium; 1.89 + nsTArray<FeatureEntry> mFeatureCache; 1.90 +}; 1.91 + 1.92 +class nsMediaQuery { 1.93 +public: 1.94 + nsMediaQuery() 1.95 + : mNegated(false) 1.96 + , mHasOnly(false) 1.97 + , mTypeOmitted(false) 1.98 + , mHadUnknownExpression(false) 1.99 + { 1.100 + } 1.101 + 1.102 +private: 1.103 + // for Clone only 1.104 + nsMediaQuery(const nsMediaQuery& aOther) 1.105 + : mNegated(aOther.mNegated) 1.106 + , mHasOnly(aOther.mHasOnly) 1.107 + , mTypeOmitted(aOther.mTypeOmitted) 1.108 + , mHadUnknownExpression(aOther.mHadUnknownExpression) 1.109 + , mMediaType(aOther.mMediaType) 1.110 + , mExpressions(aOther.mExpressions) 1.111 + { 1.112 + MOZ_ASSERT(mExpressions.Length() == aOther.mExpressions.Length()); 1.113 + } 1.114 + 1.115 +public: 1.116 + 1.117 + void SetNegated() { mNegated = true; } 1.118 + void SetHasOnly() { mHasOnly = true; } 1.119 + void SetTypeOmitted() { mTypeOmitted = true; } 1.120 + void SetHadUnknownExpression() { mHadUnknownExpression = true; } 1.121 + void SetType(nsIAtom* aMediaType) { 1.122 + NS_ASSERTION(aMediaType, 1.123 + "expected non-null"); 1.124 + mMediaType = aMediaType; 1.125 + } 1.126 + 1.127 + // Return a new nsMediaExpression in the array for the caller to fill 1.128 + // in. The caller must either fill it in completely, or call 1.129 + // SetHadUnknownExpression on this nsMediaQuery. 1.130 + // Returns null on out-of-memory. 1.131 + nsMediaExpression* NewExpression() { return mExpressions.AppendElement(); } 1.132 + 1.133 + void AppendToString(nsAString& aString) const; 1.134 + 1.135 + nsMediaQuery* Clone() const; 1.136 + 1.137 + // Does this query apply to the presentation? 1.138 + // If |aKey| is non-null, add cache information to it. 1.139 + bool Matches(nsPresContext* aPresContext, 1.140 + nsMediaQueryResultCacheKey* aKey) const; 1.141 + 1.142 +private: 1.143 + bool mNegated; 1.144 + bool mHasOnly; // only needed for serialization 1.145 + bool mTypeOmitted; // only needed for serialization 1.146 + bool mHadUnknownExpression; 1.147 + nsCOMPtr<nsIAtom> mMediaType; 1.148 + nsTArray<nsMediaExpression> mExpressions; 1.149 +}; 1.150 + 1.151 +class nsMediaList MOZ_FINAL : public nsIDOMMediaList 1.152 + , public nsWrapperCache 1.153 +{ 1.154 +public: 1.155 + typedef mozilla::ErrorResult ErrorResult; 1.156 + 1.157 + nsMediaList(); 1.158 + 1.159 + virtual JSObject* 1.160 + WrapObject(JSContext* aCx) MOZ_OVERRIDE; 1.161 + nsISupports* GetParentObject() const 1.162 + { 1.163 + return nullptr; 1.164 + } 1.165 + 1.166 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.167 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsMediaList) 1.168 + 1.169 + NS_DECL_NSIDOMMEDIALIST 1.170 + 1.171 + void GetText(nsAString& aMediaText); 1.172 + void SetText(const nsAString& aMediaText); 1.173 + 1.174 + // Does this query apply to the presentation? 1.175 + // If |aKey| is non-null, add cache information to it. 1.176 + bool Matches(nsPresContext* aPresContext, 1.177 + nsMediaQueryResultCacheKey* aKey); 1.178 + 1.179 + nsresult SetStyleSheet(nsCSSStyleSheet* aSheet); 1.180 + void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) { 1.181 + // Takes ownership of aQuery 1.182 + mArray.AppendElement(aQuery.forget()); 1.183 + } 1.184 + 1.185 + already_AddRefed<nsMediaList> Clone(); 1.186 + 1.187 + nsMediaQuery* MediumAt(int32_t aIndex) { return mArray[aIndex]; } 1.188 + void Clear() { mArray.Clear(); } 1.189 + 1.190 + // WebIDL 1.191 + // XPCOM GetMediaText and SetMediaText are fine. 1.192 + uint32_t Length() { return mArray.Length(); } 1.193 + void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aReturn); 1.194 + // XPCOM Item is fine. 1.195 + void DeleteMedium(const nsAString& aMedium, ErrorResult& aRv) 1.196 + { 1.197 + aRv = DeleteMedium(aMedium); 1.198 + } 1.199 + void AppendMedium(const nsAString& aMedium, ErrorResult& aRv) 1.200 + { 1.201 + aRv = AppendMedium(aMedium); 1.202 + } 1.203 + 1.204 +protected: 1.205 + ~nsMediaList(); 1.206 + 1.207 + nsresult Delete(const nsAString & aOldMedium); 1.208 + nsresult Append(const nsAString & aOldMedium); 1.209 + 1.210 + InfallibleTArray<nsAutoPtr<nsMediaQuery> > mArray; 1.211 + // not refcounted; sheet will let us know when it goes away 1.212 + // mStyleSheet is the sheet that needs to be dirtied when this medialist 1.213 + // changes 1.214 + nsCSSStyleSheet* mStyleSheet; 1.215 +}; 1.216 +#endif /* !defined(nsIMediaList_h_) */