1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:cindent:tabstop=2:expandtab:shiftwidth=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 /* representation of a CSS style sheet */
9 #ifndef mozilla_CSSStyleSheet_h
10 #define mozilla_CSSStyleSheet_h
12 #include "mozilla/Attributes.h"
13 #include "mozilla/MemoryReporting.h"
14 #include "mozilla/dom/Element.h"
18 #include "nsAutoPtr.h"
19 #include "nsIStyleSheet.h"
20 #include "nsIDOMCSSStyleSheet.h"
21 #include "nsICSSLoaderObserver.h"
22 #include "nsCOMArray.h"
23 #include "nsTArrayForwardDeclare.h"
25 #include "mozilla/CORSMode.h"
26 #include "nsCycleCollectionParticipant.h"
27 #include "nsWrapperCache.h"
29 class CSSRuleListImpl
;
30 class nsCSSRuleProcessor
;
35 class nsMediaQueryResultCacheKey
;
37 class nsXMLNameSpaceMap
;
40 struct ChildSheetListBuilder
;
52 // -------------------------------
53 // CSS Style Sheet Inner Data Container
56 class CSSStyleSheetInner
59 friend class mozilla::CSSStyleSheet
;
60 friend class ::nsCSSRuleProcessor
;
62 CSSStyleSheetInner(CSSStyleSheet
* aPrimarySheet
,
64 CSSStyleSheetInner(CSSStyleSheetInner
& aCopy
,
65 CSSStyleSheet
* aPrimarySheet
);
66 ~CSSStyleSheetInner();
68 CSSStyleSheetInner
* CloneFor(CSSStyleSheet
* aPrimarySheet
);
69 void AddSheet(CSSStyleSheet
* aSheet
);
70 void RemoveSheet(CSSStyleSheet
* aSheet
);
72 void RebuildNameSpaces();
74 // Create a new namespace map
75 nsresult
CreateNamespaceMap();
77 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) const;
79 nsAutoTArray
<CSSStyleSheet
*, 8> mSheets
;
80 nsCOMPtr
<nsIURI
> mSheetURI
; // for error reports, etc.
81 nsCOMPtr
<nsIURI
> mOriginalSheetURI
; // for GetHref. Can be null.
82 nsCOMPtr
<nsIURI
> mBaseURI
; // for resolving relative URIs
83 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
84 nsCOMArray
<css::Rule
> mOrderedRules
;
85 nsAutoPtr
<nsXMLNameSpaceMap
> mNameSpaceMap
;
86 // Linked list of child sheets. This is al fundamentally broken, because
87 // each of the child sheets has a unique parent... We can only hope (and
88 // currently this is the case) that any time page JS can get ts hands on a
89 // child sheet that means we've already ensured unique inners throughout its
90 // parent chain and things are good.
91 nsRefPtr
<CSSStyleSheet
> mFirstChild
;
101 // -------------------------------
105 // CID for the CSSStyleSheet class
106 // ca926f30-2a7e-477e-8467-803fb32af20a
107 #define NS_CSS_STYLE_SHEET_IMPL_CID \
108 { 0xca926f30, 0x2a7e, 0x477e, \
109 { 0x84, 0x67, 0x80, 0x3f, 0xb3, 0x2a, 0xf2, 0x0a } }
112 class CSSStyleSheet MOZ_FINAL
: public nsIStyleSheet
,
113 public nsIDOMCSSStyleSheet
,
114 public nsICSSLoaderObserver
,
115 public nsWrapperCache
118 explicit CSSStyleSheet(CORSMode aCORSMode
);
120 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
121 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CSSStyleSheet
,
124 NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_SHEET_IMPL_CID
)
126 // nsIStyleSheet interface
127 virtual nsIURI
* GetSheetURI() const MOZ_OVERRIDE
;
128 virtual nsIURI
* GetBaseURI() const MOZ_OVERRIDE
;
129 virtual void GetTitle(nsString
& aTitle
) const MOZ_OVERRIDE
;
130 virtual void GetType(nsString
& aType
) const MOZ_OVERRIDE
;
131 virtual bool HasRules() const MOZ_OVERRIDE
;
132 virtual bool IsApplicable() const MOZ_OVERRIDE
;
133 virtual void SetEnabled(bool aEnabled
) MOZ_OVERRIDE
;
134 virtual bool IsComplete() const MOZ_OVERRIDE
;
135 virtual void SetComplete() MOZ_OVERRIDE
;
136 virtual nsIStyleSheet
* GetParentSheet() const MOZ_OVERRIDE
; // may be null
137 virtual nsIDocument
* GetOwningDocument() const MOZ_OVERRIDE
; // may be null
138 virtual void SetOwningDocument(nsIDocument
* aDocument
) MOZ_OVERRIDE
;
140 // Find the ID of the owner inner window.
141 uint64_t FindOwningWindowInnerID() const;
143 virtual void List(FILE* out
= stdout
, int32_t aIndent
= 0) const MOZ_OVERRIDE
;
146 void AppendStyleSheet(CSSStyleSheet
* aSheet
);
147 void InsertStyleSheetAt(CSSStyleSheet
* aSheet
, int32_t aIndex
);
149 // XXX do these belong here or are they generic?
150 void PrependStyleRule(css::Rule
* aRule
);
151 void AppendStyleRule(css::Rule
* aRule
);
152 void ReplaceStyleRule(css::Rule
* aOld
, css::Rule
* aNew
);
154 int32_t StyleRuleCount() const;
155 css::Rule
* GetStyleRuleAt(int32_t aIndex
) const;
157 nsresult
DeleteRuleFromGroup(css::GroupRule
* aGroup
, uint32_t aIndex
);
158 nsresult
InsertRuleIntoGroup(const nsAString
& aRule
, css::GroupRule
* aGroup
, uint32_t aIndex
, uint32_t* _retval
);
159 nsresult
ReplaceRuleInGroup(css::GroupRule
* aGroup
, css::Rule
* aOld
, css::Rule
* aNew
);
161 int32_t StyleSheetCount() const;
164 * SetURIs must be called on all sheets before parsing into them.
165 * SetURIs may only be called while the sheet is 1) incomplete and 2)
168 void SetURIs(nsIURI
* aSheetURI
, nsIURI
* aOriginalSheetURI
, nsIURI
* aBaseURI
);
171 * SetPrincipal should be called on all sheets before parsing into them.
172 * This can only be called once with a non-null principal. Calling this with
173 * a null pointer is allowed and is treated as a no-op.
175 void SetPrincipal(nsIPrincipal
* aPrincipal
);
177 // Principal() never returns a null pointer.
178 nsIPrincipal
* Principal() const { return mInner
->mPrincipal
; }
180 // The document this style sheet is associated with. May be null
181 nsIDocument
* GetDocument() const { return mDocument
; }
183 void SetTitle(const nsAString
& aTitle
) { mTitle
= aTitle
; }
184 void SetMedia(nsMediaList
* aMedia
);
185 void SetOwningNode(nsINode
* aOwningNode
) { mOwningNode
= aOwningNode
; /* Not ref counted */ }
187 void SetOwnerRule(css::ImportRule
* aOwnerRule
) { mOwnerRule
= aOwnerRule
; /* Not ref counted */ }
188 css::ImportRule
* GetOwnerRule() const { return mOwnerRule
; }
190 nsXMLNameSpaceMap
* GetNameSpaceMap() const { return mInner
->mNameSpaceMap
; }
192 already_AddRefed
<CSSStyleSheet
> Clone(CSSStyleSheet
* aCloneParent
,
193 css::ImportRule
* aCloneOwnerRule
,
194 nsIDocument
* aCloneDocument
,
195 nsINode
* aCloneOwningNode
) const;
197 bool IsModified() const { return mDirty
; }
199 void SetModifiedByChildRule() {
201 "sheet must be marked dirty before handing out child rules");
205 nsresult
AddRuleProcessor(nsCSSRuleProcessor
* aProcessor
);
206 nsresult
DropRuleProcessor(nsCSSRuleProcessor
* aProcessor
);
209 * Like the DOM insertRule() method, but doesn't do any security checks
211 nsresult
InsertRuleInternal(const nsAString
& aRule
,
212 uint32_t aIndex
, uint32_t* aReturn
);
214 /* Get the URI this sheet was originally loaded from, if any. Can
216 virtual nsIURI
* GetOriginalURI() const;
218 // nsICSSLoaderObserver interface
219 NS_IMETHOD
StyleSheetLoaded(CSSStyleSheet
* aSheet
, bool aWasAlternate
,
220 nsresult aStatus
) MOZ_OVERRIDE
;
222 enum EnsureUniqueInnerResult
{
223 // No work was needed to ensure a unique inner.
224 eUniqueInner_AlreadyUnique
,
225 // A clone was done to ensure a unique inner (which means the style
226 // rules in this sheet have changed).
227 eUniqueInner_ClonedInner
229 EnsureUniqueInnerResult
EnsureUniqueInner();
231 // Append all of this sheet's child sheets to aArray.
232 void AppendAllChildSheets(nsTArray
<CSSStyleSheet
*>& aArray
);
234 bool UseForPresentation(nsPresContext
* aPresContext
,
235 nsMediaQueryResultCacheKey
& aKey
) const;
237 nsresult
ParseSheet(const nsAString
& aInput
);
239 // nsIDOMStyleSheet interface
240 NS_DECL_NSIDOMSTYLESHEET
242 // nsIDOMCSSStyleSheet interface
243 NS_DECL_NSIDOMCSSSTYLESHEET
245 // Function used as a callback to rebuild our inner's child sheet
246 // list after we clone a unique inner for ourselves.
247 static bool RebuildChildList(css::Rule
* aRule
, void* aBuilder
);
249 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) const MOZ_OVERRIDE
;
251 // Get this style sheet's CORS mode
252 CORSMode
GetCORSMode() const { return mInner
->mCORSMode
; }
254 dom::Element
* GetScopeElement() const { return mScopeElement
; }
255 void SetScopeElement(dom::Element
* aScopeElement
)
257 mScopeElement
= aScopeElement
;
260 // WebIDL StyleSheet API
261 // Our nsIStyleSheet::GetType is a const method, so it ends up
262 // ambiguous with with the XPCOM version. Just disambiguate.
263 void GetType(nsString
& aType
) {
264 const_cast<const CSSStyleSheet
*>(this)->GetType(aType
);
266 // Our XPCOM GetHref is fine for WebIDL
267 nsINode
* GetOwnerNode() const { return mOwningNode
; }
268 CSSStyleSheet
* GetParentStyleSheet() const { return mParent
; }
269 // Our nsIStyleSheet::GetTitle is a const method, so it ends up
270 // ambiguous with with the XPCOM version. Just disambiguate.
271 void GetTitle(nsString
& aTitle
) {
272 const_cast<const CSSStyleSheet
*>(this)->GetTitle(aTitle
);
274 nsMediaList
* Media();
275 bool Disabled() const { return mDisabled
; }
276 // The XPCOM SetDisabled is fine for WebIDL
278 // WebIDL CSSStyleSheet API
279 // Can't be inline because we can't include ImportRule here. And can't be
280 // called GetOwnerRule because that would be ambiguous with the ImportRule
282 nsIDOMCSSRule
* GetDOMOwnerRule() const;
283 dom::CSSRuleList
* GetCssRules(ErrorResult
& aRv
);
284 uint32_t InsertRule(const nsAString
& aRule
, uint32_t aIndex
,
287 aRv
= InsertRule(aRule
, aIndex
, &retval
);
290 void DeleteRule(uint32_t aIndex
, ErrorResult
& aRv
) {
291 aRv
= DeleteRule(aIndex
);
294 // WebIDL miscellaneous bits
295 dom::ParentObject
GetParentObject() const {
297 return dom::ParentObject(mOwningNode
);
300 return dom::ParentObject(static_cast<nsIStyleSheet
*>(mParent
), mParent
);
302 virtual JSObject
* WrapObject(JSContext
* aCx
) MOZ_OVERRIDE
;
305 CSSStyleSheet(const CSSStyleSheet
& aCopy
,
306 CSSStyleSheet
* aParentToUse
,
307 css::ImportRule
* aOwnerRuleToUse
,
308 nsIDocument
* aDocumentToUse
,
309 nsINode
* aOwningNodeToUse
);
311 CSSStyleSheet(const CSSStyleSheet
& aCopy
) MOZ_DELETE
;
312 CSSStyleSheet
& operator=(const CSSStyleSheet
& aCopy
) MOZ_DELETE
;
315 virtual ~CSSStyleSheet();
317 void ClearRuleCascades();
322 // Return success if the subject principal subsumes the principal of our
323 // inner, error otherwise. This will also succeed if the subject has
324 // UniversalXPConnect or if access is allowed by CORS. In the latter case,
325 // it will set the principal of the inner to the subject principal.
326 nsresult
SubjectSubsumesInnerPrincipal();
328 // Add the namespace mapping from this @namespace rule to our namespace map
329 nsresult
RegisterNamespaceRule(css::Rule
* aRule
);
331 // Drop our reference to mRuleCollection
332 void DropRuleCollection();
334 // Drop our reference to mMedia
337 // Unlink our inner, if needed, for cycle collection
339 // Traverse our inner, if needed, for cycle collection
340 void TraverseInner(nsCycleCollectionTraversalCallback
&);
344 nsRefPtr
<nsMediaList
> mMedia
;
345 nsRefPtr
<CSSStyleSheet
> mNext
;
346 CSSStyleSheet
* mParent
; // weak ref
347 css::ImportRule
* mOwnerRule
; // weak ref
349 nsRefPtr
<CSSRuleListImpl
> mRuleCollection
;
350 nsIDocument
* mDocument
; // weak ref; parents maintain this for their children
351 nsINode
* mOwningNode
; // weak ref
353 bool mDirty
; // has been modified
354 nsRefPtr
<dom::Element
> mScopeElement
;
356 CSSStyleSheetInner
* mInner
;
358 nsAutoTArray
<nsCSSRuleProcessor
*, 8>* mRuleProcessors
;
360 friend class ::nsMediaList
;
361 friend class ::nsCSSRuleProcessor
;
362 friend struct mozilla::ChildSheetListBuilder
;
365 NS_DEFINE_STATIC_IID_ACCESSOR(CSSStyleSheet
, NS_CSS_STYLE_SHEET_IMPL_CID
)
367 } // namespace mozilla
369 #endif /* !defined(mozilla_CSSStyleSheet_h) */