1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : // vim:cindent:tabstop=2:expandtab:shiftwidth=2:
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * L. David Baron <dbaron@dbaron.org>
25 : * Pierre Phaneuf <pp@ludusdesign.com>
26 : * Daniel Glazman <glazman@netscape.com>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either of the GNU General Public License Version 2 or later (the "GPL"),
30 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : /* representation of a CSS style sheet */
43 :
44 : #ifndef nsCSSStyleSheet_h_
45 : #define nsCSSStyleSheet_h_
46 :
47 : #include "mozilla/Attributes.h"
48 :
49 : #include "nscore.h"
50 : #include "nsCOMPtr.h"
51 : #include "nsAutoPtr.h"
52 : #include "nsIStyleSheet.h"
53 : #include "nsIDOMCSSStyleSheet.h"
54 : #include "nsICSSLoaderObserver.h"
55 : #include "nsCOMArray.h"
56 : #include "nsTArray.h"
57 : #include "nsString.h"
58 :
59 : class nsXMLNameSpaceMap;
60 : class nsCSSRuleProcessor;
61 : class nsMediaList;
62 : class nsIPrincipal;
63 : class nsIURI;
64 : class nsMediaList;
65 : class nsMediaQueryResultCacheKey;
66 : class nsCSSStyleSheet;
67 : class nsPresContext;
68 : template<class E, class A> class nsTArray;
69 :
70 : namespace mozilla {
71 : namespace css {
72 : class Rule;
73 : class GroupRule;
74 : class ImportRule;
75 : }
76 : }
77 :
78 : // -------------------------------
79 : // CSS Style Sheet Inner Data Container
80 : //
81 :
82 : class nsCSSStyleSheetInner {
83 : public:
84 : friend class nsCSSStyleSheet;
85 : friend class nsCSSRuleProcessor;
86 : friend nsresult NS_NewCSSStyleSheet(nsCSSStyleSheet** aInstancePtrResult);
87 : private:
88 : nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet);
89 : nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
90 : nsCSSStyleSheet* aPrimarySheet);
91 : ~nsCSSStyleSheetInner();
92 :
93 : nsCSSStyleSheetInner* CloneFor(nsCSSStyleSheet* aPrimarySheet);
94 : void AddSheet(nsCSSStyleSheet* aSheet);
95 : void RemoveSheet(nsCSSStyleSheet* aSheet);
96 :
97 : void RebuildNameSpaces();
98 :
99 : // Create a new namespace map
100 : nsresult CreateNamespaceMap();
101 :
102 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
103 :
104 : nsAutoTArray<nsCSSStyleSheet*, 8> mSheets;
105 : nsCOMPtr<nsIURI> mSheetURI; // for error reports, etc.
106 : nsCOMPtr<nsIURI> mOriginalSheetURI; // for GetHref. Can be null.
107 : nsCOMPtr<nsIURI> mBaseURI; // for resolving relative URIs
108 : nsCOMPtr<nsIPrincipal> mPrincipal;
109 : nsCOMArray<mozilla::css::Rule> mOrderedRules;
110 : nsAutoPtr<nsXMLNameSpaceMap> mNameSpaceMap;
111 : // Linked list of child sheets. This is al fundamentally broken, because
112 : // each of the child sheets has a unique parent... We can only hope (and
113 : // currently this is the case) that any time page JS can get ts hands on a
114 : // child sheet that means we've already ensured unique inners throughout its
115 : // parent chain and things are good.
116 : nsRefPtr<nsCSSStyleSheet> mFirstChild;
117 : bool mComplete;
118 :
119 : #ifdef DEBUG
120 : bool mPrincipalSet;
121 : #endif
122 : };
123 :
124 :
125 : // -------------------------------
126 : // CSS Style Sheet
127 : //
128 :
129 : class CSSRuleListImpl;
130 : struct ChildSheetListBuilder;
131 :
132 : // CID for the nsCSSStyleSheet class
133 : // ca926f30-2a7e-477e-8467-803fb32af20a
134 : #define NS_CSS_STYLE_SHEET_IMPL_CID \
135 : { 0xca926f30, 0x2a7e, 0x477e, \
136 : { 0x84, 0x67, 0x80, 0x3f, 0xb3, 0x2a, 0xf2, 0x0a } }
137 :
138 :
139 : class nsCSSStyleSheet MOZ_FINAL : public nsIStyleSheet,
140 : public nsIDOMCSSStyleSheet,
141 : public nsICSSLoaderObserver
142 : {
143 : public:
144 : nsCSSStyleSheet();
145 :
146 : NS_DECL_ISUPPORTS
147 :
148 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_SHEET_IMPL_CID)
149 :
150 : // nsIStyleSheet interface
151 : virtual nsIURI* GetSheetURI() const;
152 : virtual nsIURI* GetBaseURI() const;
153 : virtual void GetTitle(nsString& aTitle) const;
154 : virtual void GetType(nsString& aType) const;
155 : virtual bool HasRules() const;
156 : virtual bool IsApplicable() const;
157 : virtual void SetEnabled(bool aEnabled);
158 : virtual bool IsComplete() const;
159 : virtual void SetComplete();
160 : virtual nsIStyleSheet* GetParentSheet() const; // may be null
161 : virtual nsIDocument* GetOwningDocument() const; // may be null
162 : virtual void SetOwningDocument(nsIDocument* aDocument);
163 :
164 : // Find the ID of the owner inner window.
165 : PRUint64 FindOwningWindowInnerID() const;
166 : #ifdef DEBUG
167 : virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
168 : #endif
169 :
170 : void AppendStyleSheet(nsCSSStyleSheet* aSheet);
171 : void InsertStyleSheetAt(nsCSSStyleSheet* aSheet, PRInt32 aIndex);
172 :
173 : // XXX do these belong here or are they generic?
174 : void PrependStyleRule(mozilla::css::Rule* aRule);
175 : void AppendStyleRule(mozilla::css::Rule* aRule);
176 : void ReplaceStyleRule(mozilla::css::Rule* aOld, mozilla::css::Rule* aNew);
177 :
178 : PRInt32 StyleRuleCount() const;
179 : nsresult GetStyleRuleAt(PRInt32 aIndex, mozilla::css::Rule*& aRule) const;
180 :
181 : nsresult DeleteRuleFromGroup(mozilla::css::GroupRule* aGroup, PRUint32 aIndex);
182 : nsresult InsertRuleIntoGroup(const nsAString& aRule, mozilla::css::GroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval);
183 : nsresult ReplaceRuleInGroup(mozilla::css::GroupRule* aGroup, mozilla::css::Rule* aOld, mozilla::css::Rule* aNew);
184 :
185 : PRInt32 StyleSheetCount() const;
186 :
187 : /**
188 : * SetURIs must be called on all sheets before parsing into them.
189 : * SetURIs may only be called while the sheet is 1) incomplete and 2)
190 : * has no rules in it
191 : */
192 : void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI, nsIURI* aBaseURI);
193 :
194 : /**
195 : * SetPrincipal should be called on all sheets before parsing into them.
196 : * This can only be called once with a non-null principal. Calling this with
197 : * a null pointer is allowed and is treated as a no-op.
198 : */
199 : void SetPrincipal(nsIPrincipal* aPrincipal);
200 :
201 : // Principal() never returns a null pointer.
202 0 : nsIPrincipal* Principal() const { return mInner->mPrincipal; }
203 :
204 0 : void SetTitle(const nsAString& aTitle) { mTitle = aTitle; }
205 : void SetMedia(nsMediaList* aMedia);
206 : void SetOwningNode(nsIDOMNode* aOwningNode) { mOwningNode = aOwningNode; /* Not ref counted */ }
207 :
208 0 : void SetOwnerRule(mozilla::css::ImportRule* aOwnerRule) { mOwnerRule = aOwnerRule; /* Not ref counted */ }
209 0 : mozilla::css::ImportRule* GetOwnerRule() const { return mOwnerRule; }
210 :
211 0 : nsXMLNameSpaceMap* GetNameSpaceMap() const { return mInner->mNameSpaceMap; }
212 :
213 : already_AddRefed<nsCSSStyleSheet> Clone(nsCSSStyleSheet* aCloneParent,
214 : mozilla::css::ImportRule* aCloneOwnerRule,
215 : nsIDocument* aCloneDocument,
216 : nsIDOMNode* aCloneOwningNode) const;
217 :
218 0 : bool IsModified() const { return mDirty; }
219 :
220 0 : void SetModifiedByChildRule() {
221 0 : NS_ASSERTION(mDirty,
222 : "sheet must be marked dirty before handing out child rules");
223 0 : DidDirty();
224 0 : }
225 :
226 : nsresult AddRuleProcessor(nsCSSRuleProcessor* aProcessor);
227 : nsresult DropRuleProcessor(nsCSSRuleProcessor* aProcessor);
228 :
229 : /**
230 : * Like the DOM insertRule() method, but doesn't do any security checks
231 : */
232 : nsresult InsertRuleInternal(const nsAString& aRule,
233 : PRUint32 aIndex, PRUint32* aReturn);
234 :
235 : /* Get the URI this sheet was originally loaded from, if any. Can
236 : return null */
237 : virtual nsIURI* GetOriginalURI() const;
238 :
239 : // nsICSSLoaderObserver interface
240 : NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
241 : nsresult aStatus);
242 :
243 : enum EnsureUniqueInnerResult {
244 : // No work was needed to ensure a unique inner.
245 : eUniqueInner_AlreadyUnique,
246 : // A clone was done to ensure a unique inner (which means the style
247 : // rules in this sheet have changed).
248 : eUniqueInner_ClonedInner,
249 : // A clone was attempted, but it failed.
250 : eUniqueInner_CloneFailed
251 : };
252 : EnsureUniqueInnerResult EnsureUniqueInner();
253 :
254 : // Append all of this sheet's child sheets to aArray. Return true
255 : // on success and false on allocation failure.
256 : bool AppendAllChildSheets(nsTArray<nsCSSStyleSheet*>& aArray);
257 :
258 : bool UseForPresentation(nsPresContext* aPresContext,
259 : nsMediaQueryResultCacheKey& aKey) const;
260 :
261 : // nsIDOMStyleSheet interface
262 : NS_DECL_NSIDOMSTYLESHEET
263 :
264 : // nsIDOMCSSStyleSheet interface
265 : NS_DECL_NSIDOMCSSSTYLESHEET
266 :
267 : // Function used as a callback to rebuild our inner's child sheet
268 : // list after we clone a unique inner for ourselves.
269 : static bool RebuildChildList(mozilla::css::Rule* aRule, void* aBuilder);
270 :
271 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
272 :
273 : private:
274 : nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
275 : nsCSSStyleSheet* aParentToUse,
276 : mozilla::css::ImportRule* aOwnerRuleToUse,
277 : nsIDocument* aDocumentToUse,
278 : nsIDOMNode* aOwningNodeToUse);
279 :
280 : nsCSSStyleSheet(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
281 : nsCSSStyleSheet& operator=(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
282 :
283 : protected:
284 : virtual ~nsCSSStyleSheet();
285 :
286 : void ClearRuleCascades();
287 :
288 : nsresult WillDirty();
289 : void DidDirty();
290 :
291 : // Return success if the subject principal subsumes the principal of our
292 : // inner, error otherwise. This will also succeed if the subject has
293 : // UniversalXPConnect.
294 : nsresult SubjectSubsumesInnerPrincipal() const;
295 :
296 : // Add the namespace mapping from this @namespace rule to our namespace map
297 : nsresult RegisterNamespaceRule(mozilla::css::Rule* aRule);
298 :
299 : protected:
300 : nsString mTitle;
301 : nsRefPtr<nsMediaList> mMedia;
302 : nsRefPtr<nsCSSStyleSheet> mNext;
303 : nsCSSStyleSheet* mParent; // weak ref
304 : mozilla::css::ImportRule* mOwnerRule; // weak ref
305 :
306 : CSSRuleListImpl* mRuleCollection;
307 : nsIDocument* mDocument; // weak ref; parents maintain this for their children
308 : nsIDOMNode* mOwningNode; // weak ref
309 : bool mDisabled;
310 : bool mDirty; // has been modified
311 :
312 : nsCSSStyleSheetInner* mInner;
313 :
314 : nsAutoTArray<nsCSSRuleProcessor*, 8>* mRuleProcessors;
315 :
316 : friend class nsMediaList;
317 : friend class nsCSSRuleProcessor;
318 : friend nsresult NS_NewCSSStyleSheet(nsCSSStyleSheet** aInstancePtrResult);
319 : friend struct ChildSheetListBuilder;
320 : };
321 :
322 : NS_DEFINE_STATIC_IID_ACCESSOR(nsCSSStyleSheet, NS_CSS_STYLE_SHEET_IMPL_CID)
323 :
324 : nsresult NS_NewCSSStyleSheet(nsCSSStyleSheet** aInstancePtrResult);
325 :
326 : #endif /* !defined(nsCSSStyleSheet_h_) */
|