Bug 867089 - Validate the playbackRate before using it. r=ehsan
[gecko.git] / layout / style / nsCSSRules.cpp
bloba9d4d7094d37f74001879165b323aeac46ed6fef
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
8 #include "mozilla/Attributes.h"
10 #include "nsCSSRules.h"
11 #include "nsCSSValue.h"
12 #include "mozilla/css/ImportRule.h"
13 #include "mozilla/css/NameSpaceRule.h"
15 #include "nsString.h"
16 #include "nsIAtom.h"
18 #include "nsCSSProps.h"
19 #include "nsCSSStyleSheet.h"
21 #include "nsCOMPtr.h"
22 #include "nsIDOMCSSStyleSheet.h"
23 #include "nsIMediaList.h"
24 #include "nsICSSRuleList.h"
25 #include "nsIDocument.h"
26 #include "nsPresContext.h"
28 #include "nsContentUtils.h"
29 #include "nsError.h"
30 #include "nsStyleUtil.h"
31 #include "mozilla/css/Declaration.h"
32 #include "nsCSSParser.h"
33 #include "nsPrintfCString.h"
34 #include "nsDOMClassInfoID.h"
35 #include "mozilla/dom/CSSStyleDeclarationBinding.h"
36 #include "StyleRule.h"
38 using namespace mozilla;
40 #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
41 /* virtual */ nsIDOMCSSRule* class_::GetDOMRule() \
42 { return this; } \
43 /* virtual */ nsIDOMCSSRule* class_::GetExistingDOMRule() \
44 { return this; }
45 #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \
46 /* virtual */ void class_::MapRuleInfoInto(nsRuleData* aRuleData) \
47 { NS_ABORT_IF_FALSE(false, "should not be called"); }
49 #define IMPL_STYLE_RULE_INHERIT(class_, super_) \
50 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
51 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_)
53 // base class for all rule types in a CSS style sheet
55 namespace mozilla {
56 namespace css {
58 nsCSSStyleSheet*
59 Rule::GetStyleSheet() const
61 if (!(mSheet & 0x1)) {
62 return reinterpret_cast<nsCSSStyleSheet*>(mSheet);
65 return nullptr;
68 nsHTMLCSSStyleSheet*
69 Rule::GetHTMLCSSStyleSheet() const
71 if (mSheet & 0x1) {
72 return reinterpret_cast<nsHTMLCSSStyleSheet*>(mSheet & ~uintptr_t(0x1));
75 return nullptr;
78 /* virtual */ void
79 Rule::SetStyleSheet(nsCSSStyleSheet* aSheet)
81 // We don't reference count this up reference. The style sheet
82 // will tell us when it's going away or when we're detached from
83 // it.
84 mSheet = reinterpret_cast<uintptr_t>(aSheet);
87 void
88 Rule::SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet)
90 // We don't reference count this up reference. The style sheet
91 // will tell us when it's going away or when we're detached from
92 // it.
93 mSheet = reinterpret_cast<uintptr_t>(aSheet);
94 mSheet |= 0x1;
97 nsresult
98 Rule::GetParentRule(nsIDOMCSSRule** aParentRule)
100 if (mParentRule) {
101 NS_IF_ADDREF(*aParentRule = mParentRule->GetDOMRule());
102 } else {
103 *aParentRule = nullptr;
105 return NS_OK;
108 nsresult
109 Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
111 NS_ENSURE_ARG_POINTER(aSheet);
113 NS_IF_ADDREF(*aSheet = GetStyleSheet());
114 return NS_OK;
117 size_t
118 Rule::SizeOfCOMArrayElementIncludingThis(css::Rule* aElement,
119 nsMallocSizeOfFun aMallocSizeOf,
120 void* aData)
122 return aElement->SizeOfIncludingThis(aMallocSizeOf);
125 // -------------------------------
126 // Style Rule List for group rules
129 class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
131 public:
132 GroupRuleRuleList(GroupRule *aGroupRule);
134 NS_DECL_ISUPPORTS
136 NS_DECL_NSIDOMCSSRULELIST
138 virtual nsIDOMCSSRule* GetItemAt(uint32_t aIndex, nsresult* aResult);
140 void DropReference() { mGroupRule = nullptr; }
142 private:
143 ~GroupRuleRuleList();
145 private:
146 GroupRule* mGroupRule;
149 GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule)
151 // Not reference counted to avoid circular references.
152 // The rule will tell us when its going away.
153 mGroupRule = aGroupRule;
156 GroupRuleRuleList::~GroupRuleRuleList()
160 // QueryInterface implementation for CSSGroupRuleRuleList
161 NS_INTERFACE_MAP_BEGIN(GroupRuleRuleList)
162 NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
163 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
164 NS_INTERFACE_MAP_ENTRY(nsISupports)
165 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSGroupRuleRuleList)
166 NS_INTERFACE_MAP_END
169 NS_IMPL_ADDREF(GroupRuleRuleList)
170 NS_IMPL_RELEASE(GroupRuleRuleList)
172 NS_IMETHODIMP
173 GroupRuleRuleList::GetLength(uint32_t* aLength)
175 if (mGroupRule) {
176 *aLength = (uint32_t)mGroupRule->StyleRuleCount();
177 } else {
178 *aLength = 0;
181 return NS_OK;
184 nsIDOMCSSRule*
185 GroupRuleRuleList::GetItemAt(uint32_t aIndex, nsresult* aResult)
187 *aResult = NS_OK;
189 if (mGroupRule) {
190 nsRefPtr<Rule> rule = mGroupRule->GetStyleRuleAt(aIndex);
191 if (rule) {
192 return rule->GetDOMRule();
196 return nullptr;
199 NS_IMETHODIMP
200 GroupRuleRuleList::Item(uint32_t aIndex, nsIDOMCSSRule** aReturn)
202 nsresult rv;
203 nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
204 if (!rule) {
205 *aReturn = nullptr;
206 return rv;
209 NS_ADDREF(*aReturn = rule);
210 return NS_OK;
213 } // namespace css
214 } // namespace mozilla
216 // Must be outside the namespace
217 DOMCI_DATA(CSSGroupRuleRuleList, css::GroupRuleRuleList)
219 // -------------------------------------------
220 // CharsetRule
223 // Must be outside namespace
224 DOMCI_DATA(CSSCharsetRule, css::CharsetRule)
226 namespace mozilla {
227 namespace css {
229 CharsetRule::CharsetRule(const nsAString& aEncoding)
230 : Rule(),
231 mEncoding(aEncoding)
235 CharsetRule::CharsetRule(const CharsetRule& aCopy)
236 : Rule(aCopy),
237 mEncoding(aCopy.mEncoding)
241 NS_IMPL_ADDREF(CharsetRule)
242 NS_IMPL_RELEASE(CharsetRule)
244 // QueryInterface implementation for CharsetRule
245 NS_INTERFACE_MAP_BEGIN(CharsetRule)
246 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
247 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
248 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule)
249 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
250 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCharsetRule)
251 NS_INTERFACE_MAP_END
253 IMPL_STYLE_RULE_INHERIT(CharsetRule, Rule)
255 #ifdef DEBUG
256 /* virtual */ void
257 CharsetRule::List(FILE* out, int32_t aIndent) const
259 // Indent
260 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
262 fputs("@charset \"", out);
263 fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out);
264 fputs("\"\n", out);
266 #endif
268 /* virtual */ int32_t
269 CharsetRule::GetType() const
271 return Rule::CHARSET_RULE;
274 /* virtual */ already_AddRefed<Rule>
275 CharsetRule::Clone() const
277 nsRefPtr<Rule> clone = new CharsetRule(*this);
278 return clone.forget();
281 NS_IMETHODIMP
282 CharsetRule::GetEncoding(nsAString& aEncoding)
284 aEncoding = mEncoding;
285 return NS_OK;
288 NS_IMETHODIMP
289 CharsetRule::SetEncoding(const nsAString& aEncoding)
291 mEncoding = aEncoding;
292 return NS_OK;
295 NS_IMETHODIMP
296 CharsetRule::GetType(uint16_t* aType)
298 *aType = nsIDOMCSSRule::CHARSET_RULE;
299 return NS_OK;
302 NS_IMETHODIMP
303 CharsetRule::GetCssText(nsAString& aCssText)
305 aCssText.AssignLiteral("@charset \"");
306 aCssText.Append(mEncoding);
307 aCssText.AppendLiteral("\";");
308 return NS_OK;
311 NS_IMETHODIMP
312 CharsetRule::SetCssText(const nsAString& aCssText)
314 return NS_ERROR_NOT_IMPLEMENTED;
317 NS_IMETHODIMP
318 CharsetRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
320 return Rule::GetParentStyleSheet(aSheet);
323 NS_IMETHODIMP
324 CharsetRule::GetParentRule(nsIDOMCSSRule** aParentRule)
326 return Rule::GetParentRule(aParentRule);
329 /* virtual */ size_t
330 CharsetRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
332 return aMallocSizeOf(this);
334 // Measurement of the following members may be added later if DMD finds it is
335 // worthwhile:
336 // - mEncoding
339 // -------------------------------------------
340 // ImportRule
343 ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec)
344 : Rule()
345 , mURLSpec(aURLSpec)
346 , mMedia(aMedia)
348 // XXXbz This is really silly.... the mMedia here will be replaced
349 // with itself if we manage to load a sheet. Which should really
350 // never fail nowadays, in sane cases.
353 ImportRule::ImportRule(const ImportRule& aCopy)
354 : Rule(aCopy),
355 mURLSpec(aCopy.mURLSpec)
357 // Whether or not an @import rule has a null sheet is a permanent
358 // property of that @import rule, since it is null only if the target
359 // sheet failed security checks.
360 if (aCopy.mChildSheet) {
361 nsRefPtr<nsCSSStyleSheet> sheet =
362 aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
363 SetSheet(sheet);
364 // SetSheet sets mMedia appropriately
368 ImportRule::~ImportRule()
370 if (mChildSheet) {
371 mChildSheet->SetOwnerRule(nullptr);
375 NS_IMPL_ADDREF(ImportRule)
376 NS_IMPL_RELEASE(ImportRule)
378 // QueryInterface implementation for ImportRule
379 NS_INTERFACE_MAP_BEGIN(ImportRule)
380 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
381 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
382 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
383 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
384 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
385 NS_INTERFACE_MAP_END
387 IMPL_STYLE_RULE_INHERIT(ImportRule, Rule)
389 #ifdef DEBUG
390 /* virtual */ void
391 ImportRule::List(FILE* out, int32_t aIndent) const
393 // Indent
394 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
396 fputs("@import \"", out);
397 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
398 fputs("\" ", out);
400 nsAutoString mediaText;
401 mMedia->GetText(mediaText);
402 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
403 fputs("\n", out);
405 #endif
407 /* virtual */ int32_t
408 ImportRule::GetType() const
410 return Rule::IMPORT_RULE;
413 /* virtual */ already_AddRefed<Rule>
414 ImportRule::Clone() const
416 nsRefPtr<Rule> clone = new ImportRule(*this);
417 return clone.forget();
420 void
421 ImportRule::SetSheet(nsCSSStyleSheet* aSheet)
423 NS_PRECONDITION(aSheet, "null arg");
425 // set the new sheet
426 mChildSheet = aSheet;
427 aSheet->SetOwnerRule(this);
429 // set our medialist to be the same as the sheet's medialist
430 nsCOMPtr<nsIDOMMediaList> mediaList;
431 mChildSheet->GetMedia(getter_AddRefs(mediaList));
432 NS_ABORT_IF_FALSE(mediaList, "GetMedia returned null");
433 mMedia = static_cast<nsMediaList*>(mediaList.get());
436 NS_IMETHODIMP
437 ImportRule::GetType(uint16_t* aType)
439 NS_ENSURE_ARG_POINTER(aType);
440 *aType = nsIDOMCSSRule::IMPORT_RULE;
441 return NS_OK;
444 NS_IMETHODIMP
445 ImportRule::GetCssText(nsAString& aCssText)
447 aCssText.AssignLiteral("@import url(");
448 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
449 aCssText.Append(NS_LITERAL_STRING(")"));
450 if (mMedia) {
451 nsAutoString mediaText;
452 mMedia->GetText(mediaText);
453 if (!mediaText.IsEmpty()) {
454 aCssText.AppendLiteral(" ");
455 aCssText.Append(mediaText);
458 aCssText.AppendLiteral(";");
459 return NS_OK;
462 NS_IMETHODIMP
463 ImportRule::SetCssText(const nsAString& aCssText)
465 return NS_ERROR_NOT_IMPLEMENTED;
468 NS_IMETHODIMP
469 ImportRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
471 return Rule::GetParentStyleSheet(aSheet);
474 NS_IMETHODIMP
475 ImportRule::GetParentRule(nsIDOMCSSRule** aParentRule)
477 return Rule::GetParentRule(aParentRule);
480 NS_IMETHODIMP
481 ImportRule::GetHref(nsAString & aHref)
483 aHref = mURLSpec;
484 return NS_OK;
487 NS_IMETHODIMP
488 ImportRule::GetMedia(nsIDOMMediaList * *aMedia)
490 NS_ENSURE_ARG_POINTER(aMedia);
492 NS_IF_ADDREF(*aMedia = mMedia);
493 return NS_OK;
496 NS_IMETHODIMP
497 ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
499 NS_ENSURE_ARG_POINTER(aStyleSheet);
501 NS_IF_ADDREF(*aStyleSheet = mChildSheet);
502 return NS_OK;
505 /* virtual */ size_t
506 ImportRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
508 return aMallocSizeOf(this);
510 // Measurement of the following members may be added later if DMD finds it is
511 // worthwhile:
512 // - mURLSpec
514 // The following members are not measured:
515 // - mMedia, because it is measured via nsCSSStyleSheet::mMedia
516 // - mChildSheet, because it is measured via nsCSSStyleSheetInner::mSheets
519 } // namespace css
520 } // namespace mozilla
522 // must be outside the namespace
523 DOMCI_DATA(CSSImportRule, css::ImportRule)
525 static bool
526 CloneRuleInto(css::Rule* aRule, void* aArray)
528 nsRefPtr<css::Rule> clone = aRule->Clone();
529 static_cast<nsCOMArray<css::Rule>*>(aArray)->AppendObject(clone);
530 return true;
533 namespace mozilla {
534 namespace css {
536 GroupRule::GroupRule()
537 : Rule()
541 static bool
542 SetParentRuleReference(Rule* aRule, void* aParentRule)
544 GroupRule* parentRule = static_cast<GroupRule*>(aParentRule);
545 aRule->SetParentRule(parentRule);
546 return true;
549 GroupRule::GroupRule(const GroupRule& aCopy)
550 : Rule(aCopy)
552 const_cast<GroupRule&>(aCopy).mRules.EnumerateForwards(CloneRuleInto, &mRules);
553 mRules.EnumerateForwards(SetParentRuleReference, this);
556 GroupRule::~GroupRule()
558 NS_ABORT_IF_FALSE(!mSheet, "SetStyleSheet should have been called");
559 mRules.EnumerateForwards(SetParentRuleReference, nullptr);
560 if (mRuleCollection) {
561 mRuleCollection->DropReference();
565 NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupRule)
566 NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupRule)
568 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
569 NS_INTERFACE_MAP_END
571 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(GroupRule, Rule)
573 static bool
574 SetStyleSheetReference(Rule* aRule, void* aSheet)
576 nsCSSStyleSheet* sheet = (nsCSSStyleSheet*)aSheet;
577 aRule->SetStyleSheet(sheet);
578 return true;
581 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupRule)
582 tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr);
583 // If tmp does not have a stylesheet, neither do its descendants. In that
584 // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
585 // depth of group rule nesting. But if tmp _does_ have a stylesheet (which
586 // can happen if it gets unlinked earlier than its owning stylesheet), then we
587 // need to null out the stylesheet pointer on descendants now, before we clear
588 // tmp->mRules.
589 if (tmp->GetStyleSheet()) {
590 tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr);
592 tmp->mRules.Clear();
593 if (tmp->mRuleCollection) {
594 tmp->mRuleCollection->DropReference();
595 tmp->mRuleCollection = nullptr;
597 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
599 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupRule)
600 const nsCOMArray<Rule>& rules = tmp->mRules;
601 for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
602 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
603 cb.NoteXPCOMChild(rules[i]->GetExistingDOMRule());
605 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection)
606 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
608 /* virtual */ void
609 GroupRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
611 // Don't set the sheet on the kids if it's already the same as the sheet we
612 // already have. This is needed to avoid O(N^2) behavior in group nesting
613 // depth when seting the sheet to null during unlink, if we happen to unlin in
614 // order from most nested rule up to least nested rule.
615 if (aSheet != GetStyleSheet()) {
616 mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
617 Rule::SetStyleSheet(aSheet);
621 #ifdef DEBUG
622 /* virtual */ void
623 GroupRule::List(FILE* out, int32_t aIndent) const
625 fputs(" {\n", out);
627 for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
628 mRules.ObjectAt(index)->List(out, aIndent + 1);
631 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
632 fputs("}\n", out);
634 #endif
636 void
637 GroupRule::AppendStyleRule(Rule* aRule)
639 mRules.AppendObject(aRule);
640 nsCSSStyleSheet* sheet = GetStyleSheet();
641 aRule->SetStyleSheet(sheet);
642 aRule->SetParentRule(this);
643 if (sheet) {
644 sheet->SetModifiedByChildRule();
648 Rule*
649 GroupRule::GetStyleRuleAt(int32_t aIndex) const
651 return mRules.SafeObjectAt(aIndex);
654 bool
655 GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
657 return
658 const_cast<GroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
662 * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
663 * should never be called unless you have first called WillDirty() on
664 * the parents stylesheet. After they are called, DidDirty() needs to
665 * be called on the sheet
667 nsresult
668 GroupRule::DeleteStyleRuleAt(uint32_t aIndex)
670 Rule* rule = mRules.SafeObjectAt(aIndex);
671 if (rule) {
672 rule->SetStyleSheet(nullptr);
673 rule->SetParentRule(nullptr);
675 return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
678 nsresult
679 GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
681 aRule->SetStyleSheet(GetStyleSheet());
682 aRule->SetParentRule(this);
683 if (! mRules.InsertObjectAt(aRule, aIndex)) {
684 return NS_ERROR_FAILURE;
686 return NS_OK;
689 nsresult
690 GroupRule::ReplaceStyleRule(Rule* aOld, Rule* aNew)
692 int32_t index = mRules.IndexOf(aOld);
693 NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED);
694 mRules.ReplaceObjectAt(aNew, index);
695 aNew->SetStyleSheet(GetStyleSheet());
696 aNew->SetParentRule(this);
697 aOld->SetStyleSheet(nullptr);
698 aOld->SetParentRule(nullptr);
699 return NS_OK;
702 nsresult
703 GroupRule::AppendRulesToCssText(nsAString& aCssText)
705 aCssText.AppendLiteral(" {\n");
707 // get all the rules
708 for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
709 Rule* rule = mRules.ObjectAt(index);
710 nsIDOMCSSRule* domRule = rule->GetDOMRule();
711 if (domRule) {
712 nsAutoString cssText;
713 domRule->GetCssText(cssText);
714 aCssText.Append(NS_LITERAL_STRING(" ") +
715 cssText +
716 NS_LITERAL_STRING("\n"));
720 aCssText.AppendLiteral("}");
722 return NS_OK;
725 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
726 nsresult
727 GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
729 if (!mRuleCollection) {
730 mRuleCollection = new css::GroupRuleRuleList(this);
733 NS_ADDREF(*aRuleList = mRuleCollection);
734 return NS_OK;
737 nsresult
738 GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
740 nsCSSStyleSheet* sheet = GetStyleSheet();
741 NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
743 if (aIndex > uint32_t(mRules.Count()))
744 return NS_ERROR_DOM_INDEX_SIZE_ERR;
746 NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
747 "Too many style rules!");
749 return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
752 nsresult
753 GroupRule::DeleteRule(uint32_t aIndex)
755 nsCSSStyleSheet* sheet = GetStyleSheet();
756 NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
758 if (aIndex >= uint32_t(mRules.Count()))
759 return NS_ERROR_DOM_INDEX_SIZE_ERR;
761 NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
762 "Too many style rules!");
764 return sheet->DeleteRuleFromGroup(this, aIndex);
767 /* virtual */ size_t
768 GroupRule::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
770 return mRules.SizeOfExcludingThis(Rule::SizeOfCOMArrayElementIncludingThis,
771 aMallocSizeOf);
773 // Measurement of the following members may be added later if DMD finds it is
774 // worthwhile:
775 // - mRuleCollection
779 // -------------------------------------------
780 // nsICSSMediaRule
782 MediaRule::MediaRule()
786 MediaRule::MediaRule(const MediaRule& aCopy)
787 : GroupRule(aCopy)
789 if (aCopy.mMedia) {
790 aCopy.mMedia->Clone(getter_AddRefs(mMedia));
791 if (mMedia) {
792 // XXXldb This doesn't really make sense.
793 mMedia->SetStyleSheet(aCopy.GetStyleSheet());
798 MediaRule::~MediaRule()
800 if (mMedia) {
801 mMedia->SetStyleSheet(nullptr);
805 NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule)
806 NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule)
808 // QueryInterface implementation for MediaRule
809 NS_INTERFACE_MAP_BEGIN(MediaRule)
810 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
811 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
812 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
813 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
814 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
815 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
816 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
817 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
819 /* virtual */ void
820 MediaRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
822 if (mMedia) {
823 // Set to null so it knows it's leaving one sheet and joining another.
824 mMedia->SetStyleSheet(nullptr);
825 mMedia->SetStyleSheet(aSheet);
828 GroupRule::SetStyleSheet(aSheet);
831 #ifdef DEBUG
832 /* virtual */ void
833 MediaRule::List(FILE* out, int32_t aIndent) const
835 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
837 nsAutoString buffer;
839 fputs("@media ", out);
841 if (mMedia) {
842 nsAutoString mediaText;
843 mMedia->GetText(mediaText);
844 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
847 GroupRule::List(out, aIndent);
849 #endif
851 /* virtual */ int32_t
852 MediaRule::GetType() const
854 return Rule::MEDIA_RULE;
857 /* virtual */ already_AddRefed<Rule>
858 MediaRule::Clone() const
860 nsRefPtr<Rule> clone = new MediaRule(*this);
861 return clone.forget();
864 nsresult
865 MediaRule::SetMedia(nsMediaList* aMedia)
867 mMedia = aMedia;
868 if (aMedia)
869 mMedia->SetStyleSheet(GetStyleSheet());
870 return NS_OK;
873 // nsIDOMCSSRule methods
874 NS_IMETHODIMP
875 MediaRule::GetType(uint16_t* aType)
877 *aType = nsIDOMCSSRule::MEDIA_RULE;
878 return NS_OK;
881 NS_IMETHODIMP
882 MediaRule::GetCssText(nsAString& aCssText)
884 aCssText.AssignLiteral("@media ");
885 AppendConditionText(aCssText);
886 return GroupRule::AppendRulesToCssText(aCssText);
889 NS_IMETHODIMP
890 MediaRule::SetCssText(const nsAString& aCssText)
892 return NS_ERROR_NOT_IMPLEMENTED;
895 NS_IMETHODIMP
896 MediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
898 return GroupRule::GetParentStyleSheet(aSheet);
901 NS_IMETHODIMP
902 MediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
904 return GroupRule::GetParentRule(aParentRule);
907 // nsIDOMCSSGroupingRule methods
908 NS_IMETHODIMP
909 MediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
911 return GroupRule::GetCssRules(aRuleList);
914 NS_IMETHODIMP
915 MediaRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
917 return GroupRule::InsertRule(aRule, aIndex, _retval);
920 NS_IMETHODIMP
921 MediaRule::DeleteRule(uint32_t aIndex)
923 return GroupRule::DeleteRule(aIndex);
926 // nsIDOMCSSConditionRule methods
927 NS_IMETHODIMP
928 MediaRule::GetConditionText(nsAString& aConditionText)
930 aConditionText.Truncate(0);
931 AppendConditionText(aConditionText);
932 return NS_OK;
935 NS_IMETHODIMP
936 MediaRule::SetConditionText(const nsAString& aConditionText)
938 if (!mMedia) {
939 nsRefPtr<nsMediaList> media = new nsMediaList();
940 media->SetStyleSheet(GetStyleSheet());
941 nsresult rv = media->SetMediaText(aConditionText);
942 if (NS_SUCCEEDED(rv)) {
943 mMedia = media;
945 return rv;
948 return mMedia->SetMediaText(aConditionText);
951 // nsIDOMCSSMediaRule methods
952 NS_IMETHODIMP
953 MediaRule::GetMedia(nsIDOMMediaList* *aMedia)
955 NS_ENSURE_ARG_POINTER(aMedia);
956 NS_IF_ADDREF(*aMedia = mMedia);
957 return NS_OK;
960 // GroupRule interface
961 /* virtual */ bool
962 MediaRule::UseForPresentation(nsPresContext* aPresContext,
963 nsMediaQueryResultCacheKey& aKey)
965 if (mMedia) {
966 return mMedia->Matches(aPresContext, &aKey);
968 return true;
971 /* virtual */ size_t
972 MediaRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
974 size_t n = aMallocSizeOf(this);
975 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
977 // Measurement of the following members may be added later if DMD finds it is
978 // worthwhile:
979 // - mMedia
981 return n;
984 void
985 MediaRule::AppendConditionText(nsAString& aOutput)
987 if (mMedia) {
988 nsAutoString mediaText;
989 mMedia->GetText(mediaText);
990 aOutput.Append(mediaText);
994 } // namespace css
995 } // namespace mozilla
997 // Must be outside namespace
998 DOMCI_DATA(CSSMediaRule, css::MediaRule)
1000 namespace mozilla {
1001 namespace css {
1003 DocumentRule::DocumentRule()
1007 DocumentRule::DocumentRule(const DocumentRule& aCopy)
1008 : GroupRule(aCopy)
1009 , mURLs(new URL(*aCopy.mURLs))
1013 DocumentRule::~DocumentRule()
1017 NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule)
1018 NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule)
1020 // QueryInterface implementation for DocumentRule
1021 NS_INTERFACE_MAP_BEGIN(DocumentRule)
1022 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1023 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1024 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
1025 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
1026 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
1027 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1028 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
1029 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
1031 #ifdef DEBUG
1032 /* virtual */ void
1033 DocumentRule::List(FILE* out, int32_t aIndent) const
1035 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
1037 nsAutoCString str;
1038 str.AssignLiteral("@-moz-document ");
1039 for (URL *url = mURLs; url; url = url->next) {
1040 switch (url->func) {
1041 case eURL:
1042 str.AppendLiteral("url(\"");
1043 break;
1044 case eURLPrefix:
1045 str.AppendLiteral("url-prefix(\"");
1046 break;
1047 case eDomain:
1048 str.AppendLiteral("domain(\"");
1049 break;
1050 case eRegExp:
1051 str.AppendLiteral("regexp(\"");
1052 break;
1054 nsAutoCString escapedURL(url->url);
1055 escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
1056 str.Append(escapedURL);
1057 str.AppendLiteral("\"), ");
1059 str.Cut(str.Length() - 2, 1); // remove last ,
1060 fputs(str.get(), out);
1062 GroupRule::List(out, aIndent);
1064 #endif
1066 /* virtual */ int32_t
1067 DocumentRule::GetType() const
1069 return Rule::DOCUMENT_RULE;
1072 /* virtual */ already_AddRefed<Rule>
1073 DocumentRule::Clone() const
1075 nsRefPtr<Rule> clone = new DocumentRule(*this);
1076 return clone.forget();
1079 // nsIDOMCSSRule methods
1080 NS_IMETHODIMP
1081 DocumentRule::GetType(uint16_t* aType)
1083 // XXX What should really happen here?
1084 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1085 return NS_OK;
1088 NS_IMETHODIMP
1089 DocumentRule::GetCssText(nsAString& aCssText)
1091 aCssText.AssignLiteral("@-moz-document ");
1092 AppendConditionText(aCssText);
1093 return GroupRule::AppendRulesToCssText(aCssText);
1096 NS_IMETHODIMP
1097 DocumentRule::SetCssText(const nsAString& aCssText)
1099 return NS_ERROR_NOT_IMPLEMENTED;
1102 NS_IMETHODIMP
1103 DocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1105 return GroupRule::GetParentStyleSheet(aSheet);
1108 NS_IMETHODIMP
1109 DocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1111 return GroupRule::GetParentRule(aParentRule);
1114 // nsIDOMCSSGroupingRule methods
1115 NS_IMETHODIMP
1116 DocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1118 return GroupRule::GetCssRules(aRuleList);
1121 NS_IMETHODIMP
1122 DocumentRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
1124 return GroupRule::InsertRule(aRule, aIndex, _retval);
1127 NS_IMETHODIMP
1128 DocumentRule::DeleteRule(uint32_t aIndex)
1130 return GroupRule::DeleteRule(aIndex);
1133 // nsIDOMCSSConditionRule methods
1134 NS_IMETHODIMP
1135 DocumentRule::GetConditionText(nsAString& aConditionText)
1137 aConditionText.Truncate(0);
1138 AppendConditionText(aConditionText);
1139 return NS_OK;
1142 NS_IMETHODIMP
1143 DocumentRule::SetConditionText(const nsAString& aConditionText)
1145 return NS_ERROR_NOT_IMPLEMENTED;
1148 // GroupRule interface
1149 /* virtual */ bool
1150 DocumentRule::UseForPresentation(nsPresContext* aPresContext,
1151 nsMediaQueryResultCacheKey& aKey)
1153 nsIDocument *doc = aPresContext->Document();
1154 nsIURI *docURI = doc->GetDocumentURI();
1155 nsAutoCString docURISpec;
1156 if (docURI)
1157 docURI->GetSpec(docURISpec);
1159 for (URL *url = mURLs; url; url = url->next) {
1160 switch (url->func) {
1161 case eURL: {
1162 if (docURISpec == url->url)
1163 return true;
1164 } break;
1165 case eURLPrefix: {
1166 if (StringBeginsWith(docURISpec, url->url))
1167 return true;
1168 } break;
1169 case eDomain: {
1170 nsAutoCString host;
1171 if (docURI)
1172 docURI->GetHost(host);
1173 int32_t lenDiff = host.Length() - url->url.Length();
1174 if (lenDiff == 0) {
1175 if (host == url->url)
1176 return true;
1177 } else {
1178 if (StringEndsWith(host, url->url) &&
1179 host.CharAt(lenDiff - 1) == '.')
1180 return true;
1182 } break;
1183 case eRegExp: {
1184 NS_ConvertUTF8toUTF16 spec(docURISpec);
1185 NS_ConvertUTF8toUTF16 regex(url->url);
1186 if (nsContentUtils::IsPatternMatching(spec, regex, doc)) {
1187 return true;
1189 } break;
1193 return false;
1196 DocumentRule::URL::~URL()
1198 NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
1201 /* virtual */ size_t
1202 DocumentRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
1204 size_t n = aMallocSizeOf(this);
1205 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
1207 // Measurement of the following members may be added later if DMD finds it is
1208 // worthwhile:
1209 // - mURLs
1211 return n;
1214 void
1215 DocumentRule::AppendConditionText(nsAString& aCssText)
1217 for (URL *url = mURLs; url; url = url->next) {
1218 switch (url->func) {
1219 case eURL:
1220 aCssText.AppendLiteral("url(");
1221 break;
1222 case eURLPrefix:
1223 aCssText.AppendLiteral("url-prefix(");
1224 break;
1225 case eDomain:
1226 aCssText.AppendLiteral("domain(");
1227 break;
1228 case eRegExp:
1229 aCssText.AppendLiteral("regexp(");
1230 break;
1232 nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
1233 aCssText);
1234 aCssText.AppendLiteral("), ");
1236 aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
1239 } // namespace css
1240 } // namespace mozilla
1242 // Must be outside namespace
1243 DOMCI_DATA(CSSMozDocumentRule, css::DocumentRule)
1245 // -------------------------------------------
1246 // NameSpaceRule
1249 namespace mozilla {
1250 namespace css {
1252 NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec)
1253 : Rule(),
1254 mPrefix(aPrefix),
1255 mURLSpec(aURLSpec)
1259 NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
1260 : Rule(aCopy),
1261 mPrefix(aCopy.mPrefix),
1262 mURLSpec(aCopy.mURLSpec)
1266 NameSpaceRule::~NameSpaceRule()
1270 NS_IMPL_ADDREF(NameSpaceRule)
1271 NS_IMPL_RELEASE(NameSpaceRule)
1273 // QueryInterface implementation for NameSpaceRule
1274 NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
1275 if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) {
1276 *aInstancePtr = this;
1277 NS_ADDREF_THIS();
1278 return NS_OK;
1280 else
1281 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1282 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1283 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1284 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule)
1285 NS_INTERFACE_MAP_END
1287 IMPL_STYLE_RULE_INHERIT(NameSpaceRule, Rule)
1289 #ifdef DEBUG
1290 /* virtual */ void
1291 NameSpaceRule::List(FILE* out, int32_t aIndent) const
1293 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
1295 nsAutoString buffer;
1297 fputs("@namespace ", out);
1299 if (mPrefix) {
1300 mPrefix->ToString(buffer);
1301 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
1302 fputs(" ", out);
1305 fputs("url(", out);
1306 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
1307 fputs(")\n", out);
1309 #endif
1311 /* virtual */ int32_t
1312 NameSpaceRule::GetType() const
1314 return Rule::NAMESPACE_RULE;
1317 /* virtual */ already_AddRefed<Rule>
1318 NameSpaceRule::Clone() const
1320 nsRefPtr<Rule> clone = new NameSpaceRule(*this);
1321 return clone.forget();
1324 NS_IMETHODIMP
1325 NameSpaceRule::GetType(uint16_t* aType)
1327 *aType = nsIDOMCSSRule::NAMESPACE_RULE;
1328 return NS_OK;
1331 NS_IMETHODIMP
1332 NameSpaceRule::GetCssText(nsAString& aCssText)
1334 aCssText.AssignLiteral("@namespace ");
1335 if (mPrefix) {
1336 aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
1338 aCssText.AppendLiteral("url(");
1339 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
1340 aCssText.Append(NS_LITERAL_STRING(");"));
1341 return NS_OK;
1344 NS_IMETHODIMP
1345 NameSpaceRule::SetCssText(const nsAString& aCssText)
1347 return NS_ERROR_NOT_IMPLEMENTED;
1350 NS_IMETHODIMP
1351 NameSpaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1353 return Rule::GetParentStyleSheet(aSheet);
1356 NS_IMETHODIMP
1357 NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1359 return Rule::GetParentRule(aParentRule);
1362 /* virtual */ size_t
1363 NameSpaceRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
1365 return aMallocSizeOf(this);
1367 // Measurement of the following members may be added later if DMD finds it is
1368 // worthwhile:
1369 // - mPrefix
1370 // - mURLSpec
1374 } // namespace css
1375 } // namespace mozilla
1377 // Must be outside namespace
1378 DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule)
1380 // -------------------------------------------
1381 // nsCSSFontFaceStyleDecl and related routines
1384 // A src: descriptor is represented as an array value; each entry in
1385 // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
1386 // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear
1387 // only after one of the first two. (css3-fonts only contemplates
1388 // annotating URLs with formats, but we handle the general case.)
1389 static void
1390 AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult)
1392 NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array,
1393 "improper value unit for src:");
1395 const nsCSSValue::Array& sources = *src.GetArrayValue();
1396 size_t i = 0;
1398 while (i < sources.Count()) {
1399 nsAutoString formats;
1401 if (sources[i].GetUnit() == eCSSUnit_URL) {
1402 aResult.AppendLiteral("url(");
1403 nsDependentString url(sources[i].GetOriginalURLValue());
1404 nsStyleUtil::AppendEscapedCSSString(url, aResult);
1405 aResult.AppendLiteral(")");
1406 } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
1407 aResult.AppendLiteral("local(");
1408 nsDependentString local(sources[i].GetStringBufferValue());
1409 nsStyleUtil::AppendEscapedCSSString(local, aResult);
1410 aResult.AppendLiteral(")");
1411 } else {
1412 NS_NOTREACHED("entry in src: descriptor with improper unit");
1413 i++;
1414 continue;
1417 i++;
1418 formats.Truncate();
1419 while (i < sources.Count() &&
1420 sources[i].GetUnit() == eCSSUnit_Font_Format) {
1421 formats.Append('"');
1422 formats.Append(sources[i].GetStringBufferValue());
1423 formats.AppendLiteral("\", ");
1424 i++;
1426 if (formats.Length() > 0) {
1427 formats.Truncate(formats.Length() - 2); // remove the last comma
1428 aResult.AppendLiteral(" format(");
1429 aResult.Append(formats);
1430 aResult.Append(')');
1432 aResult.AppendLiteral(", ");
1434 aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
1437 // print all characters with at least four hex digits
1438 static void
1439 AppendSerializedUnicodePoint(uint32_t aCode, nsACString &aBuf)
1441 aBuf.Append(nsPrintfCString("%04X", aCode));
1444 // A unicode-range: descriptor is represented as an array of integers,
1445 // to be interpreted as a sequence of pairs: min max min max ...
1446 // It is in source order. (Possibly it should be sorted and overlaps
1447 // consolidated, but right now we don't do that.)
1448 static void
1449 AppendSerializedUnicodeRange(nsCSSValue const & aValue,
1450 nsAString & aResult)
1452 NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null ||
1453 aValue.GetUnit() == eCSSUnit_Array,
1454 "improper value unit for unicode-range:");
1455 aResult.Truncate();
1456 if (aValue.GetUnit() != eCSSUnit_Array)
1457 return;
1459 nsCSSValue::Array const & sources = *aValue.GetArrayValue();
1460 nsAutoCString buf;
1462 NS_ABORT_IF_FALSE(sources.Count() % 2 == 0,
1463 "odd number of entries in a unicode-range: array");
1465 for (uint32_t i = 0; i < sources.Count(); i += 2) {
1466 uint32_t min = sources[i].GetIntValue();
1467 uint32_t max = sources[i+1].GetIntValue();
1469 // We don't try to replicate the U+XX?? notation.
1470 buf.AppendLiteral("U+");
1471 AppendSerializedUnicodePoint(min, buf);
1473 if (min != max) {
1474 buf.Append('-');
1475 AppendSerializedUnicodePoint(max, buf);
1477 buf.AppendLiteral(", ");
1479 buf.Truncate(buf.Length() - 2); // remove the last comma-space
1480 CopyASCIItoUTF16(buf, aResult);
1483 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
1484 nsCSSValue nsCSSFontFaceStyleDecl::* const
1485 nsCSSFontFaceStyleDecl::Fields[] = {
1486 #define CSS_FONT_DESC(name_, method_) &nsCSSFontFaceStyleDecl::m##method_,
1487 #include "nsCSSFontDescList.h"
1488 #undef CSS_FONT_DESC
1491 // QueryInterface implementation for nsCSSFontFaceStyleDecl
1492 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
1493 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1494 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
1495 NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
1496 NS_INTERFACE_MAP_ENTRY(nsISupports)
1497 // We forward the cycle collection interfaces to ContainingRule(), which is
1498 // never null (in fact, we're part of that object!)
1499 if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
1500 aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
1501 return ContainingRule()->QueryInterface(aIID, aInstancePtr);
1503 else
1504 NS_INTERFACE_MAP_END
1506 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1507 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1509 // helper for string GetPropertyValue and RemovePropertyValue
1510 nsresult
1511 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
1512 nsAString & aResult) const
1514 NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
1515 eCSSFontDesc_COUNT - 1);
1517 aResult.Truncate();
1518 if (aFontDescID == eCSSFontDesc_UNKNOWN)
1519 return NS_OK;
1521 const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID];
1523 if (val.GetUnit() == eCSSUnit_Null) {
1524 // Avoid having to check no-value in the Family and Src cases below.
1525 return NS_OK;
1528 switch (aFontDescID) {
1529 case eCSSFontDesc_Family: {
1530 // we don't use nsCSSValue::AppendToString here because it doesn't
1531 // canonicalize the way we want, and anyway it's overkill when
1532 // we know we have eCSSUnit_String
1533 NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
1534 nsDependentString family(val.GetStringBufferValue());
1535 nsStyleUtil::AppendEscapedCSSString(family, aResult);
1536 return NS_OK;
1539 case eCSSFontDesc_Style:
1540 val.AppendToString(eCSSProperty_font_style, aResult);
1541 return NS_OK;
1543 case eCSSFontDesc_Weight:
1544 val.AppendToString(eCSSProperty_font_weight, aResult);
1545 return NS_OK;
1547 case eCSSFontDesc_Stretch:
1548 val.AppendToString(eCSSProperty_font_stretch, aResult);
1549 return NS_OK;
1551 case eCSSFontDesc_FontFeatureSettings:
1552 nsStyleUtil::AppendFontFeatureSettings(val, aResult);
1553 return NS_OK;
1555 case eCSSFontDesc_FontLanguageOverride:
1556 val.AppendToString(eCSSProperty_font_language_override, aResult);
1557 return NS_OK;
1559 case eCSSFontDesc_Src:
1560 AppendSerializedFontSrc(val, aResult);
1561 return NS_OK;
1563 case eCSSFontDesc_UnicodeRange:
1564 AppendSerializedUnicodeRange(val, aResult);
1565 return NS_OK;
1567 case eCSSFontDesc_UNKNOWN:
1568 case eCSSFontDesc_COUNT:
1571 NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
1572 "out-of-range value got to the switch");
1573 return NS_ERROR_INVALID_ARG;
1577 // attribute DOMString cssText;
1578 NS_IMETHODIMP
1579 nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
1581 nsAutoString descStr;
1583 aCssText.Truncate();
1584 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1585 id < eCSSFontDesc_COUNT;
1586 id = nsCSSFontDesc(id + 1)) {
1587 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1588 != eCSSUnit_Null &&
1589 NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
1590 NS_ASSERTION(descStr.Length() > 0,
1591 "GetCssText: non-null unit, empty property value");
1592 aCssText.AppendLiteral(" ");
1593 aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
1594 aCssText.AppendLiteral(": ");
1595 aCssText.Append(descStr);
1596 aCssText.AppendLiteral(";\n");
1599 return NS_OK;
1602 NS_IMETHODIMP
1603 nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
1605 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1608 // DOMString getPropertyValue (in DOMString propertyName);
1609 NS_IMETHODIMP
1610 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
1611 nsAString & aResult)
1613 return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
1616 // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
1617 already_AddRefed<dom::CSSValue>
1618 nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
1619 ErrorResult& aRv)
1621 // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
1622 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
1623 return nullptr;
1626 // DOMString removeProperty (in DOMString propertyName) raises (DOMException);
1627 NS_IMETHODIMP
1628 nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
1629 nsAString & aResult)
1631 nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
1632 NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
1633 descID < eCSSFontDesc_COUNT,
1634 "LookupFontDesc returned value out of range");
1636 if (descID == eCSSFontDesc_UNKNOWN) {
1637 aResult.Truncate();
1638 } else {
1639 nsresult rv = GetPropertyValue(descID, aResult);
1640 NS_ENSURE_SUCCESS(rv, rv);
1641 (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset();
1643 return NS_OK;
1646 // DOMString getPropertyPriority (in DOMString propertyName);
1647 NS_IMETHODIMP
1648 nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
1649 nsAString & aResult)
1651 // font descriptors do not have priorities at present
1652 aResult.Truncate();
1653 return NS_OK;
1656 // void setProperty (in DOMString propertyName, in DOMString value,
1657 // in DOMString priority) raises (DOMException);
1658 NS_IMETHODIMP
1659 nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
1660 const nsAString & value,
1661 const nsAString & priority)
1663 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1666 // readonly attribute unsigned long length;
1667 NS_IMETHODIMP
1668 nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength)
1670 uint32_t len = 0;
1671 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1672 id < eCSSFontDesc_COUNT;
1673 id = nsCSSFontDesc(id + 1))
1674 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null)
1675 len++;
1677 *aLength = len;
1678 return NS_OK;
1681 // DOMString item (in unsigned long index);
1682 NS_IMETHODIMP
1683 nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn)
1685 bool found;
1686 IndexedGetter(aIndex, found, aReturn);
1687 if (!found) {
1688 aReturn.Truncate();
1690 return NS_OK;
1693 void
1694 nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult)
1696 int32_t nset = -1;
1697 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1698 id < eCSSFontDesc_COUNT;
1699 id = nsCSSFontDesc(id + 1)) {
1700 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1701 != eCSSUnit_Null) {
1702 nset++;
1703 if (nset == int32_t(index)) {
1704 aFound = true;
1705 aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
1706 return;
1710 aFound = false;
1713 // readonly attribute nsIDOMCSSRule parentRule;
1714 NS_IMETHODIMP
1715 nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
1717 NS_IF_ADDREF(*aParentRule = ContainingRule()->GetDOMRule());
1718 return NS_OK;
1721 NS_IMETHODIMP
1722 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSProperty aPropID,
1723 nsAString& aValue)
1725 return
1726 GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1727 aValue);
1730 NS_IMETHODIMP
1731 nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSProperty aPropID,
1732 const nsAString& aValue)
1734 return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1735 aValue, EmptyString());
1738 nsINode*
1739 nsCSSFontFaceStyleDecl::GetParentObject()
1741 return ContainingRule()->GetDocument();
1744 JSObject*
1745 nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
1747 return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, scope, this);
1750 // -------------------------------------------
1751 // nsCSSFontFaceRule
1754 /* virtual */ already_AddRefed<css::Rule>
1755 nsCSSFontFaceRule::Clone() const
1757 nsRefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
1758 return clone.forget();
1761 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSFontFaceRule)
1762 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSFontFaceRule)
1764 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule)
1765 // Trace the wrapper for our declaration. This just expands out
1766 // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
1767 // directly because the wrapper is on the declaration, not on us.
1768 nsContentUtils::TraceWrapper(&tmp->mDecl, aCallback, aClosure);
1769 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1771 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule)
1772 // Unlink the wrapper for our declaraton. This just expands out
1773 // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
1774 // directly because the wrapper is on the declaration, not on us.
1775 nsContentUtils::ReleaseWrapper(static_cast<nsISupports*>(p), &tmp->mDecl);
1776 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1778 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule)
1779 // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call
1780 // into our Trace hook, where we do the right thing with declarations
1781 // already.
1782 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
1783 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1785 DOMCI_DATA(CSSFontFaceRule, nsCSSFontFaceRule)
1787 // QueryInterface implementation for nsCSSFontFaceRule
1788 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSFontFaceRule)
1789 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1790 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
1791 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1792 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1793 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule)
1794 NS_INTERFACE_MAP_END
1796 IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, Rule)
1798 #ifdef DEBUG
1799 void
1800 nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const
1802 nsCString baseInd, descInd;
1803 for (int32_t indent = aIndent; --indent >= 0; ) {
1804 baseInd.AppendLiteral(" ");
1805 descInd.AppendLiteral(" ");
1807 descInd.AppendLiteral(" ");
1809 nsString descStr;
1811 fprintf(out, "%s@font-face {\n", baseInd.get());
1812 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1813 id < eCSSFontDesc_COUNT;
1814 id = nsCSSFontDesc(id + 1))
1815 if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1816 != eCSSUnit_Null) {
1817 if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
1818 descStr.AssignLiteral("#<serialization error>");
1819 else if (descStr.Length() == 0)
1820 descStr.AssignLiteral("#<serialization missing>");
1821 fprintf(out, "%s%s: %s\n",
1822 descInd.get(), nsCSSProps::GetStringValue(id).get(),
1823 NS_ConvertUTF16toUTF8(descStr).get());
1825 fprintf(out, "%s}\n", baseInd.get());
1827 #endif
1829 /* virtual */ int32_t
1830 nsCSSFontFaceRule::GetType() const
1832 return Rule::FONT_FACE_RULE;
1835 NS_IMETHODIMP
1836 nsCSSFontFaceRule::GetType(uint16_t* aType)
1838 *aType = nsIDOMCSSRule::FONT_FACE_RULE;
1839 return NS_OK;
1842 NS_IMETHODIMP
1843 nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
1845 nsAutoString propText;
1846 mDecl.GetCssText(propText);
1848 aCssText.AssignLiteral("@font-face {\n");
1849 aCssText.Append(propText);
1850 aCssText.Append('}');
1851 return NS_OK;
1854 NS_IMETHODIMP
1855 nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
1857 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1860 NS_IMETHODIMP
1861 nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1863 return Rule::GetParentStyleSheet(aSheet);
1866 NS_IMETHODIMP
1867 nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1869 return Rule::GetParentRule(aParentRule);
1872 NS_IMETHODIMP
1873 nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1875 NS_IF_ADDREF(*aStyle = &mDecl);
1876 return NS_OK;
1879 // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
1880 void
1881 nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
1883 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1884 aDescID < eCSSFontDesc_COUNT,
1885 "aDescID out of range in nsCSSFontFaceRule::SetDesc");
1887 // FIXME: handle dynamic changes
1889 mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue;
1892 void
1893 nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
1895 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1896 aDescID < eCSSFontDesc_COUNT,
1897 "aDescID out of range in nsCSSFontFaceRule::GetDesc");
1899 aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];
1902 /* virtual */ size_t
1903 nsCSSFontFaceRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
1905 return aMallocSizeOf(this);
1907 // Measurement of the following members may be added later if DMD finds it is
1908 // worthwhile:
1909 // - mDecl
1913 // -------------------------------------------
1914 // nsCSSKeyframeStyleDeclaration
1917 nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
1918 : mRule(aRule)
1922 nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration()
1924 NS_ASSERTION(!mRule, "DropReference not called.");
1927 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration)
1928 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration)
1930 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration)
1932 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration)
1933 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1934 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
1936 css::Declaration*
1937 nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(bool aAllocate)
1939 if (mRule) {
1940 return mRule->Declaration();
1941 } else {
1942 return nullptr;
1946 void
1947 nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
1949 GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
1952 NS_IMETHODIMP
1953 nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
1955 NS_ENSURE_ARG_POINTER(aParent);
1957 NS_IF_ADDREF(*aParent = mRule);
1958 return NS_OK;
1961 nsresult
1962 nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
1964 NS_ABORT_IF_FALSE(aDecl, "must be non-null");
1965 mRule->ChangeDeclaration(aDecl);
1966 return NS_OK;
1969 nsIDocument*
1970 nsCSSKeyframeStyleDeclaration::DocToUpdate()
1972 return nullptr;
1975 nsINode*
1976 nsCSSKeyframeStyleDeclaration::GetParentObject()
1978 return mRule ? mRule->GetDocument() : nullptr;
1981 // -------------------------------------------
1982 // nsCSSKeyframeRule
1985 nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
1986 // copy everything except our reference count and mDOMDeclaration
1987 : Rule(aCopy)
1988 , mKeys(aCopy.mKeys)
1989 , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
1993 nsCSSKeyframeRule::~nsCSSKeyframeRule()
1995 if (mDOMDeclaration) {
1996 mDOMDeclaration->DropReference();
2000 /* virtual */ already_AddRefed<css::Rule>
2001 nsCSSKeyframeRule::Clone() const
2003 nsRefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
2004 return clone.forget();
2007 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule)
2008 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule)
2011 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule)
2012 if (tmp->mDOMDeclaration) {
2013 tmp->mDOMDeclaration->DropReference();
2014 ImplCycleCollectionUnlink(tmp->mDOMDeclaration);
2016 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
2017 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule)
2018 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
2019 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2021 DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule)
2023 // QueryInterface implementation for nsCSSKeyframeRule
2024 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule)
2025 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2026 NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
2027 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2028 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2029 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframeRule)
2030 NS_INTERFACE_MAP_END
2032 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule)
2034 /* virtual */ void
2035 nsCSSKeyframeRule::MapRuleInfoInto(nsRuleData* aRuleData)
2037 // We need to implement MapRuleInfoInto because the animation manager
2038 // constructs a rule node pointing to us in order to compute the
2039 // styles it needs to animate.
2041 // The spec says that !important declarations should just be ignored
2042 NS_ASSERTION(!mDeclaration->HasImportantData(),
2043 "Keyframe rules has !important data");
2045 mDeclaration->MapNormalRuleInfoInto(aRuleData);
2048 #ifdef DEBUG
2049 void
2050 nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const
2052 for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out);
2054 nsAutoString tmp;
2055 DoGetKeyText(tmp);
2056 fputs(NS_ConvertUTF16toUTF8(tmp).get(), out);
2057 fputs(" ", out);
2058 mDeclaration->List(out, aIndent);
2059 fputs("\n", out);
2061 #endif
2063 /* virtual */ int32_t
2064 nsCSSKeyframeRule::GetType() const
2066 return Rule::KEYFRAME_RULE;
2069 NS_IMETHODIMP
2070 nsCSSKeyframeRule::GetType(uint16_t* aType)
2072 *aType = nsIDOMCSSRule::KEYFRAME_RULE;
2073 return NS_OK;
2076 NS_IMETHODIMP
2077 nsCSSKeyframeRule::GetCssText(nsAString& aCssText)
2079 DoGetKeyText(aCssText);
2080 aCssText.AppendLiteral(" { ");
2081 nsAutoString tmp;
2082 mDeclaration->ToString(tmp);
2083 aCssText.Append(tmp);
2084 aCssText.AppendLiteral(" }");
2085 return NS_OK;
2088 NS_IMETHODIMP
2089 nsCSSKeyframeRule::SetCssText(const nsAString& aCssText)
2091 // FIXME: implement???
2092 return NS_ERROR_NOT_IMPLEMENTED;
2095 NS_IMETHODIMP
2096 nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2098 return Rule::GetParentStyleSheet(aSheet);
2101 NS_IMETHODIMP
2102 nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2104 return Rule::GetParentRule(aParentRule);
2107 NS_IMETHODIMP
2108 nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText)
2110 DoGetKeyText(aKeyText);
2111 return NS_OK;
2114 void
2115 nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const
2117 aKeyText.Truncate();
2118 uint32_t i = 0, i_end = mKeys.Length();
2119 NS_ABORT_IF_FALSE(i_end != 0, "must have some keys");
2120 for (;;) {
2121 aKeyText.AppendFloat(mKeys[i] * 100.0f);
2122 aKeyText.Append(PRUnichar('%'));
2123 if (++i == i_end) {
2124 break;
2126 aKeyText.AppendLiteral(", ");
2130 NS_IMETHODIMP
2131 nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
2133 nsCSSParser parser;
2135 InfallibleTArray<float> newSelectors;
2136 // FIXME: pass filename and line number
2137 if (parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) {
2138 newSelectors.SwapElements(mKeys);
2139 } else {
2140 // for now, we don't do anything if the parse fails
2143 nsCSSStyleSheet* sheet = GetStyleSheet();
2144 if (sheet) {
2145 sheet->SetModifiedByChildRule();
2148 return NS_OK;
2151 NS_IMETHODIMP
2152 nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
2154 if (!mDOMDeclaration) {
2155 mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this);
2157 NS_ADDREF(*aStyle = mDOMDeclaration);
2158 return NS_OK;
2161 void
2162 nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration)
2164 // Be careful to not assign to an nsAutoPtr if we would be assigning
2165 // the thing it already holds.
2166 if (aDeclaration != mDeclaration) {
2167 mDeclaration = aDeclaration;
2170 nsCSSStyleSheet* sheet = GetStyleSheet();
2171 if (sheet) {
2172 sheet->SetModifiedByChildRule();
2176 /* virtual */ size_t
2177 nsCSSKeyframeRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
2179 return aMallocSizeOf(this);
2181 // Measurement of the following members may be added later if DMD finds it is
2182 // worthwhile:
2183 // - mKeys
2184 // - mDeclaration
2185 // - mDOMDeclaration
2189 // -------------------------------------------
2190 // nsCSSKeyframesRule
2193 nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
2194 // copy everything except our reference count. GroupRule's copy
2195 // constructor also doesn't copy the lazily-constructed
2196 // mRuleCollection.
2197 : GroupRule(aCopy),
2198 mName(aCopy.mName)
2202 nsCSSKeyframesRule::~nsCSSKeyframesRule()
2206 /* virtual */ already_AddRefed<css::Rule>
2207 nsCSSKeyframesRule::Clone() const
2209 nsRefPtr<css::Rule> clone = new nsCSSKeyframesRule(*this);
2210 return clone.forget();
2213 NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, css::GroupRule)
2214 NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, css::GroupRule)
2216 DOMCI_DATA(MozCSSKeyframesRule, nsCSSKeyframesRule)
2218 // QueryInterface implementation for nsCSSKeyframesRule
2219 NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule)
2220 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2221 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2222 NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
2223 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2224 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframesRule)
2225 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
2227 #ifdef DEBUG
2228 void
2229 nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const
2231 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2233 fprintf(out, "@keyframes %s", NS_ConvertUTF16toUTF8(mName).get());
2234 GroupRule::List(out, aIndent);
2236 #endif
2238 /* virtual */ int32_t
2239 nsCSSKeyframesRule::GetType() const
2241 return Rule::KEYFRAMES_RULE;
2244 NS_IMETHODIMP
2245 nsCSSKeyframesRule::GetType(uint16_t* aType)
2247 *aType = nsIDOMCSSRule::KEYFRAMES_RULE;
2248 return NS_OK;
2251 NS_IMETHODIMP
2252 nsCSSKeyframesRule::GetCssText(nsAString& aCssText)
2254 aCssText.AssignLiteral("@keyframes ");
2255 aCssText.Append(mName);
2256 aCssText.AppendLiteral(" {\n");
2257 nsAutoString tmp;
2258 for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) {
2259 static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp);
2260 aCssText.Append(tmp);
2261 aCssText.AppendLiteral("\n");
2263 aCssText.AppendLiteral("}");
2264 return NS_OK;
2267 NS_IMETHODIMP
2268 nsCSSKeyframesRule::SetCssText(const nsAString& aCssText)
2270 // FIXME: implement???
2271 return NS_ERROR_NOT_IMPLEMENTED;
2274 NS_IMETHODIMP
2275 nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2277 return GroupRule::GetParentStyleSheet(aSheet);
2280 NS_IMETHODIMP
2281 nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2283 return GroupRule::GetParentRule(aParentRule);
2286 NS_IMETHODIMP
2287 nsCSSKeyframesRule::GetName(nsAString& aName)
2289 aName = mName;
2290 return NS_OK;
2293 NS_IMETHODIMP
2294 nsCSSKeyframesRule::SetName(const nsAString& aName)
2296 mName = aName;
2298 nsCSSStyleSheet* sheet = GetStyleSheet();
2299 if (sheet) {
2300 sheet->SetModifiedByChildRule();
2303 return NS_OK;
2306 NS_IMETHODIMP
2307 nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
2309 return GroupRule::GetCssRules(aRuleList);
2312 NS_IMETHODIMP
2313 nsCSSKeyframesRule::AppendRule(const nsAString& aRule)
2315 // The spec is confusing, and I think we should just append the rule,
2316 // which also turns out to match WebKit:
2317 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
2318 nsCSSParser parser;
2320 // FIXME: pass filename and line number
2321 nsRefPtr<nsCSSKeyframeRule> rule =
2322 parser.ParseKeyframeRule(aRule, nullptr, 0);
2323 if (rule) {
2324 AppendStyleRule(rule);
2327 return NS_OK;
2330 static const uint32_t RULE_NOT_FOUND = uint32_t(-1);
2332 uint32_t
2333 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
2335 nsCSSParser parser;
2337 InfallibleTArray<float> keys;
2338 // FIXME: pass filename and line number
2339 if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
2340 // The spec isn't clear, but we'll match on the key list, which
2341 // mostly matches what WebKit does, except we'll do last-match
2342 // instead of first-match, and handling parsing differences better.
2343 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
2344 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
2345 for (uint32_t i = mRules.Count(); i-- != 0; ) {
2346 if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) {
2347 return i;
2352 return RULE_NOT_FOUND;
2355 NS_IMETHODIMP
2356 nsCSSKeyframesRule::DeleteRule(const nsAString& aKey)
2358 uint32_t index = FindRuleIndexForKey(aKey);
2359 if (index != RULE_NOT_FOUND) {
2360 mRules.RemoveObjectAt(index);
2361 nsCSSStyleSheet* sheet = GetStyleSheet();
2362 if (sheet) {
2363 sheet->SetModifiedByChildRule();
2366 return NS_OK;
2369 NS_IMETHODIMP
2370 nsCSSKeyframesRule::FindRule(const nsAString& aKey,
2371 nsIDOMMozCSSKeyframeRule** aResult)
2373 uint32_t index = FindRuleIndexForKey(aKey);
2374 if (index == RULE_NOT_FOUND) {
2375 *aResult = nullptr;
2376 } else {
2377 NS_ADDREF(*aResult = static_cast<nsCSSKeyframeRule*>(mRules[index]));
2379 return NS_OK;
2382 // GroupRule interface
2383 /* virtual */ bool
2384 nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
2385 nsMediaQueryResultCacheKey& aKey)
2387 NS_ABORT_IF_FALSE(false, "should not be called");
2388 return false;
2391 /* virtual */ size_t
2392 nsCSSKeyframesRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
2394 size_t n = aMallocSizeOf(this);
2395 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
2397 // Measurement of the following members may be added later if DMD finds it is
2398 // worthwhile:
2399 // - mName
2401 return n;
2404 // -------------------------------------------
2405 // nsCSSPageStyleDeclaration
2408 nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
2409 : mRule(aRule)
2413 nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
2415 NS_ASSERTION(!mRule, "DropReference not called.");
2418 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
2419 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
2421 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
2423 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
2424 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
2425 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
2427 css::Declaration*
2428 nsCSSPageStyleDeclaration::GetCSSDeclaration(bool aAllocate)
2430 if (mRule) {
2431 return mRule->Declaration();
2432 } else {
2433 return nullptr;
2437 void
2438 nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
2440 GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
2443 NS_IMETHODIMP
2444 nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
2446 NS_ENSURE_ARG_POINTER(aParent);
2448 NS_IF_ADDREF(*aParent = mRule);
2449 return NS_OK;
2452 nsresult
2453 nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
2455 NS_ABORT_IF_FALSE(aDecl, "must be non-null");
2456 mRule->ChangeDeclaration(aDecl);
2457 return NS_OK;
2460 nsIDocument*
2461 nsCSSPageStyleDeclaration::DocToUpdate()
2463 return nullptr;
2466 nsINode*
2467 nsCSSPageStyleDeclaration::GetParentObject()
2469 return mRule ? mRule->GetDocument() : nullptr;
2472 // -------------------------------------------
2473 // nsCSSPageRule
2476 nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
2477 // copy everything except our reference count and mDOMDeclaration
2478 : Rule(aCopy)
2479 , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
2483 nsCSSPageRule::~nsCSSPageRule()
2485 if (mDOMDeclaration) {
2486 mDOMDeclaration->DropReference();
2490 /* virtual */ already_AddRefed<css::Rule>
2491 nsCSSPageRule::Clone() const
2493 nsRefPtr<css::Rule> clone = new nsCSSPageRule(*this);
2494 return clone.forget();
2497 NS_IMPL_ADDREF(nsCSSPageRule)
2498 NS_IMPL_RELEASE(nsCSSPageRule)
2500 DOMCI_DATA(CSSPageRule, nsCSSPageRule)
2502 // QueryInterface implementation for nsCSSPageRule
2503 NS_INTERFACE_MAP_BEGIN(nsCSSPageRule)
2504 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2505 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule)
2506 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2507 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2508 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule)
2509 NS_INTERFACE_MAP_END
2511 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule)
2513 #ifdef DEBUG
2514 void
2515 nsCSSPageRule::List(FILE* out, int32_t aIndent) const
2517 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2519 fputs("@page ", out);
2520 mDeclaration->List(out, aIndent);
2521 fputs("\n", out);
2523 #endif
2525 /* virtual */ int32_t
2526 nsCSSPageRule::GetType() const
2528 return Rule::PAGE_RULE;
2531 NS_IMETHODIMP
2532 nsCSSPageRule::GetType(uint16_t* aType)
2534 *aType = nsIDOMCSSRule::PAGE_RULE;
2535 return NS_OK;
2538 NS_IMETHODIMP
2539 nsCSSPageRule::GetCssText(nsAString& aCssText)
2541 aCssText.AppendLiteral("@page { ");
2542 nsAutoString tmp;
2543 mDeclaration->ToString(tmp);
2544 aCssText.Append(tmp);
2545 aCssText.AppendLiteral(" }");
2546 return NS_OK;
2549 NS_IMETHODIMP
2550 nsCSSPageRule::SetCssText(const nsAString& aCssText)
2552 // FIXME: implement???
2553 return NS_ERROR_NOT_IMPLEMENTED;
2556 NS_IMETHODIMP
2557 nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2559 return Rule::GetParentStyleSheet(aSheet);
2562 NS_IMETHODIMP
2563 nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2565 return Rule::GetParentRule(aParentRule);
2568 css::ImportantRule*
2569 nsCSSPageRule::GetImportantRule()
2571 if (!mDeclaration->HasImportantData()) {
2572 return nullptr;
2574 if (!mImportantRule) {
2575 mImportantRule = new css::ImportantRule(mDeclaration);
2577 return mImportantRule;
2580 /* virtual */ void
2581 nsCSSPageRule::MapRuleInfoInto(nsRuleData* aRuleData)
2583 mDeclaration->MapNormalRuleInfoInto(aRuleData);
2586 NS_IMETHODIMP
2587 nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
2589 if (!mDOMDeclaration) {
2590 mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
2592 NS_ADDREF(*aStyle = mDOMDeclaration);
2593 return NS_OK;
2596 void
2597 nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
2599 mImportantRule = nullptr;
2600 // Be careful to not assign to an nsAutoPtr if we would be assigning
2601 // the thing it already holds.
2602 if (aDeclaration != mDeclaration) {
2603 mDeclaration = aDeclaration;
2606 nsCSSStyleSheet* sheet = GetStyleSheet();
2607 if (sheet) {
2608 sheet->SetModifiedByChildRule();
2612 /* virtual */ size_t
2613 nsCSSPageRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
2615 return aMallocSizeOf(this);
2618 namespace mozilla {
2620 CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
2621 const nsString& aCondition)
2622 : mUseGroup(aConditionMet),
2623 mCondition(aCondition)
2627 CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
2628 : css::GroupRule(aCopy),
2629 mUseGroup(aCopy.mUseGroup),
2630 mCondition(aCopy.mCondition)
2634 #ifdef DEBUG
2635 /* virtual */ void
2636 CSSSupportsRule::List(FILE* out, int32_t aIndent) const
2638 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2640 fputs("@supports ", out);
2641 fputs(NS_ConvertUTF16toUTF8(mCondition).get(), out);
2642 css::GroupRule::List(out, aIndent);
2644 #endif
2646 /* virtual */ int32_t
2647 CSSSupportsRule::GetType() const
2649 return Rule::SUPPORTS_RULE;
2652 /* virtual */ already_AddRefed<mozilla::css::Rule>
2653 CSSSupportsRule::Clone() const
2655 nsRefPtr<css::Rule> clone = new CSSSupportsRule(*this);
2656 return clone.forget();
2659 /* virtual */ bool
2660 CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
2661 nsMediaQueryResultCacheKey& aKey)
2663 return mUseGroup;
2666 NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule)
2667 NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule)
2669 // QueryInterface implementation for CSSSupportsRule
2670 NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
2671 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2672 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2673 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
2674 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
2675 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
2676 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2677 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule)
2678 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
2680 // nsIDOMCSSRule methods
2681 NS_IMETHODIMP
2682 CSSSupportsRule::GetType(uint16_t* aType)
2684 *aType = nsIDOMCSSRule::SUPPORTS_RULE;
2685 return NS_OK;
2688 NS_IMETHODIMP
2689 CSSSupportsRule::GetCssText(nsAString& aCssText)
2691 aCssText.AssignLiteral("@supports ");
2692 aCssText.Append(mCondition);
2693 return css::GroupRule::AppendRulesToCssText(aCssText);
2696 NS_IMETHODIMP
2697 CSSSupportsRule::SetCssText(const nsAString& aCssText)
2699 return NS_ERROR_NOT_IMPLEMENTED;
2702 NS_IMETHODIMP
2703 CSSSupportsRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2705 return css::GroupRule::GetParentStyleSheet(aSheet);
2708 NS_IMETHODIMP
2709 CSSSupportsRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2711 return css::GroupRule::GetParentRule(aParentRule);
2714 // nsIDOMCSSGroupingRule methods
2715 NS_IMETHODIMP
2716 CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
2718 return css::GroupRule::GetCssRules(aRuleList);
2721 NS_IMETHODIMP
2722 CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
2724 return css::GroupRule::InsertRule(aRule, aIndex, _retval);
2727 NS_IMETHODIMP
2728 CSSSupportsRule::DeleteRule(uint32_t aIndex)
2730 return css::GroupRule::DeleteRule(aIndex);
2733 // nsIDOMCSSConditionRule methods
2734 NS_IMETHODIMP
2735 CSSSupportsRule::GetConditionText(nsAString& aConditionText)
2737 aConditionText.Assign(mCondition);
2738 return NS_OK;
2741 NS_IMETHODIMP
2742 CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
2744 return NS_ERROR_NOT_IMPLEMENTED;
2747 /* virtual */ size_t
2748 CSSSupportsRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
2750 size_t n = aMallocSizeOf(this);
2751 n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
2752 n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
2753 return n;
2756 } // namespace mozilla
2758 // Must be outside namespace
2759 DOMCI_DATA(CSSSupportsRule, mozilla::CSSSupportsRule)