Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / style / nsCSSRules.cpp
bloba8045e99b218c9e8489736385a88db365de7e1dd
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Boris Zbarsky <bzbarsky@mit.edu>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
41 #include "nsCSSRules.h"
42 #include "nsCSSValue.h"
43 #include "nsICSSImportRule.h"
44 #include "nsICSSNameSpaceRule.h"
46 #include "nsString.h"
47 #include "nsIAtom.h"
48 #include "nsIURL.h"
50 #include "nsCSSRule.h"
51 #include "nsCSSProps.h"
52 #include "nsICSSStyleSheet.h"
54 #include "nsCOMPtr.h"
55 #include "nsIDOMCSSStyleSheet.h"
56 #include "nsIDOMCSSRule.h"
57 #include "nsIDOMCSSImportRule.h"
58 #include "nsIDOMCSSMediaRule.h"
59 #include "nsIDOMCSSMozDocumentRule.h"
60 #include "nsIDOMCSSCharsetRule.h"
61 #include "nsIDOMCSSStyleDeclaration.h"
62 #include "nsIMediaList.h"
63 #include "nsIDOMMediaList.h"
64 #include "nsICSSRuleList.h"
65 #include "nsIDOMStyleSheet.h"
66 #include "nsIDocument.h"
67 #include "nsPresContext.h"
69 #include "nsContentUtils.h"
70 #include "nsStyleConsts.h"
71 #include "nsDOMError.h"
72 #include "nsStyleUtil.h"
73 #include "nsCSSDeclaration.h"
75 #define IMPL_STYLE_RULE_INHERIT(_class, super) \
76 NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); } \
77 NS_IMETHODIMP _class::SetStyleSheet(nsICSSStyleSheet* aSheet) { return super::SetStyleSheet(aSheet); } \
78 NS_IMETHODIMP _class::SetParentRule(nsICSSGroupRule* aRule) { return super::SetParentRule(aRule); } \
79 nsIDOMCSSRule* _class::GetDOMRuleWeak(nsresult *aResult) { *aResult = NS_OK; return this; } \
80 NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; }
82 #define IMPL_STYLE_RULE_INHERIT2(_class, super) \
83 NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); } \
84 NS_IMETHODIMP _class::SetParentRule(nsICSSGroupRule* aRule) { return super::SetParentRule(aRule); } \
85 NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; }
87 // -------------------------------
88 // Style Rule List for group rules
90 class CSSGroupRuleRuleListImpl : public nsICSSRuleList
92 public:
93 CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule);
95 NS_DECL_ISUPPORTS
97 NS_DECL_NSIDOMCSSRULELIST
99 virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult);
101 void DropReference() { mGroupRule = nsnull; }
103 protected:
104 virtual ~CSSGroupRuleRuleListImpl(void);
106 private:
107 nsICSSGroupRule* mGroupRule;
110 CSSGroupRuleRuleListImpl::CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule)
112 // Not reference counted to avoid circular references.
113 // The rule will tell us when its going away.
114 mGroupRule = aGroupRule;
117 CSSGroupRuleRuleListImpl::~CSSGroupRuleRuleListImpl()
121 // QueryInterface implementation for CSSGroupRuleRuleList
122 NS_INTERFACE_MAP_BEGIN(CSSGroupRuleRuleListImpl)
123 NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
124 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
125 NS_INTERFACE_MAP_ENTRY(nsISupports)
126 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSGroupRuleRuleList)
127 NS_INTERFACE_MAP_END
130 NS_IMPL_ADDREF(CSSGroupRuleRuleListImpl)
131 NS_IMPL_RELEASE(CSSGroupRuleRuleListImpl)
133 NS_IMETHODIMP
134 CSSGroupRuleRuleListImpl::GetLength(PRUint32* aLength)
136 if (mGroupRule) {
137 PRInt32 count;
138 mGroupRule->StyleRuleCount(count);
139 *aLength = (PRUint32)count;
140 } else {
141 *aLength = 0;
144 return NS_OK;
147 nsIDOMCSSRule*
148 CSSGroupRuleRuleListImpl::GetItemAt(PRUint32 aIndex, nsresult* aResult)
150 nsresult result = NS_OK;
152 if (mGroupRule) {
153 nsCOMPtr<nsICSSRule> rule;
155 result = mGroupRule->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
156 if (rule) {
157 return rule->GetDOMRuleWeak(aResult);
159 if (result == NS_ERROR_ILLEGAL_VALUE) {
160 result = NS_OK; // per spec: "Return Value ... null if ... not a valid index."
164 *aResult = result;
166 return nsnull;
169 NS_IMETHODIMP
170 CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
172 nsresult rv;
173 nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
174 if (!rule) {
175 *aReturn = nsnull;
176 return rv;
179 return CallQueryInterface(rule, aReturn);
182 // -------------------------------------------
183 // CharsetRule
185 class CSSCharsetRuleImpl : public nsCSSRule,
186 public nsICSSRule,
187 public nsIDOMCSSCharsetRule
189 public:
190 CSSCharsetRuleImpl(const nsAString& aEncoding);
191 CSSCharsetRuleImpl(const CSSCharsetRuleImpl& aCopy);
192 virtual ~CSSCharsetRuleImpl(void);
194 NS_DECL_ISUPPORTS_INHERITED
196 DECL_STYLE_RULE_INHERIT
198 // nsIStyleRule methods
199 #ifdef DEBUG
200 NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
201 #endif
203 // nsICSSRule methods
204 NS_IMETHOD GetType(PRInt32& aType) const;
205 NS_IMETHOD Clone(nsICSSRule*& aClone) const;
207 // nsIDOMCSSRule interface
208 NS_DECL_NSIDOMCSSRULE
210 // nsIDOMCSSCharsetRule methods
211 NS_IMETHOD GetEncoding(nsAString& aEncoding);
212 NS_IMETHOD SetEncoding(const nsAString& aEncoding);
214 protected:
215 nsString mEncoding;
218 CSSCharsetRuleImpl::CSSCharsetRuleImpl(const nsAString& aEncoding)
219 : nsCSSRule(),
220 mEncoding(aEncoding)
224 CSSCharsetRuleImpl::CSSCharsetRuleImpl(const CSSCharsetRuleImpl& aCopy)
225 : nsCSSRule(aCopy),
226 mEncoding(aCopy.mEncoding)
230 CSSCharsetRuleImpl::~CSSCharsetRuleImpl(void)
234 NS_IMPL_ADDREF_INHERITED(CSSCharsetRuleImpl, nsCSSRule)
235 NS_IMPL_RELEASE_INHERITED(CSSCharsetRuleImpl, nsCSSRule)
237 // QueryInterface implementation for CSSCharsetRuleImpl
238 NS_INTERFACE_MAP_BEGIN(CSSCharsetRuleImpl)
239 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
240 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
241 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
242 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule)
243 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule)
244 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSCharsetRule)
245 NS_INTERFACE_MAP_END
247 IMPL_STYLE_RULE_INHERIT(CSSCharsetRuleImpl, nsCSSRule)
249 #ifdef DEBUG
250 NS_IMETHODIMP
251 CSSCharsetRuleImpl::List(FILE* out, PRInt32 aIndent) const
253 // Indent
254 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
256 fputs("@charset \"", out);
257 fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out);
258 fputs("\"\n", out);
260 return NS_OK;
262 #endif
264 NS_IMETHODIMP
265 CSSCharsetRuleImpl::GetType(PRInt32& aType) const
267 aType = nsICSSRule::CHARSET_RULE;
268 return NS_OK;
271 NS_IMETHODIMP
272 CSSCharsetRuleImpl::Clone(nsICSSRule*& aClone) const
274 CSSCharsetRuleImpl* clone = new CSSCharsetRuleImpl(*this);
275 if (clone) {
276 return CallQueryInterface(clone, &aClone);
278 aClone = nsnull;
279 return NS_ERROR_OUT_OF_MEMORY;
282 NS_IMETHODIMP
283 CSSCharsetRuleImpl::GetEncoding(nsAString& aEncoding)
285 aEncoding = mEncoding;
286 return NS_OK;
289 NS_IMETHODIMP
290 CSSCharsetRuleImpl::SetEncoding(const nsAString& aEncoding)
292 mEncoding = aEncoding;
293 return NS_OK;
297 nsresult
298 NS_NewCSSCharsetRule(nsICSSRule** aInstancePtrResult, const nsAString& aEncoding)
300 if (! aInstancePtrResult) {
301 return NS_ERROR_NULL_POINTER;
304 CSSCharsetRuleImpl* it = new CSSCharsetRuleImpl(aEncoding);
306 if (! it) {
307 return NS_ERROR_OUT_OF_MEMORY;
310 return CallQueryInterface(it, aInstancePtrResult);
313 NS_IMETHODIMP
314 CSSCharsetRuleImpl::GetType(PRUint16* aType)
316 *aType = nsIDOMCSSRule::CHARSET_RULE;
317 return NS_OK;
320 NS_IMETHODIMP
321 CSSCharsetRuleImpl::GetCssText(nsAString& aCssText)
323 aCssText.AssignLiteral("@charset \"");
324 aCssText.Append(mEncoding);
325 aCssText.AppendLiteral("\";");
326 return NS_OK;
329 NS_IMETHODIMP
330 CSSCharsetRuleImpl::SetCssText(const nsAString& aCssText)
332 return NS_ERROR_NOT_IMPLEMENTED;
335 NS_IMETHODIMP
336 CSSCharsetRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
338 NS_ENSURE_ARG_POINTER(aSheet);
340 if (mSheet) {
341 return CallQueryInterface(mSheet, aSheet);
343 *aSheet = nsnull;
344 return NS_OK;
347 NS_IMETHODIMP
348 CSSCharsetRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
350 if (mParentRule) {
351 return mParentRule->GetDOMRule(aParentRule);
353 *aParentRule = nsnull;
354 return NS_OK;
359 // -------------------------------------------
360 // nsICSSImportRule
362 class CSSImportRuleImpl : public nsCSSRule,
363 public nsICSSImportRule,
364 public nsIDOMCSSImportRule
366 public:
367 CSSImportRuleImpl(nsMediaList* aMedia);
368 CSSImportRuleImpl(const CSSImportRuleImpl& aCopy);
369 virtual ~CSSImportRuleImpl(void);
371 NS_DECL_ISUPPORTS_INHERITED
373 DECL_STYLE_RULE_INHERIT
375 // nsIStyleRule methods
376 #ifdef DEBUG
377 NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
378 #endif
380 // nsICSSRule methods
381 NS_IMETHOD GetType(PRInt32& aType) const;
382 NS_IMETHOD Clone(nsICSSRule*& aClone) const;
384 // nsICSSImportRule methods
385 NS_IMETHOD SetURLSpec(const nsString& aURLSpec);
386 NS_IMETHOD GetURLSpec(nsString& aURLSpec) const;
388 NS_IMETHOD SetMedia(const nsString& aMedia);
389 NS_IMETHOD GetMedia(nsString& aMedia) const;
391 NS_IMETHOD SetSheet(nsICSSStyleSheet*);
393 // nsIDOMCSSRule interface
394 NS_DECL_NSIDOMCSSRULE
396 // nsIDOMCSSImportRule interface
397 NS_DECL_NSIDOMCSSIMPORTRULE
399 protected:
400 nsString mURLSpec;
401 nsRefPtr<nsMediaList> mMedia;
402 nsCOMPtr<nsICSSStyleSheet> mChildSheet;
405 CSSImportRuleImpl::CSSImportRuleImpl(nsMediaList* aMedia)
406 : nsCSSRule()
407 , mURLSpec()
408 , mMedia(aMedia)
410 // XXXbz This is really silly.... the mMedia here will be replaced
411 // with itself if we manage to load a sheet. Which should really
412 // never fail nowadays, in sane cases.
415 CSSImportRuleImpl::CSSImportRuleImpl(const CSSImportRuleImpl& aCopy)
416 : nsCSSRule(aCopy),
417 mURLSpec(aCopy.mURLSpec)
419 nsCOMPtr<nsICSSStyleSheet> sheet;
420 if (aCopy.mChildSheet) {
421 aCopy.mChildSheet->Clone(nsnull, this, nsnull, nsnull,
422 getter_AddRefs(sheet));
424 SetSheet(sheet);
425 // SetSheet sets mMedia appropriately
428 CSSImportRuleImpl::~CSSImportRuleImpl(void)
430 if (mChildSheet) {
431 mChildSheet->SetOwnerRule(nsnull);
435 NS_IMPL_ADDREF_INHERITED(CSSImportRuleImpl, nsCSSRule)
436 NS_IMPL_RELEASE_INHERITED(CSSImportRuleImpl, nsCSSRule)
438 // QueryInterface implementation for CSSImportRuleImpl
439 NS_INTERFACE_MAP_BEGIN(CSSImportRuleImpl)
440 NS_INTERFACE_MAP_ENTRY(nsICSSImportRule)
441 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
442 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
443 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
444 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
445 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSImportRule)
446 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSImportRule)
447 NS_INTERFACE_MAP_END
449 IMPL_STYLE_RULE_INHERIT(CSSImportRuleImpl, nsCSSRule)
451 #ifdef DEBUG
452 NS_IMETHODIMP
453 CSSImportRuleImpl::List(FILE* out, PRInt32 aIndent) const
455 // Indent
456 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
458 fputs("@import \"", out);
459 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
460 fputs("\" ", out);
462 nsAutoString mediaText;
463 mMedia->GetText(mediaText);
464 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
465 fputs("\n", out);
467 return NS_OK;
469 #endif
471 NS_IMETHODIMP
472 CSSImportRuleImpl::GetType(PRInt32& aType) const
474 aType = nsICSSRule::IMPORT_RULE;
475 return NS_OK;
478 NS_IMETHODIMP
479 CSSImportRuleImpl::Clone(nsICSSRule*& aClone) const
481 CSSImportRuleImpl* clone = new CSSImportRuleImpl(*this);
482 if (clone) {
483 return CallQueryInterface(clone, &aClone);
485 aClone = nsnull;
486 return NS_ERROR_OUT_OF_MEMORY;
489 NS_IMETHODIMP
490 CSSImportRuleImpl::SetURLSpec(const nsString& aURLSpec)
492 mURLSpec = aURLSpec;
493 return NS_OK;
496 NS_IMETHODIMP
497 CSSImportRuleImpl::GetURLSpec(nsString& aURLSpec) const
499 aURLSpec = mURLSpec;
500 return NS_OK;
503 NS_IMETHODIMP
504 CSSImportRuleImpl::SetMedia(const nsString& aMedia)
506 if (mMedia) {
507 return mMedia->SetText(aMedia);
508 } else {
509 return NS_OK;
513 NS_IMETHODIMP
514 CSSImportRuleImpl::GetMedia(nsString& aMedia) const
516 if (mMedia) {
517 return mMedia->GetText(aMedia);
518 } else {
519 aMedia.Truncate();
520 return NS_OK;
524 NS_IMETHODIMP
525 CSSImportRuleImpl::SetSheet(nsICSSStyleSheet* aSheet)
527 nsresult rv;
528 NS_ENSURE_ARG_POINTER(aSheet);
530 // set the new sheet
531 mChildSheet = aSheet;
532 aSheet->SetOwnerRule(this);
534 // set our medialist to be the same as the sheet's medialist
535 nsCOMPtr<nsIDOMStyleSheet> sheet(do_QueryInterface(mChildSheet, &rv));
536 NS_ENSURE_SUCCESS(rv, rv);
537 nsCOMPtr<nsIDOMMediaList> mediaList;
538 rv = sheet->GetMedia(getter_AddRefs(mediaList));
539 NS_ENSURE_SUCCESS(rv, rv);
540 mMedia = static_cast<nsMediaList*>(mediaList.get());
542 return NS_OK;
545 nsresult
546 NS_NewCSSImportRule(nsICSSImportRule** aInstancePtrResult,
547 const nsString& aURLSpec,
548 nsMediaList* aMedia)
550 NS_ENSURE_ARG_POINTER(aInstancePtrResult);
552 CSSImportRuleImpl* it = new CSSImportRuleImpl(aMedia);
554 if (! it) {
555 return NS_ERROR_OUT_OF_MEMORY;
558 it->SetURLSpec(aURLSpec);
559 return CallQueryInterface(it, aInstancePtrResult);
562 NS_IMETHODIMP
563 CSSImportRuleImpl::GetType(PRUint16* aType)
565 NS_ENSURE_ARG_POINTER(aType);
566 *aType = nsIDOMCSSRule::IMPORT_RULE;
567 return NS_OK;
570 NS_IMETHODIMP
571 CSSImportRuleImpl::GetCssText(nsAString& aCssText)
573 aCssText.AssignLiteral("@import url(");
574 aCssText.Append(mURLSpec);
575 aCssText.Append(NS_LITERAL_STRING(")"));
576 if (mMedia) {
577 nsAutoString mediaText;
578 mMedia->GetText(mediaText);
579 if (!mediaText.IsEmpty()) {
580 aCssText.AppendLiteral(" ");
581 aCssText.Append(mediaText);
584 aCssText.AppendLiteral(";");
585 return NS_OK;
588 NS_IMETHODIMP
589 CSSImportRuleImpl::SetCssText(const nsAString& aCssText)
591 return NS_ERROR_NOT_IMPLEMENTED;
594 NS_IMETHODIMP
595 CSSImportRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
597 NS_ENSURE_ARG_POINTER(aSheet);
598 if (mSheet) {
599 return CallQueryInterface(mSheet, aSheet);
601 *aSheet = nsnull;
602 return NS_OK;
605 NS_IMETHODIMP
606 CSSImportRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
608 if (mParentRule) {
609 return mParentRule->GetDOMRule(aParentRule);
611 *aParentRule = nsnull;
612 return NS_OK;
615 NS_IMETHODIMP
616 CSSImportRuleImpl::GetHref(nsAString & aHref)
618 aHref = mURLSpec;
619 return NS_OK;
622 NS_IMETHODIMP
623 CSSImportRuleImpl::GetMedia(nsIDOMMediaList * *aMedia)
625 NS_ENSURE_ARG_POINTER(aMedia);
626 if (!mMedia) {
627 *aMedia = nsnull;
628 return NS_OK;
631 return CallQueryInterface(mMedia.get(), aMedia);
634 NS_IMETHODIMP
635 CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
637 NS_ENSURE_ARG_POINTER(aStyleSheet);
638 if (!mChildSheet) {
639 *aStyleSheet = nsnull;
640 return NS_OK;
643 return CallQueryInterface(mChildSheet, aStyleSheet);
646 nsCSSGroupRule::nsCSSGroupRule()
647 : nsCSSRule()
648 , mRuleCollection(nsnull)
652 static PRBool
653 CloneRuleInto(nsICSSRule* aRule, void* aArray)
655 nsICSSRule* clone = nsnull;
656 aRule->Clone(clone);
657 if (clone) {
658 static_cast<nsCOMArray<nsICSSRule>*>(aArray)->AppendObject(clone);
659 NS_RELEASE(clone);
661 return PR_TRUE;
664 static PRBool
665 SetParentRuleReference(nsICSSRule* aRule, void* aParentRule)
667 nsCSSGroupRule* parentRule = static_cast<nsCSSGroupRule*>(aParentRule);
668 aRule->SetParentRule(parentRule);
669 return PR_TRUE;
672 nsCSSGroupRule::nsCSSGroupRule(const nsCSSGroupRule& aCopy)
673 : nsCSSRule(aCopy)
674 , mRuleCollection(nsnull) // lazily constructed
676 const_cast<nsCSSGroupRule&>(aCopy).mRules.EnumerateForwards(CloneRuleInto, &mRules);
677 mRules.EnumerateForwards(SetParentRuleReference, this);
680 nsCSSGroupRule::~nsCSSGroupRule()
682 mRules.EnumerateForwards(SetParentRuleReference, nsnull);
683 if (mRuleCollection) {
684 mRuleCollection->DropReference();
685 NS_RELEASE(mRuleCollection);
689 IMPL_STYLE_RULE_INHERIT2(nsCSSGroupRule, nsCSSRule)
691 static PRBool
692 SetStyleSheetReference(nsICSSRule* aRule, void* aSheet)
694 nsICSSStyleSheet* sheet = (nsICSSStyleSheet*)aSheet;
695 aRule->SetStyleSheet(sheet);
696 return PR_TRUE;
699 NS_IMETHODIMP
700 nsCSSGroupRule::SetStyleSheet(nsICSSStyleSheet* aSheet)
702 mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
703 return nsCSSRule::SetStyleSheet(aSheet);
706 #ifdef DEBUG
707 NS_IMETHODIMP
708 nsCSSGroupRule::List(FILE* out, PRInt32 aIndent) const
710 fputs(" {\n", out);
712 for (PRInt32 index = 0, count = mRules.Count(); index < count; ++index) {
713 mRules.ObjectAt(index)->List(out, aIndent + 1);
715 fputs("}\n", out);
716 return NS_OK;
718 #endif
720 NS_IMETHODIMP
721 nsCSSGroupRule::AppendStyleRule(nsICSSRule* aRule)
723 mRules.AppendObject(aRule);
724 aRule->SetStyleSheet(mSheet);
725 aRule->SetParentRule(this);
726 if (mSheet) {
727 // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and
728 // shouldn't |SetModified| be removed?
729 mSheet->SetModified(PR_TRUE);
731 return NS_OK;
734 NS_IMETHODIMP
735 nsCSSGroupRule::StyleRuleCount(PRInt32& aCount) const
737 aCount = mRules.Count();
738 return NS_OK;
741 NS_IMETHODIMP
742 nsCSSGroupRule::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const
744 if (aIndex < 0 || aIndex >= mRules.Count()) {
745 aRule = nsnull;
746 return NS_ERROR_ILLEGAL_VALUE;
749 NS_ADDREF(aRule = mRules.ObjectAt(aIndex));
750 return NS_OK;
753 NS_IMETHODIMP_(PRBool)
754 nsCSSGroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
756 return
757 const_cast<nsCSSGroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
761 * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt)
762 * should never be called unless you have first called WillDirty() on
763 * the parents tylesheet. After they are called, DidDirty() needs to
764 * be called on the sheet
766 NS_IMETHODIMP
767 nsCSSGroupRule::DeleteStyleRuleAt(PRUint32 aIndex)
769 nsICSSRule* rule = mRules.SafeObjectAt(aIndex);
770 if (rule) {
771 rule->SetStyleSheet(nsnull);
772 rule->SetParentRule(nsnull);
774 return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
777 NS_IMETHODIMP
778 nsCSSGroupRule::InsertStyleRulesAt(PRUint32 aIndex,
779 nsCOMArray<nsICSSRule>& aRules)
781 aRules.EnumerateForwards(SetStyleSheetReference, mSheet);
782 aRules.EnumerateForwards(SetParentRuleReference, this);
783 if (! mRules.InsertObjectsAt(aRules, aIndex)) {
784 return NS_ERROR_FAILURE;
786 return NS_OK;
789 NS_IMETHODIMP
790 nsCSSGroupRule::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew)
792 PRInt32 index = mRules.IndexOf(aOld);
793 NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED);
794 mRules.ReplaceObjectAt(aNew, index);
795 aNew->SetStyleSheet(mSheet);
796 aNew->SetParentRule(this);
797 aOld->SetStyleSheet(nsnull);
798 aOld->SetParentRule(nsnull);
799 return NS_OK;
802 nsresult
803 nsCSSGroupRule::AppendRulesToCssText(nsAString& aCssText)
805 aCssText.AppendLiteral(" {\n");
807 // get all the rules
808 for (PRInt32 index = 0, count = mRules.Count(); index < count; ++index) {
809 nsICSSRule* rule = mRules.ObjectAt(index);
810 nsCOMPtr<nsIDOMCSSRule> domRule;
811 rule->GetDOMRule(getter_AddRefs(domRule));
812 if (domRule) {
813 nsAutoString cssText;
814 domRule->GetCssText(cssText);
815 aCssText.Append(NS_LITERAL_STRING(" ") +
816 cssText +
817 NS_LITERAL_STRING("\n"));
821 aCssText.AppendLiteral("}");
823 return NS_OK;
826 nsresult
827 nsCSSGroupRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
829 if (mSheet) {
830 return CallQueryInterface(mSheet, aSheet);
832 *aSheet = nsnull;
833 return NS_OK;
836 nsresult
837 nsCSSGroupRule::GetParentRule(nsIDOMCSSRule** aParentRule)
839 if (mParentRule) {
840 return mParentRule->GetDOMRule(aParentRule);
842 *aParentRule = nsnull;
843 return NS_OK;
846 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
847 nsresult
848 nsCSSGroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
850 if (!mRuleCollection) {
851 mRuleCollection = new CSSGroupRuleRuleListImpl(this);
852 if (!mRuleCollection) {
853 return NS_ERROR_OUT_OF_MEMORY;
855 NS_ADDREF(mRuleCollection);
858 return CallQueryInterface(mRuleCollection, aRuleList);
861 nsresult
862 nsCSSGroupRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
864 NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE);
866 if (aIndex > PRUint32(mRules.Count()))
867 return NS_ERROR_DOM_INDEX_SIZE_ERR;
869 NS_ASSERTION(PRUint32(mRules.Count()) <= PR_INT32_MAX,
870 "Too many style rules!");
872 return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
875 nsresult
876 nsCSSGroupRule::DeleteRule(PRUint32 aIndex)
878 NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE);
880 if (aIndex >= PRUint32(mRules.Count()))
881 return NS_ERROR_DOM_INDEX_SIZE_ERR;
883 NS_ASSERTION(PRUint32(mRules.Count()) <= PR_INT32_MAX,
884 "Too many style rules!");
886 return mSheet->DeleteRuleFromGroup(this, aIndex);
889 // -------------------------------------------
890 // nsICSSMediaRule
892 nsCSSMediaRule::nsCSSMediaRule()
896 nsCSSMediaRule::nsCSSMediaRule(const nsCSSMediaRule& aCopy)
897 : nsCSSGroupRule(aCopy)
899 if (aCopy.mMedia) {
900 aCopy.mMedia->Clone(getter_AddRefs(mMedia));
901 if (mMedia) {
902 // XXXldb This doesn't really make sense.
903 mMedia->SetStyleSheet(aCopy.mSheet);
908 nsCSSMediaRule::~nsCSSMediaRule()
910 if (mMedia) {
911 mMedia->SetStyleSheet(nsnull);
915 NS_IMPL_ADDREF_INHERITED(nsCSSMediaRule, nsCSSRule)
916 NS_IMPL_RELEASE_INHERITED(nsCSSMediaRule, nsCSSRule)
918 // QueryInterface implementation for nsCSSMediaRule
919 NS_INTERFACE_MAP_BEGIN(nsCSSMediaRule)
920 NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule)
921 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
922 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
923 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
924 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
925 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule)
926 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMediaRule)
927 NS_INTERFACE_MAP_END
929 NS_IMETHODIMP
930 nsCSSMediaRule::SetStyleSheet(nsICSSStyleSheet* aSheet)
932 if (mMedia) {
933 // Set to null so it knows it's leaving one sheet and joining another.
934 mMedia->SetStyleSheet(nsnull);
935 mMedia->SetStyleSheet(aSheet);
938 return nsCSSGroupRule::SetStyleSheet(aSheet);
941 #ifdef DEBUG
942 NS_IMETHODIMP
943 nsCSSMediaRule::List(FILE* out, PRInt32 aIndent) const
945 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
947 nsAutoString buffer;
949 fputs("@media ", out);
951 if (mMedia) {
952 nsAutoString mediaText;
953 mMedia->GetText(mediaText);
954 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
957 return nsCSSGroupRule::List(out, aIndent);
959 #endif
961 NS_IMETHODIMP
962 nsCSSMediaRule::GetType(PRInt32& aType) const
964 aType = nsICSSRule::MEDIA_RULE;
965 return NS_OK;
968 NS_IMETHODIMP
969 nsCSSMediaRule::Clone(nsICSSRule*& aClone) const
971 nsCSSMediaRule* clone = new nsCSSMediaRule(*this);
972 if (clone) {
973 return CallQueryInterface(clone, &aClone);
975 aClone = nsnull;
976 return NS_ERROR_OUT_OF_MEMORY;
979 nsresult
980 nsCSSMediaRule::SetMedia(nsMediaList* aMedia)
982 mMedia = aMedia;
983 if (aMedia)
984 mMedia->SetStyleSheet(mSheet);
985 return NS_OK;
988 // nsIDOMCSSRule methods
989 NS_IMETHODIMP
990 nsCSSMediaRule::GetType(PRUint16* aType)
992 *aType = nsIDOMCSSRule::MEDIA_RULE;
993 return NS_OK;
996 NS_IMETHODIMP
997 nsCSSMediaRule::GetCssText(nsAString& aCssText)
999 aCssText.AssignLiteral("@media ");
1000 // get all the media
1001 if (mMedia) {
1002 nsAutoString mediaText;
1003 mMedia->GetText(mediaText);
1004 aCssText.Append(mediaText);
1007 return nsCSSGroupRule::AppendRulesToCssText(aCssText);
1010 NS_IMETHODIMP
1011 nsCSSMediaRule::SetCssText(const nsAString& aCssText)
1013 return NS_ERROR_NOT_IMPLEMENTED;
1016 NS_IMETHODIMP
1017 nsCSSMediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1019 return nsCSSGroupRule::GetParentStyleSheet(aSheet);
1022 NS_IMETHODIMP
1023 nsCSSMediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1025 return nsCSSGroupRule::GetParentRule(aParentRule);
1028 // nsIDOMCSSMediaRule methods
1029 NS_IMETHODIMP
1030 nsCSSMediaRule::GetMedia(nsIDOMMediaList* *aMedia)
1032 NS_ENSURE_ARG_POINTER(aMedia);
1033 if (!mMedia) {
1034 *aMedia = nsnull;
1035 return NS_OK;
1038 return CallQueryInterface(mMedia.get(), aMedia);
1041 NS_IMETHODIMP
1042 nsCSSMediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1044 return nsCSSGroupRule::GetCssRules(aRuleList);
1047 NS_IMETHODIMP
1048 nsCSSMediaRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
1050 return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval);
1053 NS_IMETHODIMP
1054 nsCSSMediaRule::DeleteRule(PRUint32 aIndex)
1056 return nsCSSGroupRule::DeleteRule(aIndex);
1059 // nsICSSGroupRule interface
1060 NS_IMETHODIMP_(PRBool)
1061 nsCSSMediaRule::UseForPresentation(nsPresContext* aPresContext,
1062 nsMediaQueryResultCacheKey& aKey)
1064 if (mMedia) {
1065 return mMedia->Matches(aPresContext, aKey);
1067 return PR_TRUE;
1071 nsCSSDocumentRule::nsCSSDocumentRule(void)
1075 nsCSSDocumentRule::nsCSSDocumentRule(const nsCSSDocumentRule& aCopy)
1076 : nsCSSGroupRule(aCopy)
1077 , mURLs(new URL(*aCopy.mURLs))
1081 nsCSSDocumentRule::~nsCSSDocumentRule(void)
1085 NS_IMPL_ADDREF_INHERITED(nsCSSDocumentRule, nsCSSRule)
1086 NS_IMPL_RELEASE_INHERITED(nsCSSDocumentRule, nsCSSRule)
1088 // QueryInterface implementation for nsCSSDocumentRule
1089 NS_INTERFACE_MAP_BEGIN(nsCSSDocumentRule)
1090 NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule)
1091 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1092 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1093 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1094 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
1095 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule)
1096 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMozDocumentRule)
1097 NS_INTERFACE_MAP_END
1099 #ifdef DEBUG
1100 NS_IMETHODIMP
1101 nsCSSDocumentRule::List(FILE* out, PRInt32 aIndent) const
1103 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
1105 nsCAutoString str;
1106 str.AssignLiteral("@-moz-document ");
1107 for (URL *url = mURLs; url; url = url->next) {
1108 switch (url->func) {
1109 case eURL:
1110 str.AppendLiteral("url(\"");
1111 break;
1112 case eURLPrefix:
1113 str.AppendLiteral("url-prefix(\"");
1114 break;
1115 case eDomain:
1116 str.AppendLiteral("domain(\"");
1117 break;
1119 nsCAutoString escapedURL(url->url);
1120 escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
1121 str.Append(escapedURL);
1122 str.AppendLiteral("\"), ");
1124 str.Cut(str.Length() - 2, 1); // remove last ,
1125 fputs(str.get(), out);
1127 return nsCSSGroupRule::List(out, aIndent);
1129 #endif
1131 NS_IMETHODIMP
1132 nsCSSDocumentRule::GetType(PRInt32& aType) const
1134 aType = nsICSSRule::DOCUMENT_RULE;
1135 return NS_OK;
1138 NS_IMETHODIMP
1139 nsCSSDocumentRule::Clone(nsICSSRule*& aClone) const
1141 nsCSSDocumentRule* clone = new nsCSSDocumentRule(*this);
1142 if (clone) {
1143 return CallQueryInterface(clone, &aClone);
1145 aClone = nsnull;
1146 return NS_ERROR_OUT_OF_MEMORY;
1149 // nsIDOMCSSRule methods
1150 NS_IMETHODIMP
1151 nsCSSDocumentRule::GetType(PRUint16* aType)
1153 // XXX What should really happen here?
1154 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1155 return NS_OK;
1158 NS_IMETHODIMP
1159 nsCSSDocumentRule::GetCssText(nsAString& aCssText)
1161 aCssText.AssignLiteral("@-moz-document ");
1162 for (URL *url = mURLs; url; url = url->next) {
1163 switch (url->func) {
1164 case eURL:
1165 aCssText.AppendLiteral("url(\"");
1166 break;
1167 case eURLPrefix:
1168 aCssText.AppendLiteral("url-prefix(\"");
1169 break;
1170 case eDomain:
1171 aCssText.AppendLiteral("domain(\"");
1172 break;
1174 nsCAutoString escapedURL(url->url);
1175 escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
1176 AppendUTF8toUTF16(escapedURL, aCssText);
1177 aCssText.AppendLiteral("\"), ");
1179 aCssText.Cut(aCssText.Length() - 2, 1); // remove last ,
1181 return nsCSSGroupRule::AppendRulesToCssText(aCssText);
1184 NS_IMETHODIMP
1185 nsCSSDocumentRule::SetCssText(const nsAString& aCssText)
1187 return NS_ERROR_NOT_IMPLEMENTED;
1190 NS_IMETHODIMP
1191 nsCSSDocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1193 return nsCSSGroupRule::GetParentStyleSheet(aSheet);
1196 NS_IMETHODIMP
1197 nsCSSDocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1199 return nsCSSGroupRule::GetParentRule(aParentRule);
1202 NS_IMETHODIMP
1203 nsCSSDocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1205 return nsCSSGroupRule::GetCssRules(aRuleList);
1208 NS_IMETHODIMP
1209 nsCSSDocumentRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
1211 return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval);
1214 NS_IMETHODIMP
1215 nsCSSDocumentRule::DeleteRule(PRUint32 aIndex)
1217 return nsCSSGroupRule::DeleteRule(aIndex);
1220 // nsICSSGroupRule interface
1221 NS_IMETHODIMP_(PRBool)
1222 nsCSSDocumentRule::UseForPresentation(nsPresContext* aPresContext,
1223 nsMediaQueryResultCacheKey& aKey)
1225 nsIURI *docURI = aPresContext->Document()->GetDocumentURI();
1226 nsCAutoString docURISpec;
1227 if (docURI)
1228 docURI->GetSpec(docURISpec);
1230 for (URL *url = mURLs; url; url = url->next) {
1231 switch (url->func) {
1232 case eURL: {
1233 if (docURISpec == url->url)
1234 return PR_TRUE;
1235 } break;
1236 case eURLPrefix: {
1237 if (StringBeginsWith(docURISpec, url->url))
1238 return PR_TRUE;
1239 } break;
1240 case eDomain: {
1241 nsCAutoString host;
1242 if (docURI)
1243 docURI->GetHost(host);
1244 PRInt32 lenDiff = host.Length() - url->url.Length();
1245 if (lenDiff == 0) {
1246 if (host == url->url)
1247 return PR_TRUE;
1248 } else {
1249 if (StringEndsWith(host, url->url) &&
1250 host.CharAt(lenDiff - 1) == '.')
1251 return PR_TRUE;
1253 } break;
1257 return PR_FALSE;
1261 // -------------------------------------------
1262 // nsICSSNameSpaceRule
1264 class CSSNameSpaceRuleImpl : public nsCSSRule,
1265 public nsICSSNameSpaceRule,
1266 public nsIDOMCSSRule
1268 public:
1269 CSSNameSpaceRuleImpl(void);
1270 CSSNameSpaceRuleImpl(const CSSNameSpaceRuleImpl& aCopy);
1271 virtual ~CSSNameSpaceRuleImpl(void);
1273 NS_DECL_ISUPPORTS_INHERITED
1275 DECL_STYLE_RULE_INHERIT
1277 // nsIStyleRule methods
1278 #ifdef DEBUG
1279 NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
1280 #endif
1282 // nsICSSRule methods
1283 NS_IMETHOD GetType(PRInt32& aType) const;
1284 NS_IMETHOD Clone(nsICSSRule*& aClone) const;
1286 // nsICSSNameSpaceRule methods
1287 NS_IMETHOD GetPrefix(nsIAtom*& aPrefix) const;
1288 NS_IMETHOD SetPrefix(nsIAtom* aPrefix);
1290 NS_IMETHOD GetURLSpec(nsString& aURLSpec) const;
1291 NS_IMETHOD SetURLSpec(const nsString& aURLSpec);
1293 // nsIDOMCSSRule interface
1294 NS_DECL_NSIDOMCSSRULE
1296 protected:
1297 nsIAtom* mPrefix;
1298 nsString mURLSpec;
1301 CSSNameSpaceRuleImpl::CSSNameSpaceRuleImpl(void)
1302 : nsCSSRule(),
1303 mPrefix(nsnull),
1304 mURLSpec()
1308 CSSNameSpaceRuleImpl::CSSNameSpaceRuleImpl(const CSSNameSpaceRuleImpl& aCopy)
1309 : nsCSSRule(aCopy),
1310 mPrefix(aCopy.mPrefix),
1311 mURLSpec(aCopy.mURLSpec)
1313 NS_IF_ADDREF(mPrefix);
1316 CSSNameSpaceRuleImpl::~CSSNameSpaceRuleImpl(void)
1318 NS_IF_RELEASE(mPrefix);
1321 NS_IMPL_ADDREF_INHERITED(CSSNameSpaceRuleImpl, nsCSSRule)
1322 NS_IMPL_RELEASE_INHERITED(CSSNameSpaceRuleImpl, nsCSSRule)
1324 // QueryInterface implementation for CSSNameSpaceRuleImpl
1325 NS_INTERFACE_MAP_BEGIN(CSSNameSpaceRuleImpl)
1326 NS_INTERFACE_MAP_ENTRY(nsICSSNameSpaceRule)
1327 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1328 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1329 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1330 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSNameSpaceRule)
1331 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSNameSpaceRule)
1332 NS_INTERFACE_MAP_END
1334 IMPL_STYLE_RULE_INHERIT(CSSNameSpaceRuleImpl, nsCSSRule)
1336 #ifdef DEBUG
1337 NS_IMETHODIMP
1338 CSSNameSpaceRuleImpl::List(FILE* out, PRInt32 aIndent) const
1340 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
1342 nsAutoString buffer;
1344 fputs("@namespace ", out);
1346 if (mPrefix) {
1347 mPrefix->ToString(buffer);
1348 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
1349 fputs(" ", out);
1352 fputs("url(", out);
1353 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
1354 fputs(")\n", out);
1355 return NS_OK;
1357 #endif
1359 NS_IMETHODIMP
1360 CSSNameSpaceRuleImpl::GetType(PRInt32& aType) const
1362 aType = nsICSSRule::NAMESPACE_RULE;
1363 return NS_OK;
1366 NS_IMETHODIMP
1367 CSSNameSpaceRuleImpl::Clone(nsICSSRule*& aClone) const
1369 CSSNameSpaceRuleImpl* clone = new CSSNameSpaceRuleImpl(*this);
1370 if (clone) {
1371 return CallQueryInterface(clone, &aClone);
1373 aClone = nsnull;
1374 return NS_ERROR_OUT_OF_MEMORY;
1377 NS_IMETHODIMP
1378 CSSNameSpaceRuleImpl::GetPrefix(nsIAtom*& aPrefix) const
1380 aPrefix = mPrefix;
1381 NS_IF_ADDREF(aPrefix);
1382 return NS_OK;
1385 NS_IMETHODIMP
1386 CSSNameSpaceRuleImpl::SetPrefix(nsIAtom* aPrefix)
1388 NS_IF_RELEASE(mPrefix);
1389 mPrefix = aPrefix;
1390 NS_IF_ADDREF(mPrefix);
1391 return NS_OK;
1394 NS_IMETHODIMP
1395 CSSNameSpaceRuleImpl::GetURLSpec(nsString& aURLSpec) const
1397 aURLSpec = mURLSpec;
1398 return NS_OK;
1401 NS_IMETHODIMP
1402 CSSNameSpaceRuleImpl::SetURLSpec(const nsString& aURLSpec)
1404 mURLSpec = aURLSpec;
1405 return NS_OK;
1408 nsresult
1409 NS_NewCSSNameSpaceRule(nsICSSNameSpaceRule** aInstancePtrResult,
1410 nsIAtom* aPrefix, const nsString& aURLSpec)
1412 if (! aInstancePtrResult) {
1413 return NS_ERROR_NULL_POINTER;
1416 CSSNameSpaceRuleImpl* it = new CSSNameSpaceRuleImpl();
1418 if (! it) {
1419 return NS_ERROR_OUT_OF_MEMORY;
1422 it->SetPrefix(aPrefix);
1423 it->SetURLSpec(aURLSpec);
1424 return CallQueryInterface(it, aInstancePtrResult);
1427 NS_IMETHODIMP
1428 CSSNameSpaceRuleImpl::GetType(PRUint16* aType)
1430 // XXX What should really happen here?
1431 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1432 return NS_OK;
1435 NS_IMETHODIMP
1436 CSSNameSpaceRuleImpl::GetCssText(nsAString& aCssText)
1438 aCssText.AssignLiteral("@namespace ");
1439 if (mPrefix) {
1440 nsString atomStr;
1441 mPrefix->ToString(atomStr);
1442 aCssText.Append(atomStr);
1443 aCssText.AppendLiteral(" ");
1445 aCssText.AppendLiteral("url(");
1446 aCssText.Append(mURLSpec);
1447 aCssText.Append(NS_LITERAL_STRING(");"));
1448 return NS_OK;
1451 NS_IMETHODIMP
1452 CSSNameSpaceRuleImpl::SetCssText(const nsAString& aCssText)
1454 return NS_ERROR_NOT_IMPLEMENTED;
1457 NS_IMETHODIMP
1458 CSSNameSpaceRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1460 if (mSheet) {
1461 return CallQueryInterface(mSheet, aSheet);
1463 *aSheet = nsnull;
1464 return NS_OK;
1467 NS_IMETHODIMP
1468 CSSNameSpaceRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
1470 if (mParentRule) {
1471 return mParentRule->GetDOMRule(aParentRule);
1473 *aParentRule = nsnull;
1474 return NS_OK;
1477 // -------------------------------------------
1478 // nsCSSFontFaceStyleDecl and related routines
1481 // A src: descriptor is represented as an array value; each entry in
1482 // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
1483 // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear
1484 // only after one of the first two. (css3-fonts only contemplates
1485 // annotating URLs with formats, but we handle the general case.)
1486 static void
1487 SerializeFontSrc(const nsCSSValue& src, nsAString & aResult NS_OUTPARAM)
1489 NS_PRECONDITION(src.GetUnit() == eCSSUnit_Null ||
1490 src.GetUnit() == eCSSUnit_Array,
1491 "improper value unit for src:");
1492 aResult.Truncate();
1493 if (src.GetUnit() != eCSSUnit_Array)
1494 return;
1496 const nsCSSValue::Array& sources = *src.GetArrayValue();
1497 PRUint32 i = 0;
1499 while (i < sources.Count()) {
1500 nsAutoString formats;
1502 if (sources[i].GetUnit() == eCSSUnit_URL) {
1503 nsDependentString url(sources[i].GetOriginalURLValue());
1504 nsAutoString escapedUrl;
1505 nsStyleUtil::EscapeCSSString(url, escapedUrl);
1506 aResult.AppendLiteral("url(\"");
1507 aResult.Append(escapedUrl);
1508 aResult.AppendLiteral("\")");
1509 } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
1510 nsDependentString local(sources[i].GetStringBufferValue());
1511 nsAutoString escapedLocal;
1512 nsStyleUtil::EscapeCSSString(local, escapedLocal);
1513 aResult.AppendLiteral("local(\"");
1514 aResult.Append(escapedLocal);
1515 aResult.AppendLiteral("\")");
1516 } else {
1517 NS_NOTREACHED("entry in src: descriptor with improper unit");
1518 i++;
1519 continue;
1522 i++;
1523 formats.Truncate();
1524 while (i < sources.Count() &&
1525 sources[i].GetUnit() == eCSSUnit_Font_Format) {
1526 formats.Append('"');
1527 formats.Append(sources[i].GetStringBufferValue());
1528 formats.AppendLiteral("\", ");
1529 i++;
1531 if (formats.Length() > 0) {
1532 formats.Truncate(formats.Length() - 2); // remove the last comma
1533 aResult.AppendLiteral(" format(");
1534 aResult.Append(formats);
1535 aResult.Append(')');
1537 aResult.AppendLiteral(", ");
1539 aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
1542 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
1543 // Keep this in sync with enum nsCSSFontDesc in nsCSSProperty.h.
1544 nsCSSValue nsCSSFontFaceStyleDecl::* const
1545 nsCSSFontFaceStyleDecl::Fields[] = {
1546 &nsCSSFontFaceStyleDecl::mFamily,
1547 &nsCSSFontFaceStyleDecl::mStyle,
1548 &nsCSSFontFaceStyleDecl::mWeight,
1549 &nsCSSFontFaceStyleDecl::mStretch,
1550 &nsCSSFontFaceStyleDecl::mSrc,
1551 &nsCSSFontFaceStyleDecl::mUnicodeRange
1554 // QueryInterface implementation for nsCSSFontFaceStyleDecl
1555 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
1556 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
1557 NS_INTERFACE_MAP_ENTRY(nsISupports)
1558 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSFontFaceStyleDecl)
1559 NS_INTERFACE_MAP_END
1561 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1562 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1564 // helper for string GetPropertyValue and RemovePropertyValue
1565 nsresult
1566 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
1567 nsAString & aResult NS_OUTPARAM) const
1569 NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
1570 eCSSFontDesc_COUNT - 1);
1572 aResult.Truncate();
1573 if (aFontDescID == eCSSFontDesc_UNKNOWN)
1574 return NS_OK;
1576 const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID];
1578 switch (aFontDescID) {
1579 case eCSSFontDesc_Family: {
1580 // we don't use AppendCSSValueToString here because it doesn't
1581 // canonicalize the way we want, and anyway it's overkill when
1582 // we know we have eCSSUnit_String
1583 nsDependentString family(val.GetStringBufferValue());
1584 nsAutoString escapedFamily;
1585 nsStyleUtil::EscapeCSSString(family, escapedFamily);
1586 aResult.Append('"');
1587 aResult.Append(escapedFamily);
1588 aResult.Append('"');
1589 return NS_OK;
1592 case eCSSFontDesc_Style:
1593 nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_font_style, val,
1594 aResult);
1595 return NS_OK;
1597 case eCSSFontDesc_Weight:
1598 nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_font_weight, val,
1599 aResult);
1600 return NS_OK;
1602 case eCSSFontDesc_Stretch:
1603 nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_font_stretch, val,
1604 aResult);
1605 return NS_OK;
1607 case eCSSFontDesc_Src:
1608 SerializeFontSrc(val, aResult);
1609 return NS_OK;
1611 case eCSSFontDesc_UnicodeRange:
1612 // these are not implemented, so always return an empty string
1613 return NS_OK;
1615 case eCSSFontDesc_UNKNOWN:
1616 case eCSSFontDesc_COUNT:
1619 NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
1620 "out-of-range value got to the switch");
1621 return NS_ERROR_INVALID_ARG;
1625 // attribute DOMString cssText;
1626 NS_IMETHODIMP
1627 nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
1629 nsAutoString descStr;
1631 aCssText.Truncate();
1632 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1633 id < eCSSFontDesc_COUNT;
1634 id = nsCSSFontDesc(id + 1)) {
1635 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1636 != eCSSUnit_Null &&
1637 NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
1638 NS_ASSERTION(descStr.Length() > 0,
1639 "GetCssText: non-null unit, empty property value");
1640 aCssText.AppendLiteral(" ");
1641 aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
1642 aCssText.AppendLiteral(": ");
1643 aCssText.Append(descStr);
1644 aCssText.AppendLiteral(";\n");
1647 return NS_OK;
1650 NS_IMETHODIMP
1651 nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
1653 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1656 // DOMString getPropertyValue (in DOMString propertyName);
1657 NS_IMETHODIMP
1658 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
1659 nsAString & aResult NS_OUTPARAM)
1661 return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
1664 // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
1665 NS_IMETHODIMP
1666 nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
1667 nsIDOMCSSValue **aResult NS_OUTPARAM)
1669 // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
1670 return NS_ERROR_NOT_IMPLEMENTED;
1673 // DOMString removeProperty (in DOMString propertyName) raises (DOMException);
1674 NS_IMETHODIMP
1675 nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
1676 nsAString & aResult NS_OUTPARAM)
1678 nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
1679 NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
1680 descID < eCSSFontDesc_COUNT,
1681 "LookupFontDesc returned value out of range");
1683 if (descID == eCSSFontDesc_UNKNOWN) {
1684 aResult.Truncate();
1685 } else {
1686 nsresult rv = GetPropertyValue(descID, aResult);
1687 NS_ENSURE_SUCCESS(rv, rv);
1688 (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset();
1690 return NS_OK;
1693 // DOMString getPropertyPriority (in DOMString propertyName);
1694 NS_IMETHODIMP
1695 nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
1696 nsAString & aResult NS_OUTPARAM)
1698 // font descriptors do not have priorities at present
1699 aResult.Truncate();
1700 return NS_OK;
1703 // void setProperty (in DOMString propertyName, in DOMString value,
1704 // in DOMString priority) raises (DOMException);
1705 NS_IMETHODIMP
1706 nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
1707 const nsAString & value,
1708 const nsAString & priority)
1710 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1713 // readonly attribute unsigned long length;
1714 NS_IMETHODIMP
1715 nsCSSFontFaceStyleDecl::GetLength(PRUint32 *aLength)
1717 PRUint32 len = 0;
1718 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1719 id < eCSSFontDesc_COUNT;
1720 id = nsCSSFontDesc(id + 1))
1721 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null)
1722 len++;
1724 *aLength = len;
1725 return NS_OK;
1728 // DOMString item (in unsigned long index);
1729 NS_IMETHODIMP
1730 nsCSSFontFaceStyleDecl::Item(PRUint32 index, nsAString & aResult NS_OUTPARAM)
1732 PRInt32 nset = -1;
1733 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1734 id < eCSSFontDesc_COUNT;
1735 id = nsCSSFontDesc(id + 1)) {
1736 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1737 != eCSSUnit_Null) {
1738 nset++;
1739 if (nset == PRInt32(index)) {
1740 aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
1741 return NS_OK;
1745 aResult.Truncate();
1746 return NS_OK;
1749 // readonly attribute nsIDOMCSSRule parentRule;
1750 NS_IMETHODIMP
1751 nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
1753 return ContainingRule()->GetDOMRule(aParentRule);
1757 // -------------------------------------------
1758 // nsCSSFontFaceRule
1761 NS_IMETHODIMP
1762 nsCSSFontFaceRule::Clone(nsICSSRule*& aClone) const
1764 nsCSSFontFaceRule* clone = new nsCSSFontFaceRule(*this);
1765 if (clone) {
1766 return CallQueryInterface(clone, &aClone);
1768 aClone = nsnull;
1769 return NS_ERROR_OUT_OF_MEMORY;
1772 NS_IMPL_ADDREF_INHERITED(nsCSSFontFaceRule, nsCSSRule)
1773 NS_IMPL_RELEASE_INHERITED(nsCSSFontFaceRule, nsCSSRule)
1775 // QueryInterface implementation for nsCSSFontFaceRule
1776 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceRule)
1777 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1778 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1779 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
1780 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1781 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule)
1782 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSFontFaceRule)
1783 NS_INTERFACE_MAP_END
1785 IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, nsCSSRule)
1787 #ifdef DEBUG
1788 NS_IMETHODIMP
1789 nsCSSFontFaceRule::List(FILE* out, PRInt32 aIndent) const
1791 nsCString baseInd, descInd;
1792 for (PRInt32 indent = aIndent; --indent >= 0; ) {
1793 baseInd.AppendLiteral(" ");
1794 descInd.AppendLiteral(" ");
1796 descInd.AppendLiteral(" ");
1798 nsString descStr;
1800 fprintf(out, "%s@font-face {\n", baseInd.get());
1801 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1802 id < eCSSFontDesc_COUNT;
1803 id = nsCSSFontDesc(id + 1))
1804 if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1805 != eCSSUnit_Null) {
1806 if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
1807 descStr.AssignLiteral("#<serialization error>");
1808 else if (descStr.Length() == 0)
1809 descStr.AssignLiteral("#<serialization missing>");
1810 fprintf(out, "%s%s: %s\n",
1811 descInd.get(), nsCSSProps::GetStringValue(id).get(),
1812 NS_ConvertUTF16toUTF8(descStr).get());
1814 fprintf(out, "%s}\n", baseInd.get());
1815 return NS_OK;
1817 #endif
1819 NS_IMETHODIMP
1820 nsCSSFontFaceRule::GetType(PRInt32& aType) const
1822 aType = nsICSSRule::FONT_FACE_RULE;
1823 return NS_OK;
1826 NS_IMETHODIMP
1827 nsCSSFontFaceRule::GetType(PRUint16* aType)
1829 *aType = nsIDOMCSSRule::FONT_FACE_RULE;
1830 return NS_OK;
1833 NS_IMETHODIMP
1834 nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
1836 nsAutoString propText;
1837 mDecl.GetCssText(propText);
1839 aCssText.AssignLiteral("@font-face {\n");
1840 aCssText.Append(propText);
1841 aCssText.Append('}');
1842 return NS_OK;
1845 NS_IMETHODIMP
1846 nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
1848 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1851 NS_IMETHODIMP
1852 nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1854 if (mSheet) {
1855 return CallQueryInterface(mSheet, aSheet);
1857 *aSheet = nsnull;
1858 return NS_OK;
1861 NS_IMETHODIMP
1862 nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1864 if (mParentRule) {
1865 return mParentRule->GetDOMRule(aParentRule);
1867 *aParentRule = nsnull;
1868 return NS_OK;
1871 NS_IMETHODIMP
1872 nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1874 return CallQueryInterface(&mDecl, aStyle);
1877 // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
1878 void
1879 nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
1881 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1882 aDescID < eCSSFontDesc_COUNT,
1883 "aDescID out of range in nsCSSFontFaceRule::SetDesc");
1885 mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue;
1888 void
1889 nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
1891 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1892 aDescID < eCSSFontDesc_COUNT,
1893 "aDescID out of range in nsCSSFontFaceRule::GetDesc");
1895 aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];