1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 /* base class for DOM objects for element.style and cssStyleRule.style */
8 
9 #ifndef nsDOMCSSDeclaration_h___
10 #define nsDOMCSSDeclaration_h___
11 
12 #include "nsICSSDeclaration.h"
13 
14 #include "mozilla/Attributes.h"
15 #include "mozilla/Maybe.h"
16 #include "mozilla/URLExtraData.h"
17 #include "nsAttrValue.h"
18 #include "nsCOMPtr.h"
19 #include "nsCompatibility.h"
20 
21 class nsIPrincipal;
22 struct JSContext;
23 class JSObject;
24 
25 namespace mozilla {
26 class DeclarationBlock;
27 struct DeclarationBlockMutationClosure;
28 namespace css {
29 class Loader;
30 class Rule;
31 }  // namespace css
32 namespace dom {
33 class Document;
34 class Element;
35 }  // namespace dom
36 
37 struct MutationClosureData {
MutationClosureDataMutationClosureData38   MutationClosureData() : mClosure(nullptr), mElement(nullptr), mModType(0) {}
39 
40   // mClosure is non-null as long as the closure hasn't been called.
41   // This is needed so that it can be guaranteed that
42   // InlineStyleDeclarationWillChange is always called before
43   // SetInlineStyleDeclaration.
44   void (*mClosure)(void*);
45   mozilla::dom::Element* mElement;
46   Maybe<nsAttrValue> mOldValue;
47   uint8_t mModType;
48 };
49 
50 }  // namespace mozilla
51 
52 class nsDOMCSSDeclaration : public nsICSSDeclaration {
53  public:
54   // Only implement QueryInterface; subclasses have the responsibility
55   // of implementing AddRef/Release.
56   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
57 
58   // Declare addref and release so they can be called on us, but don't
59   // implement them.  Our subclasses must handle their own
60   // refcounting.
61   NS_IMETHOD_(MozExternalRefCountType) AddRef() override = 0;
62   NS_IMETHOD_(MozExternalRefCountType) Release() override = 0;
63 
64   /**
65    * Method analogous to CSSStyleDeclaration::GetPropertyValue,
66    * which obeys all the same restrictions.
67    */
68   virtual nsresult GetPropertyValue(const nsCSSPropertyID aPropID,
69                                     nsACString& aValue);
70 
71   /**
72    * Method analogous to CSSStyleDeclaration::SetProperty.  This
73    * method does NOT allow setting a priority (the priority will
74    * always be set to default priority).
75    */
76   virtual void SetPropertyValue(const nsCSSPropertyID aPropID,
77                                 const nsACString& aValue,
78                                 nsIPrincipal* aSubjectPrincipal,
79                                 mozilla::ErrorResult& aRv);
80 
81   // Require subclasses to implement |GetParentRule|.
82   // NS_DECL_NSIDOMCSSSTYLEDECLARATION
83   void GetCssText(nsACString& aCssText) override;
84   void SetCssText(const nsACString& aCssText, nsIPrincipal* aSubjectPrincipal,
85                   mozilla::ErrorResult& aRv) override;
86   NS_IMETHOD GetPropertyValue(const nsACString& propertyName,
87                               nsACString& _retval) override;
88   void RemoveProperty(const nsACString& propertyName, nsACString& _retval,
89                       mozilla::ErrorResult& aRv) override;
90   void GetPropertyPriority(const nsACString& propertyName,
91                            nsACString& aPriority) override;
92   void SetProperty(const nsACString& propertyName, const nsACString& value,
93                    const nsACString& priority, nsIPrincipal* aSubjectPrincipal,
94                    mozilla::ErrorResult& aRv) override;
95   uint32_t Length() override;
96 
97   // WebIDL interface for CSS2Properties
98 #define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) publicname_
99 #define CSS_PROP(id_, method_)                                                 \
100   void Get##method_(nsACString& aValue, mozilla::ErrorResult& rv) {            \
101     rv = GetPropertyValue(eCSSProperty_##id_, aValue);                         \
102   }                                                                            \
103                                                                                \
104   void Set##method_(const nsACString& aValue, nsIPrincipal* aSubjectPrincipal, \
105                     mozilla::ErrorResult& aRv) {                               \
106     SetPropertyValue(eCSSProperty_##id_, aValue, aSubjectPrincipal, aRv);      \
107   }
108 
109 #define CSS_PROP_LIST_EXCLUDE_INTERNAL
110 #define CSS_PROP_LIST_EXCLUDE_NOT_IN_STYLE
111 #define CSS_PROP_LONGHAND(name_, id_, method_, ...) CSS_PROP(id_, method_)
112 #define CSS_PROP_SHORTHAND(name_, id_, method_, ...) CSS_PROP(id_, method_)
113 #define CSS_PROP_ALIAS(name_, aliasid_, id_, method_, ...) \
114   CSS_PROP(id_, method_)
115 #include "mozilla/ServoCSSPropList.h"
116 #undef CSS_PROP_ALIAS
117 #undef CSS_PROP_SHORTHAND
118 #undef CSS_PROP_LONGHAND
119 #undef CSS_PROP_LIST_EXCLUDE_INTERNAL
120 #undef CSS_PROP_LIST_EXCLUDE_NOT_IN_STYLE
121 #undef CSS_PROP
122 #undef CSS_PROP_PUBLIC_OR_PRIVATE
123 
124   virtual void IndexedGetter(uint32_t aIndex, bool& aFound,
125                              nsACString& aPropName) override;
126 
127   JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
128 
129   // Information needed to parse a declaration for Servo side.
130   // Put this in public so other Servo parsing functions can reuse this.
131   struct MOZ_STACK_CLASS ParsingEnvironment {
132     RefPtr<mozilla::URLExtraData> mUrlExtraData;
133     nsCompatibility mCompatMode = eCompatibility_FullStandards;
134     mozilla::css::Loader* mLoader = nullptr;
135     uint16_t mRuleType{0};
136   };
137 
138  protected:
139   // The reason for calling GetOrCreateCSSDeclaration.
140   enum class Operation {
141     // We are calling GetOrCreateCSSDeclaration so that we can read from it.
142     // Does not allocate a new declaration if we don't have one yet; returns
143     // nullptr in this case.
144     Read,
145 
146     // We are calling GetOrCreateCSSDeclaration so that we can set a property on
147     // it or re-parse the whole declaration.  Allocates a new declaration if we
148     // don't have one yet. A nullptr return value indicates an error allocating
149     // the declaration.
150     Modify,
151 
152     // We are calling GetOrCreateCSSDeclaration so that we can remove a property
153     // from it. Does not allocate a new declaration if we don't have one yet;
154     // returns nullptr in this case.
155     RemoveProperty,
156   };
157 
158   // If aOperation is Modify, aCreated must be non-null and the call may set it
159   // to point to the newly created object.
160   virtual mozilla::DeclarationBlock* GetOrCreateCSSDeclaration(
161       Operation aOperation, mozilla::DeclarationBlock** aCreated) = 0;
162 
163   virtual nsresult SetCSSDeclaration(
164       mozilla::DeclarationBlock* aDecl,
165       mozilla::MutationClosureData* aClosureData) = 0;
166   // Document that we must call BeginUpdate/EndUpdate on around the
167   // calls to SetCSSDeclaration and the style rule mutation that leads
168   // to it.
169   virtual mozilla::dom::Document* DocToUpdate() = 0;
170 
171   // mUrlExtraData returns URL data for parsing url values in
172   // CSS. Returns nullptr on failure. If mUrlExtraData is nullptr,
173   // mCompatMode may not be set to anything meaningful.
174   // If aSubjectPrincipal is passed, it should be the subject principal of the
175   // scripted caller that initiated the parser.
176   virtual ParsingEnvironment GetParsingEnvironment(
177       nsIPrincipal* aSubjectPrincipal = nullptr) const = 0;
178 
179   // An implementation for GetParsingEnvironment for callers wrapping a
180   // css::Rule.
181   //
182   // The RuleType argument is just to avoid a virtual call, since all callers
183   // know it statically. Should be equal to aRule->Type().
184   static ParsingEnvironment GetParsingEnvironmentForRule(
185       const mozilla::css::Rule* aRule, uint16_t aRuleType);
186 
187   nsresult ParsePropertyValue(const nsCSSPropertyID aPropID,
188                               const nsACString& aPropValue, bool aIsImportant,
189                               nsIPrincipal* aSubjectPrincipal);
190 
191   nsresult ParseCustomPropertyValue(const nsACString& aPropertyName,
192                                     const nsACString& aPropValue,
193                                     bool aIsImportant,
194                                     nsIPrincipal* aSubjectPrincipal);
195 
196   void RemovePropertyInternal(nsCSSPropertyID aPropID,
197                               mozilla::ErrorResult& aRv);
198   void RemovePropertyInternal(const nsACString& aPropert,
199                               mozilla::ErrorResult& aRv);
200 
GetPropertyChangeClosure(mozilla::DeclarationBlockMutationClosure * aClosure,mozilla::MutationClosureData * aClosureData)201   virtual void GetPropertyChangeClosure(
202       mozilla::DeclarationBlockMutationClosure* aClosure,
203       mozilla::MutationClosureData* aClosureData) {}
204 
205  protected:
206   virtual ~nsDOMCSSDeclaration();
207 
208  private:
209   template <typename ServoFunc>
210   inline nsresult ModifyDeclaration(nsIPrincipal* aSubjectPrincipal,
211                                     mozilla::MutationClosureData* aClosureData,
212                                     ServoFunc aServoFunc);
213 };
214 
215 #endif  // nsDOMCSSDeclaration_h___
216