michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: #include "nsCSSRules.h" michael@0: #include "nsCSSValue.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "mozilla/css/ImportRule.h" michael@0: #include "mozilla/css/NameSpaceRule.h" michael@0: michael@0: #include "nsString.h" michael@0: #include "nsIAtom.h" michael@0: michael@0: #include "nsCSSProps.h" michael@0: #include "nsCSSStyleSheet.h" michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIDOMCSSStyleSheet.h" michael@0: #include "nsIMediaList.h" michael@0: #include "nsICSSRuleList.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsPresContext.h" michael@0: michael@0: #include "nsContentUtils.h" michael@0: #include "nsError.h" michael@0: #include "nsStyleUtil.h" michael@0: #include "mozilla/css/Declaration.h" michael@0: #include "nsCSSParser.h" michael@0: #include "nsPrintfCString.h" michael@0: #include "nsDOMClassInfoID.h" michael@0: #include "mozilla/dom/CSSStyleDeclarationBinding.h" michael@0: #include "StyleRule.h" michael@0: #include "nsFont.h" michael@0: #include "nsIURI.h" michael@0: #include "mozAutoDocUpdate.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \ michael@0: /* virtual */ nsIDOMCSSRule* class_::GetDOMRule() \ michael@0: { return this; } \ michael@0: /* virtual */ nsIDOMCSSRule* class_::GetExistingDOMRule() \ michael@0: { return this; } michael@0: #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \ michael@0: /* virtual */ void class_::MapRuleInfoInto(nsRuleData* aRuleData) \ michael@0: { NS_ABORT_IF_FALSE(false, "should not be called"); } michael@0: michael@0: #define IMPL_STYLE_RULE_INHERIT(class_, super_) \ michael@0: IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \ michael@0: IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) michael@0: michael@0: // base class for all rule types in a CSS style sheet michael@0: michael@0: namespace mozilla { michael@0: namespace css { michael@0: michael@0: nsCSSStyleSheet* michael@0: Rule::GetStyleSheet() const michael@0: { michael@0: if (!(mSheet & 0x1)) { michael@0: return reinterpret_cast(mSheet); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: nsHTMLCSSStyleSheet* michael@0: Rule::GetHTMLCSSStyleSheet() const michael@0: { michael@0: if (mSheet & 0x1) { michael@0: return reinterpret_cast(mSheet & ~uintptr_t(0x1)); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: /* virtual */ void michael@0: Rule::SetStyleSheet(nsCSSStyleSheet* aSheet) michael@0: { michael@0: // We don't reference count this up reference. The style sheet michael@0: // will tell us when it's going away or when we're detached from michael@0: // it. michael@0: mSheet = reinterpret_cast(aSheet); michael@0: } michael@0: michael@0: void michael@0: Rule::SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet) michael@0: { michael@0: // We don't reference count this up reference. The style sheet michael@0: // will tell us when it's going away or when we're detached from michael@0: // it. michael@0: mSheet = reinterpret_cast(aSheet); michael@0: mSheet |= 0x1; michael@0: } michael@0: michael@0: nsresult michael@0: Rule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: if (mParentRule) { michael@0: NS_IF_ADDREF(*aParentRule = mParentRule->GetDOMRule()); michael@0: } else { michael@0: *aParentRule = nullptr; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aSheet); michael@0: michael@0: NS_IF_ADDREF(*aSheet = GetStyleSheet()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: size_t michael@0: Rule::SizeOfCOMArrayElementIncludingThis(css::Rule* aElement, michael@0: MallocSizeOf aMallocSizeOf, michael@0: void* aData) michael@0: { michael@0: return aElement->SizeOfIncludingThis(aMallocSizeOf); michael@0: } michael@0: michael@0: // ------------------------------- michael@0: // Style Rule List for group rules michael@0: // michael@0: michael@0: class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList michael@0: { michael@0: public: michael@0: GroupRuleRuleList(GroupRule *aGroupRule); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: virtual nsIDOMCSSRule* michael@0: IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE; michael@0: virtual uint32_t michael@0: Length() MOZ_OVERRIDE; michael@0: michael@0: void DropReference() { mGroupRule = nullptr; } michael@0: michael@0: private: michael@0: ~GroupRuleRuleList(); michael@0: michael@0: private: michael@0: GroupRule* mGroupRule; michael@0: }; michael@0: michael@0: GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule) michael@0: { michael@0: // Not reference counted to avoid circular references. michael@0: // The rule will tell us when its going away. michael@0: mGroupRule = aGroupRule; michael@0: } michael@0: michael@0: GroupRuleRuleList::~GroupRuleRuleList() michael@0: { michael@0: } michael@0: michael@0: // QueryInterface implementation for GroupRuleRuleList michael@0: NS_INTERFACE_MAP_BEGIN(GroupRuleRuleList) michael@0: NS_INTERFACE_MAP_ENTRY(nsICSSRuleList) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: michael@0: NS_IMPL_ADDREF(GroupRuleRuleList) michael@0: NS_IMPL_RELEASE(GroupRuleRuleList) michael@0: michael@0: uint32_t michael@0: GroupRuleRuleList::Length() michael@0: { michael@0: if (!mGroupRule) { michael@0: return 0; michael@0: } michael@0: michael@0: return SafeCast(mGroupRule->StyleRuleCount()); michael@0: } michael@0: michael@0: nsIDOMCSSRule* michael@0: GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound) michael@0: { michael@0: aFound = false; michael@0: michael@0: if (mGroupRule) { michael@0: nsRefPtr rule = mGroupRule->GetStyleRuleAt(aIndex); michael@0: if (rule) { michael@0: aFound = true; michael@0: return rule->GetDOMRule(); michael@0: } michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: } // namespace css michael@0: } // namespace mozilla michael@0: michael@0: // ------------------------------------------- michael@0: // CharsetRule michael@0: // michael@0: michael@0: // Must be outside namespace michael@0: DOMCI_DATA(CSSCharsetRule, css::CharsetRule) michael@0: michael@0: namespace mozilla { michael@0: namespace css { michael@0: michael@0: CharsetRule::CharsetRule(const nsAString& aEncoding) michael@0: : Rule(), michael@0: mEncoding(aEncoding) michael@0: { michael@0: } michael@0: michael@0: CharsetRule::CharsetRule(const CharsetRule& aCopy) michael@0: : Rule(aCopy), michael@0: mEncoding(aCopy.mEncoding) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(CharsetRule) michael@0: NS_IMPL_RELEASE(CharsetRule) michael@0: michael@0: // QueryInterface implementation for CharsetRule michael@0: NS_INTERFACE_MAP_BEGIN(CharsetRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCharsetRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT(CharsetRule, Rule) michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: CharsetRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: // Indent michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: fputs("@charset \"", out); michael@0: fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out); michael@0: fputs("\"\n", out); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: CharsetRule::GetType() const michael@0: { michael@0: return Rule::CHARSET_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: CharsetRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new CharsetRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::GetEncoding(nsAString& aEncoding) michael@0: { michael@0: aEncoding = mEncoding; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::SetEncoding(const nsAString& aEncoding) michael@0: { michael@0: mEncoding = aEncoding; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::CHARSET_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@charset \""); michael@0: aCssText.Append(mEncoding); michael@0: aCssText.AppendLiteral("\";"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CharsetRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: CharsetRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mEncoding michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // ImportRule michael@0: // michael@0: michael@0: ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec) michael@0: : Rule() michael@0: , mURLSpec(aURLSpec) michael@0: , mMedia(aMedia) michael@0: { michael@0: // XXXbz This is really silly.... the mMedia here will be replaced michael@0: // with itself if we manage to load a sheet. Which should really michael@0: // never fail nowadays, in sane cases. michael@0: } michael@0: michael@0: ImportRule::ImportRule(const ImportRule& aCopy) michael@0: : Rule(aCopy), michael@0: mURLSpec(aCopy.mURLSpec) michael@0: { michael@0: // Whether or not an @import rule has a null sheet is a permanent michael@0: // property of that @import rule, since it is null only if the target michael@0: // sheet failed security checks. michael@0: if (aCopy.mChildSheet) { michael@0: nsRefPtr sheet = michael@0: aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr); michael@0: SetSheet(sheet); michael@0: // SetSheet sets mMedia appropriately michael@0: } michael@0: } michael@0: michael@0: ImportRule::~ImportRule() michael@0: { michael@0: if (mChildSheet) { michael@0: mChildSheet->SetOwnerRule(nullptr); michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(ImportRule) michael@0: NS_IMPL_RELEASE(ImportRule) michael@0: michael@0: // QueryInterface implementation for ImportRule michael@0: NS_INTERFACE_MAP_BEGIN(ImportRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT(ImportRule, Rule) michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: ImportRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: // Indent michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: fputs("@import \"", out); michael@0: fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out); michael@0: fputs("\" ", out); michael@0: michael@0: nsAutoString mediaText; michael@0: mMedia->GetText(mediaText); michael@0: fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out); michael@0: fputs("\n", out); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: ImportRule::GetType() const michael@0: { michael@0: return Rule::IMPORT_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: ImportRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new ImportRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: void michael@0: ImportRule::SetSheet(nsCSSStyleSheet* aSheet) michael@0: { michael@0: NS_PRECONDITION(aSheet, "null arg"); michael@0: michael@0: // set the new sheet michael@0: mChildSheet = aSheet; michael@0: aSheet->SetOwnerRule(this); michael@0: michael@0: // set our medialist to be the same as the sheet's medialist michael@0: mMedia = mChildSheet->Media(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetType(uint16_t* aType) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aType); michael@0: *aType = nsIDOMCSSRule::IMPORT_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@import url("); michael@0: nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText); michael@0: aCssText.Append(NS_LITERAL_STRING(")")); michael@0: if (mMedia) { michael@0: nsAutoString mediaText; michael@0: mMedia->GetText(mediaText); michael@0: if (!mediaText.IsEmpty()) { michael@0: aCssText.AppendLiteral(" "); michael@0: aCssText.Append(mediaText); michael@0: } michael@0: } michael@0: aCssText.AppendLiteral(";"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetHref(nsAString & aHref) michael@0: { michael@0: aHref = mURLSpec; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetMedia(nsIDOMMediaList * *aMedia) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aMedia); michael@0: michael@0: NS_IF_ADDREF(*aMedia = mMedia); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aStyleSheet); michael@0: michael@0: NS_IF_ADDREF(*aStyleSheet = mChildSheet); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mURLSpec michael@0: // michael@0: // The following members are not measured: michael@0: // - mMedia, because it is measured via nsCSSStyleSheet::mMedia michael@0: // - mChildSheet, because it is measured via nsCSSStyleSheetInner::mSheets michael@0: } michael@0: michael@0: } // namespace css michael@0: } // namespace mozilla michael@0: michael@0: // must be outside the namespace michael@0: DOMCI_DATA(CSSImportRule, css::ImportRule) michael@0: michael@0: namespace mozilla { michael@0: namespace css { michael@0: michael@0: GroupRule::GroupRule() michael@0: : Rule() michael@0: { michael@0: } michael@0: michael@0: static bool michael@0: SetParentRuleReference(Rule* aRule, void* aParentRule) michael@0: { michael@0: GroupRule* parentRule = static_cast(aParentRule); michael@0: aRule->SetParentRule(parentRule); michael@0: return true; michael@0: } michael@0: michael@0: GroupRule::GroupRule(const GroupRule& aCopy) michael@0: : Rule(aCopy) michael@0: { michael@0: const_cast(aCopy).mRules.EnumerateForwards(GroupRule::CloneRuleInto, &mRules); michael@0: mRules.EnumerateForwards(SetParentRuleReference, this); michael@0: } michael@0: michael@0: GroupRule::~GroupRule() michael@0: { michael@0: NS_ABORT_IF_FALSE(!mSheet, "SetStyleSheet should have been called"); michael@0: mRules.EnumerateForwards(SetParentRuleReference, nullptr); michael@0: if (mRuleCollection) { michael@0: mRuleCollection->DropReference(); michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupRule) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupRule) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(GroupRule, Rule) michael@0: michael@0: static bool michael@0: SetStyleSheetReference(Rule* aRule, void* aSheet) michael@0: { michael@0: nsCSSStyleSheet* sheet = (nsCSSStyleSheet*)aSheet; michael@0: aRule->SetStyleSheet(sheet); michael@0: return true; michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupRule) michael@0: tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr); michael@0: // If tmp does not have a stylesheet, neither do its descendants. In that michael@0: // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in michael@0: // depth of group rule nesting. But if tmp _does_ have a stylesheet (which michael@0: // can happen if it gets unlinked earlier than its owning stylesheet), then we michael@0: // need to null out the stylesheet pointer on descendants now, before we clear michael@0: // tmp->mRules. michael@0: if (tmp->GetStyleSheet()) { michael@0: tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr); michael@0: } michael@0: tmp->mRules.Clear(); michael@0: if (tmp->mRuleCollection) { michael@0: tmp->mRuleCollection->DropReference(); michael@0: tmp->mRuleCollection = nullptr; michael@0: } michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupRule) michael@0: const nsCOMArray& rules = tmp->mRules; michael@0: for (int32_t i = 0, count = rules.Count(); i < count; ++i) { michael@0: NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]"); michael@0: cb.NoteXPCOMChild(rules[i]->GetExistingDOMRule()); michael@0: } michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: /* virtual */ void michael@0: GroupRule::SetStyleSheet(nsCSSStyleSheet* aSheet) michael@0: { michael@0: // Don't set the sheet on the kids if it's already the same as the sheet we michael@0: // already have. This is needed to avoid O(N^2) behavior in group nesting michael@0: // depth when seting the sheet to null during unlink, if we happen to unlin in michael@0: // order from most nested rule up to least nested rule. michael@0: if (aSheet != GetStyleSheet()) { michael@0: mRules.EnumerateForwards(SetStyleSheetReference, aSheet); michael@0: Rule::SetStyleSheet(aSheet); michael@0: } michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: GroupRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: fputs(" {\n", out); michael@0: michael@0: for (int32_t index = 0, count = mRules.Count(); index < count; ++index) { michael@0: mRules.ObjectAt(index)->List(out, aIndent + 1); michael@0: } michael@0: michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: fputs("}\n", out); michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: GroupRule::AppendStyleRule(Rule* aRule) michael@0: { michael@0: mRules.AppendObject(aRule); michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: aRule->SetStyleSheet(sheet); michael@0: aRule->SetParentRule(this); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: } michael@0: } michael@0: michael@0: Rule* michael@0: GroupRule::GetStyleRuleAt(int32_t aIndex) const michael@0: { michael@0: return mRules.SafeObjectAt(aIndex); michael@0: } michael@0: michael@0: bool michael@0: GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const michael@0: { michael@0: return michael@0: const_cast(this)->mRules.EnumerateForwards(aFunc, aData); michael@0: } michael@0: michael@0: /* michael@0: * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt) michael@0: * should never be called unless you have first called WillDirty() on michael@0: * the parents stylesheet. After they are called, DidDirty() needs to michael@0: * be called on the sheet michael@0: */ michael@0: nsresult michael@0: GroupRule::DeleteStyleRuleAt(uint32_t aIndex) michael@0: { michael@0: Rule* rule = mRules.SafeObjectAt(aIndex); michael@0: if (rule) { michael@0: rule->SetStyleSheet(nullptr); michael@0: rule->SetParentRule(nullptr); michael@0: } michael@0: return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE; michael@0: } michael@0: michael@0: nsresult michael@0: GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule) michael@0: { michael@0: aRule->SetStyleSheet(GetStyleSheet()); michael@0: aRule->SetParentRule(this); michael@0: if (! mRules.InsertObjectAt(aRule, aIndex)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: GroupRule::ReplaceStyleRule(Rule* aOld, Rule* aNew) michael@0: { michael@0: int32_t index = mRules.IndexOf(aOld); michael@0: NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); michael@0: mRules.ReplaceObjectAt(aNew, index); michael@0: aNew->SetStyleSheet(GetStyleSheet()); michael@0: aNew->SetParentRule(this); michael@0: aOld->SetStyleSheet(nullptr); michael@0: aOld->SetParentRule(nullptr); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: GroupRule::AppendRulesToCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AppendLiteral(" {\n"); michael@0: michael@0: // get all the rules michael@0: for (int32_t index = 0, count = mRules.Count(); index < count; ++index) { michael@0: Rule* rule = mRules.ObjectAt(index); michael@0: nsIDOMCSSRule* domRule = rule->GetDOMRule(); michael@0: if (domRule) { michael@0: nsAutoString cssText; michael@0: domRule->GetCssText(cssText); michael@0: aCssText.Append(NS_LITERAL_STRING(" ") + michael@0: cssText + michael@0: NS_LITERAL_STRING("\n")); michael@0: } michael@0: } michael@0: michael@0: aCssText.AppendLiteral("}"); michael@0: } michael@0: michael@0: // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods michael@0: nsresult michael@0: GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) michael@0: { michael@0: if (!mRuleCollection) { michael@0: mRuleCollection = new css::GroupRuleRuleList(this); michael@0: } michael@0: michael@0: NS_ADDREF(*aRuleList = mRuleCollection); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval) michael@0: { michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE); michael@0: michael@0: if (aIndex > uint32_t(mRules.Count())) michael@0: return NS_ERROR_DOM_INDEX_SIZE_ERR; michael@0: michael@0: NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX, michael@0: "Too many style rules!"); michael@0: michael@0: return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); michael@0: } michael@0: michael@0: nsresult michael@0: GroupRule::DeleteRule(uint32_t aIndex) michael@0: { michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE); michael@0: michael@0: if (aIndex >= uint32_t(mRules.Count())) michael@0: return NS_ERROR_DOM_INDEX_SIZE_ERR; michael@0: michael@0: NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX, michael@0: "Too many style rules!"); michael@0: michael@0: return sheet->DeleteRuleFromGroup(this, aIndex); michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return mRules.SizeOfExcludingThis(Rule::SizeOfCOMArrayElementIncludingThis, michael@0: aMallocSizeOf); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mRuleCollection michael@0: } michael@0: michael@0: michael@0: // ------------------------------------------- michael@0: // nsICSSMediaRule michael@0: // michael@0: MediaRule::MediaRule() michael@0: { michael@0: } michael@0: michael@0: MediaRule::MediaRule(const MediaRule& aCopy) michael@0: : GroupRule(aCopy) michael@0: { michael@0: if (aCopy.mMedia) { michael@0: mMedia = aCopy.mMedia->Clone(); michael@0: // XXXldb This doesn't really make sense. michael@0: mMedia->SetStyleSheet(aCopy.GetStyleSheet()); michael@0: } michael@0: } michael@0: michael@0: MediaRule::~MediaRule() michael@0: { michael@0: if (mMedia) { michael@0: mMedia->SetStyleSheet(nullptr); michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule) michael@0: NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule) michael@0: michael@0: // QueryInterface implementation for MediaRule michael@0: NS_INTERFACE_MAP_BEGIN(MediaRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule) michael@0: NS_INTERFACE_MAP_END_INHERITING(GroupRule) michael@0: michael@0: /* virtual */ void michael@0: MediaRule::SetStyleSheet(nsCSSStyleSheet* aSheet) michael@0: { michael@0: if (mMedia) { michael@0: // Set to null so it knows it's leaving one sheet and joining another. michael@0: mMedia->SetStyleSheet(nullptr); michael@0: mMedia->SetStyleSheet(aSheet); michael@0: } michael@0: michael@0: GroupRule::SetStyleSheet(aSheet); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: MediaRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: nsAutoString buffer; michael@0: michael@0: fputs("@media ", out); michael@0: michael@0: if (mMedia) { michael@0: nsAutoString mediaText; michael@0: mMedia->GetText(mediaText); michael@0: fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out); michael@0: } michael@0: michael@0: GroupRule::List(out, aIndent); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: MediaRule::GetType() const michael@0: { michael@0: return Rule::MEDIA_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: MediaRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new MediaRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: nsresult michael@0: MediaRule::SetMedia(nsMediaList* aMedia) michael@0: { michael@0: mMedia = aMedia; michael@0: if (aMedia) michael@0: mMedia->SetStyleSheet(GetStyleSheet()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsIDOMCSSRule methods michael@0: NS_IMETHODIMP michael@0: MediaRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::MEDIA_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@media "); michael@0: AppendConditionText(aCssText); michael@0: GroupRule::AppendRulesToCssText(aCssText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return GroupRule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return GroupRule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: // nsIDOMCSSGroupingRule methods michael@0: NS_IMETHODIMP michael@0: MediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) michael@0: { michael@0: return GroupRule::GetCssRules(aRuleList); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval) michael@0: { michael@0: return GroupRule::InsertRule(aRule, aIndex, _retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::DeleteRule(uint32_t aIndex) michael@0: { michael@0: return GroupRule::DeleteRule(aIndex); michael@0: } michael@0: michael@0: // nsIDOMCSSConditionRule methods michael@0: NS_IMETHODIMP michael@0: MediaRule::GetConditionText(nsAString& aConditionText) michael@0: { michael@0: aConditionText.Truncate(0); michael@0: AppendConditionText(aConditionText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: MediaRule::SetConditionText(const nsAString& aConditionText) michael@0: { michael@0: if (!mMedia) { michael@0: nsRefPtr media = new nsMediaList(); michael@0: media->SetStyleSheet(GetStyleSheet()); michael@0: nsresult rv = media->SetMediaText(aConditionText); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: mMedia = media; michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: return mMedia->SetMediaText(aConditionText); michael@0: } michael@0: michael@0: // nsIDOMCSSMediaRule methods michael@0: NS_IMETHODIMP michael@0: MediaRule::GetMedia(nsIDOMMediaList* *aMedia) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aMedia); michael@0: NS_IF_ADDREF(*aMedia = mMedia); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // GroupRule interface michael@0: /* virtual */ bool michael@0: MediaRule::UseForPresentation(nsPresContext* aPresContext, michael@0: nsMediaQueryResultCacheKey& aKey) michael@0: { michael@0: if (mMedia) { michael@0: return mMedia->Matches(aPresContext, &aKey); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: size_t n = aMallocSizeOf(this); michael@0: n += GroupRule::SizeOfExcludingThis(aMallocSizeOf); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mMedia michael@0: michael@0: return n; michael@0: } michael@0: michael@0: void michael@0: MediaRule::AppendConditionText(nsAString& aOutput) michael@0: { michael@0: if (mMedia) { michael@0: nsAutoString mediaText; michael@0: mMedia->GetText(mediaText); michael@0: aOutput.Append(mediaText); michael@0: } michael@0: } michael@0: michael@0: } // namespace css michael@0: } // namespace mozilla michael@0: michael@0: // Must be outside namespace michael@0: DOMCI_DATA(CSSMediaRule, css::MediaRule) michael@0: michael@0: namespace mozilla { michael@0: namespace css { michael@0: michael@0: DocumentRule::DocumentRule() michael@0: { michael@0: } michael@0: michael@0: DocumentRule::DocumentRule(const DocumentRule& aCopy) michael@0: : GroupRule(aCopy) michael@0: , mURLs(new URL(*aCopy.mURLs)) michael@0: { michael@0: } michael@0: michael@0: DocumentRule::~DocumentRule() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule) michael@0: NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule) michael@0: michael@0: // QueryInterface implementation for DocumentRule michael@0: NS_INTERFACE_MAP_BEGIN(DocumentRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule) michael@0: NS_INTERFACE_MAP_END_INHERITING(GroupRule) michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: DocumentRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: nsAutoCString str; michael@0: str.AssignLiteral("@-moz-document "); michael@0: for (URL *url = mURLs; url; url = url->next) { michael@0: switch (url->func) { michael@0: case eURL: michael@0: str.AppendLiteral("url(\""); michael@0: break; michael@0: case eURLPrefix: michael@0: str.AppendLiteral("url-prefix(\""); michael@0: break; michael@0: case eDomain: michael@0: str.AppendLiteral("domain(\""); michael@0: break; michael@0: case eRegExp: michael@0: str.AppendLiteral("regexp(\""); michael@0: break; michael@0: } michael@0: nsAutoCString escapedURL(url->url); michael@0: escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes michael@0: str.Append(escapedURL); michael@0: str.AppendLiteral("\"), "); michael@0: } michael@0: str.Cut(str.Length() - 2, 1); // remove last , michael@0: fputs(str.get(), out); michael@0: michael@0: GroupRule::List(out, aIndent); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: DocumentRule::GetType() const michael@0: { michael@0: return Rule::DOCUMENT_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: DocumentRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new DocumentRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: // nsIDOMCSSRule methods michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetType(uint16_t* aType) michael@0: { michael@0: // XXX What should really happen here? michael@0: *aType = nsIDOMCSSRule::UNKNOWN_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@-moz-document "); michael@0: AppendConditionText(aCssText); michael@0: GroupRule::AppendRulesToCssText(aCssText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return GroupRule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return GroupRule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: // nsIDOMCSSGroupingRule methods michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) michael@0: { michael@0: return GroupRule::GetCssRules(aRuleList); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval) michael@0: { michael@0: return GroupRule::InsertRule(aRule, aIndex, _retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::DeleteRule(uint32_t aIndex) michael@0: { michael@0: return GroupRule::DeleteRule(aIndex); michael@0: } michael@0: michael@0: // nsIDOMCSSConditionRule methods michael@0: NS_IMETHODIMP michael@0: DocumentRule::GetConditionText(nsAString& aConditionText) michael@0: { michael@0: aConditionText.Truncate(0); michael@0: AppendConditionText(aConditionText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DocumentRule::SetConditionText(const nsAString& aConditionText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: // GroupRule interface michael@0: /* virtual */ bool michael@0: DocumentRule::UseForPresentation(nsPresContext* aPresContext, michael@0: nsMediaQueryResultCacheKey& aKey) michael@0: { michael@0: nsIDocument *doc = aPresContext->Document(); michael@0: nsIURI *docURI = doc->GetDocumentURI(); michael@0: nsAutoCString docURISpec; michael@0: if (docURI) michael@0: docURI->GetSpec(docURISpec); michael@0: michael@0: for (URL *url = mURLs; url; url = url->next) { michael@0: switch (url->func) { michael@0: case eURL: { michael@0: if (docURISpec == url->url) michael@0: return true; michael@0: } break; michael@0: case eURLPrefix: { michael@0: if (StringBeginsWith(docURISpec, url->url)) michael@0: return true; michael@0: } break; michael@0: case eDomain: { michael@0: nsAutoCString host; michael@0: if (docURI) michael@0: docURI->GetHost(host); michael@0: int32_t lenDiff = host.Length() - url->url.Length(); michael@0: if (lenDiff == 0) { michael@0: if (host == url->url) michael@0: return true; michael@0: } else { michael@0: if (StringEndsWith(host, url->url) && michael@0: host.CharAt(lenDiff - 1) == '.') michael@0: return true; michael@0: } michael@0: } break; michael@0: case eRegExp: { michael@0: NS_ConvertUTF8toUTF16 spec(docURISpec); michael@0: NS_ConvertUTF8toUTF16 regex(url->url); michael@0: if (nsContentUtils::IsPatternMatching(spec, regex, doc)) { michael@0: return true; michael@0: } michael@0: } break; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: DocumentRule::URL::~URL() michael@0: { michael@0: NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next); michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: size_t n = aMallocSizeOf(this); michael@0: n += GroupRule::SizeOfExcludingThis(aMallocSizeOf); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mURLs michael@0: michael@0: return n; michael@0: } michael@0: michael@0: void michael@0: DocumentRule::AppendConditionText(nsAString& aCssText) michael@0: { michael@0: for (URL *url = mURLs; url; url = url->next) { michael@0: switch (url->func) { michael@0: case eURL: michael@0: aCssText.AppendLiteral("url("); michael@0: break; michael@0: case eURLPrefix: michael@0: aCssText.AppendLiteral("url-prefix("); michael@0: break; michael@0: case eDomain: michael@0: aCssText.AppendLiteral("domain("); michael@0: break; michael@0: case eRegExp: michael@0: aCssText.AppendLiteral("regexp("); michael@0: break; michael@0: } michael@0: nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url), michael@0: aCssText); michael@0: aCssText.AppendLiteral("), "); michael@0: } michael@0: aCssText.Truncate(aCssText.Length() - 2); // remove last ", " michael@0: } michael@0: michael@0: } // namespace css michael@0: } // namespace mozilla michael@0: michael@0: // Must be outside namespace michael@0: DOMCI_DATA(CSSMozDocumentRule, css::DocumentRule) michael@0: michael@0: // ------------------------------------------- michael@0: // NameSpaceRule michael@0: // michael@0: michael@0: namespace mozilla { michael@0: namespace css { michael@0: michael@0: NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec) michael@0: : Rule(), michael@0: mPrefix(aPrefix), michael@0: mURLSpec(aURLSpec) michael@0: { michael@0: } michael@0: michael@0: NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy) michael@0: : Rule(aCopy), michael@0: mPrefix(aCopy.mPrefix), michael@0: mURLSpec(aCopy.mURLSpec) michael@0: { michael@0: } michael@0: michael@0: NameSpaceRule::~NameSpaceRule() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(NameSpaceRule) michael@0: NS_IMPL_RELEASE(NameSpaceRule) michael@0: michael@0: // QueryInterface implementation for NameSpaceRule michael@0: NS_INTERFACE_MAP_BEGIN(NameSpaceRule) michael@0: if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) { michael@0: *aInstancePtr = this; michael@0: NS_ADDREF_THIS(); michael@0: return NS_OK; michael@0: } michael@0: else michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT(NameSpaceRule, Rule) michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: NameSpaceRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: nsAutoString buffer; michael@0: michael@0: fputs("@namespace ", out); michael@0: michael@0: if (mPrefix) { michael@0: mPrefix->ToString(buffer); michael@0: fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); michael@0: fputs(" ", out); michael@0: } michael@0: michael@0: fputs("url(", out); michael@0: fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out); michael@0: fputs(")\n", out); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: NameSpaceRule::GetType() const michael@0: { michael@0: return Rule::NAMESPACE_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: NameSpaceRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new NameSpaceRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: NameSpaceRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::NAMESPACE_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: NameSpaceRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@namespace "); michael@0: if (mPrefix) { michael@0: aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" ")); michael@0: } michael@0: aCssText.AppendLiteral("url("); michael@0: nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText); michael@0: aCssText.Append(NS_LITERAL_STRING(");")); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: NameSpaceRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: NameSpaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mPrefix michael@0: // - mURLSpec michael@0: } michael@0: michael@0: michael@0: } // namespace css michael@0: } // namespace mozilla michael@0: michael@0: // Must be outside namespace michael@0: DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule) michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSFontFaceStyleDecl and related routines michael@0: // michael@0: michael@0: // A src: descriptor is represented as an array value; each entry in michael@0: // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or michael@0: // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear michael@0: // only after one of the first two. (css3-fonts only contemplates michael@0: // annotating URLs with formats, but we handle the general case.) michael@0: static void michael@0: AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult) michael@0: { michael@0: NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array, michael@0: "improper value unit for src:"); michael@0: michael@0: const nsCSSValue::Array& sources = *src.GetArrayValue(); michael@0: size_t i = 0; michael@0: michael@0: while (i < sources.Count()) { michael@0: nsAutoString formats; michael@0: michael@0: if (sources[i].GetUnit() == eCSSUnit_URL) { michael@0: aResult.AppendLiteral("url("); michael@0: nsDependentString url(sources[i].GetOriginalURLValue()); michael@0: nsStyleUtil::AppendEscapedCSSString(url, aResult); michael@0: aResult.AppendLiteral(")"); michael@0: } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) { michael@0: aResult.AppendLiteral("local("); michael@0: nsDependentString local(sources[i].GetStringBufferValue()); michael@0: nsStyleUtil::AppendEscapedCSSString(local, aResult); michael@0: aResult.AppendLiteral(")"); michael@0: } else { michael@0: NS_NOTREACHED("entry in src: descriptor with improper unit"); michael@0: i++; michael@0: continue; michael@0: } michael@0: michael@0: i++; michael@0: formats.Truncate(); michael@0: while (i < sources.Count() && michael@0: sources[i].GetUnit() == eCSSUnit_Font_Format) { michael@0: formats.Append('"'); michael@0: formats.Append(sources[i].GetStringBufferValue()); michael@0: formats.AppendLiteral("\", "); michael@0: i++; michael@0: } michael@0: if (formats.Length() > 0) { michael@0: formats.Truncate(formats.Length() - 2); // remove the last comma michael@0: aResult.AppendLiteral(" format("); michael@0: aResult.Append(formats); michael@0: aResult.Append(')'); michael@0: } michael@0: aResult.AppendLiteral(", "); michael@0: } michael@0: aResult.Truncate(aResult.Length() - 2); // remove the last comma-space michael@0: } michael@0: michael@0: // print all characters with at least four hex digits michael@0: static void michael@0: AppendSerializedUnicodePoint(uint32_t aCode, nsACString &aBuf) michael@0: { michael@0: aBuf.Append(nsPrintfCString("%04X", aCode)); michael@0: } michael@0: michael@0: // A unicode-range: descriptor is represented as an array of integers, michael@0: // to be interpreted as a sequence of pairs: min max min max ... michael@0: // It is in source order. (Possibly it should be sorted and overlaps michael@0: // consolidated, but right now we don't do that.) michael@0: static void michael@0: AppendSerializedUnicodeRange(nsCSSValue const & aValue, michael@0: nsAString & aResult) michael@0: { michael@0: NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null || michael@0: aValue.GetUnit() == eCSSUnit_Array, michael@0: "improper value unit for unicode-range:"); michael@0: aResult.Truncate(); michael@0: if (aValue.GetUnit() != eCSSUnit_Array) michael@0: return; michael@0: michael@0: nsCSSValue::Array const & sources = *aValue.GetArrayValue(); michael@0: nsAutoCString buf; michael@0: michael@0: NS_ABORT_IF_FALSE(sources.Count() % 2 == 0, michael@0: "odd number of entries in a unicode-range: array"); michael@0: michael@0: for (uint32_t i = 0; i < sources.Count(); i += 2) { michael@0: uint32_t min = sources[i].GetIntValue(); michael@0: uint32_t max = sources[i+1].GetIntValue(); michael@0: michael@0: // We don't try to replicate the U+XX?? notation. michael@0: buf.AppendLiteral("U+"); michael@0: AppendSerializedUnicodePoint(min, buf); michael@0: michael@0: if (min != max) { michael@0: buf.Append('-'); michael@0: AppendSerializedUnicodePoint(max, buf); michael@0: } michael@0: buf.AppendLiteral(", "); michael@0: } michael@0: buf.Truncate(buf.Length() - 2); // remove the last comma-space michael@0: CopyASCIItoUTF16(buf, aResult); michael@0: } michael@0: michael@0: // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields. michael@0: nsCSSValue nsCSSFontFaceStyleDecl::* const michael@0: nsCSSFontFaceStyleDecl::Fields[] = { michael@0: #define CSS_FONT_DESC(name_, method_) &nsCSSFontFaceStyleDecl::m##method_, michael@0: #include "nsCSSFontDescList.h" michael@0: #undef CSS_FONT_DESC michael@0: }; michael@0: michael@0: // QueryInterface implementation for nsCSSFontFaceStyleDecl michael@0: NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl) michael@0: NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration) michael@0: NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: // We forward the cycle collection interfaces to ContainingRule(), which is michael@0: // never null (in fact, we're part of that object!) michael@0: if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) || michael@0: aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { michael@0: return ContainingRule()->QueryInterface(aIID, aInstancePtr); michael@0: } michael@0: else michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule()) michael@0: NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule()) michael@0: michael@0: // helper for string GetPropertyValue and RemovePropertyValue michael@0: nsresult michael@0: nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID, michael@0: nsAString & aResult) const michael@0: { michael@0: NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN, michael@0: eCSSFontDesc_COUNT - 1); michael@0: michael@0: aResult.Truncate(); michael@0: if (aFontDescID == eCSSFontDesc_UNKNOWN) michael@0: return NS_OK; michael@0: michael@0: const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID]; michael@0: michael@0: if (val.GetUnit() == eCSSUnit_Null) { michael@0: // Avoid having to check no-value in the Family and Src cases below. michael@0: return NS_OK; michael@0: } michael@0: michael@0: switch (aFontDescID) { michael@0: case eCSSFontDesc_Family: { michael@0: // we don't use nsCSSValue::AppendToString here because it doesn't michael@0: // canonicalize the way we want, and anyway it's overkill when michael@0: // we know we have eCSSUnit_String michael@0: NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit"); michael@0: nsDependentString family(val.GetStringBufferValue()); michael@0: nsStyleUtil::AppendEscapedCSSString(family, aResult); michael@0: return NS_OK; michael@0: } michael@0: michael@0: case eCSSFontDesc_Style: michael@0: val.AppendToString(eCSSProperty_font_style, aResult, michael@0: nsCSSValue::eNormalized); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_Weight: michael@0: val.AppendToString(eCSSProperty_font_weight, aResult, michael@0: nsCSSValue::eNormalized); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_Stretch: michael@0: val.AppendToString(eCSSProperty_font_stretch, aResult, michael@0: nsCSSValue::eNormalized); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_FontFeatureSettings: michael@0: nsStyleUtil::AppendFontFeatureSettings(val, aResult); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_FontLanguageOverride: michael@0: val.AppendToString(eCSSProperty_font_language_override, aResult, michael@0: nsCSSValue::eNormalized); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_Src: michael@0: AppendSerializedFontSrc(val, aResult); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_UnicodeRange: michael@0: AppendSerializedUnicodeRange(val, aResult); michael@0: return NS_OK; michael@0: michael@0: case eCSSFontDesc_UNKNOWN: michael@0: case eCSSFontDesc_COUNT: michael@0: ; michael@0: } michael@0: NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: " michael@0: "out-of-range value got to the switch"); michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: michael@0: // attribute DOMString cssText; michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText) michael@0: { michael@0: nsAutoString descStr; michael@0: michael@0: aCssText.Truncate(); michael@0: for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1); michael@0: id < eCSSFontDesc_COUNT; michael@0: id = nsCSSFontDesc(id + 1)) { michael@0: if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() michael@0: != eCSSUnit_Null && michael@0: NS_SUCCEEDED(GetPropertyValue(id, descStr))) { michael@0: NS_ASSERTION(descStr.Length() > 0, michael@0: "GetCssText: non-null unit, empty property value"); michael@0: aCssText.AppendLiteral(" "); michael@0: aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get()); michael@0: aCssText.AppendLiteral(": "); michael@0: aCssText.Append(descStr); michael@0: aCssText.AppendLiteral(";\n"); michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; // bug 443978 michael@0: } michael@0: michael@0: // DOMString getPropertyValue (in DOMString propertyName); michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName, michael@0: nsAString & aResult) michael@0: { michael@0: return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName, michael@0: nsAString& aResult) michael@0: { michael@0: // We don't return any authored property values different from michael@0: // GetPropertyValue, currently. michael@0: return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult); michael@0: } michael@0: michael@0: // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName); michael@0: already_AddRefed michael@0: nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName, michael@0: ErrorResult& aRv) michael@0: { michael@0: // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong. michael@0: aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); michael@0: return nullptr; michael@0: } michael@0: michael@0: // DOMString removeProperty (in DOMString propertyName) raises (DOMException); michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName, michael@0: nsAString & aResult) michael@0: { michael@0: nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName); michael@0: NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN && michael@0: descID < eCSSFontDesc_COUNT, michael@0: "LookupFontDesc returned value out of range"); michael@0: michael@0: if (descID == eCSSFontDesc_UNKNOWN) { michael@0: aResult.Truncate(); michael@0: } else { michael@0: nsresult rv = GetPropertyValue(descID, aResult); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset(); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: // DOMString getPropertyPriority (in DOMString propertyName); michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName, michael@0: nsAString & aResult) michael@0: { michael@0: // font descriptors do not have priorities at present michael@0: aResult.Truncate(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // void setProperty (in DOMString propertyName, in DOMString value, michael@0: // in DOMString priority) raises (DOMException); michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName, michael@0: const nsAString & value, michael@0: const nsAString & priority) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; // bug 443978 michael@0: } michael@0: michael@0: // readonly attribute unsigned long length; michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength) michael@0: { michael@0: uint32_t len = 0; michael@0: for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1); michael@0: id < eCSSFontDesc_COUNT; michael@0: id = nsCSSFontDesc(id + 1)) michael@0: if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null) michael@0: len++; michael@0: michael@0: *aLength = len; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // DOMString item (in unsigned long index); michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn) michael@0: { michael@0: bool found; michael@0: IndexedGetter(aIndex, found, aReturn); michael@0: if (!found) { michael@0: aReturn.Truncate(); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult) michael@0: { michael@0: int32_t nset = -1; michael@0: for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1); michael@0: id < eCSSFontDesc_COUNT; michael@0: id = nsCSSFontDesc(id + 1)) { michael@0: if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() michael@0: != eCSSUnit_Null) { michael@0: nset++; michael@0: if (nset == int32_t(index)) { michael@0: aFound = true; michael@0: aResult.AssignASCII(nsCSSProps::GetStringValue(id).get()); michael@0: return; michael@0: } michael@0: } michael@0: } michael@0: aFound = false; michael@0: } michael@0: michael@0: // readonly attribute nsIDOMCSSRule parentRule; michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: NS_IF_ADDREF(*aParentRule = ContainingRule()->GetDOMRule()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSProperty aPropID, michael@0: nsAString& aValue) michael@0: { michael@0: return michael@0: GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)), michael@0: aValue); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSProperty aPropID, michael@0: const nsAString& aValue) michael@0: { michael@0: return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)), michael@0: aValue, EmptyString()); michael@0: } michael@0: michael@0: nsINode* michael@0: nsCSSFontFaceStyleDecl::GetParentObject() michael@0: { michael@0: return ContainingRule()->GetDocument(); michael@0: } michael@0: michael@0: JSObject* michael@0: nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx) michael@0: { michael@0: return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this); michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSFontFaceRule michael@0: // michael@0: michael@0: /* virtual */ already_AddRefed michael@0: nsCSSFontFaceRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new nsCSSFontFaceRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSFontFaceRule) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSFontFaceRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSFontFaceRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule) michael@0: // Trace the wrapper for our declaration. This just expands out michael@0: // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use michael@0: // directly because the wrapper is on the declaration, not on us. michael@0: tmp->mDecl.TraceWrapper(aCallbacks, aClosure); michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule) michael@0: // Unlink the wrapper for our declaraton. This just expands out michael@0: // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use michael@0: // directly because the wrapper is on the declaration, not on us. michael@0: tmp->mDecl.ReleaseWrapper(static_cast(p)); michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule) michael@0: // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call michael@0: // into our Trace hook, where we do the right thing with declarations michael@0: // already. michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: DOMCI_DATA(CSSFontFaceRule, nsCSSFontFaceRule) michael@0: michael@0: // QueryInterface implementation for nsCSSFontFaceRule michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSFontFaceRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, Rule) michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: nsCString baseInd, descInd; michael@0: for (int32_t indent = aIndent; --indent >= 0; ) { michael@0: baseInd.AppendLiteral(" "); michael@0: descInd.AppendLiteral(" "); michael@0: } michael@0: descInd.AppendLiteral(" "); michael@0: michael@0: nsString descStr; michael@0: michael@0: fprintf(out, "%s@font-face {\n", baseInd.get()); michael@0: for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1); michael@0: id < eCSSFontDesc_COUNT; michael@0: id = nsCSSFontDesc(id + 1)) michael@0: if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() michael@0: != eCSSUnit_Null) { michael@0: if (NS_FAILED(mDecl.GetPropertyValue(id, descStr))) michael@0: descStr.AssignLiteral("#"); michael@0: else if (descStr.Length() == 0) michael@0: descStr.AssignLiteral("#"); michael@0: fprintf(out, "%s%s: %s\n", michael@0: descInd.get(), nsCSSProps::GetStringValue(id).get(), michael@0: NS_ConvertUTF16toUTF8(descStr).get()); michael@0: } michael@0: fprintf(out, "%s}\n", baseInd.get()); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: nsCSSFontFaceRule::GetType() const michael@0: { michael@0: return Rule::FONT_FACE_RULE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::FONT_FACE_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: nsAutoString propText; michael@0: mDecl.GetCssText(propText); michael@0: michael@0: aCssText.AssignLiteral("@font-face {\n"); michael@0: aCssText.Append(propText); michael@0: aCssText.Append('}'); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; // bug 443978 michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) michael@0: { michael@0: NS_IF_ADDREF(*aStyle = &mDecl); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Arguably these should forward to nsCSSFontFaceStyleDecl methods. michael@0: void michael@0: nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue) michael@0: { michael@0: NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN && michael@0: aDescID < eCSSFontDesc_COUNT, michael@0: "aDescID out of range in nsCSSFontFaceRule::SetDesc"); michael@0: michael@0: // FIXME: handle dynamic changes michael@0: michael@0: mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue; michael@0: } michael@0: michael@0: void michael@0: nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue) michael@0: { michael@0: NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN && michael@0: aDescID < eCSSFontDesc_COUNT, michael@0: "aDescID out of range in nsCSSFontFaceRule::GetDesc"); michael@0: michael@0: aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID]; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mDecl michael@0: } michael@0: michael@0: michael@0: // ----------------------------------- michael@0: // nsCSSFontFeatureValuesRule michael@0: // michael@0: michael@0: /* virtual */ already_AddRefed michael@0: nsCSSFontFeatureValuesRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new nsCSSFontFeatureValuesRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(nsCSSFontFeatureValuesRule) michael@0: NS_IMPL_RELEASE(nsCSSFontFeatureValuesRule) michael@0: michael@0: DOMCI_DATA(CSSFontFeatureValuesRule, nsCSSFontFeatureValuesRule) michael@0: michael@0: // QueryInterface implementation for nsCSSFontFeatureValuesRule michael@0: NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFeatureValuesRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT(nsCSSFontFeatureValuesRule, Rule) michael@0: michael@0: static void michael@0: FamilyListToString(const nsTArray& aFamilyList, nsAString& aOutStr) michael@0: { michael@0: uint32_t i, n = aFamilyList.Length(); michael@0: michael@0: for (i = 0; i < n; i++) { michael@0: nsStyleUtil::AppendEscapedCSSString(aFamilyList[i], aOutStr); michael@0: if (i != n - 1) { michael@0: aOutStr.AppendLiteral(", "); michael@0: } michael@0: } michael@0: } michael@0: michael@0: static void michael@0: FeatureValuesToString( michael@0: const nsTArray& aFeatureValues, michael@0: nsAString& aOutStr) michael@0: { michael@0: uint32_t i, n; michael@0: michael@0: // append values michael@0: n = aFeatureValues.Length(); michael@0: for (i = 0; i < n; i++) { michael@0: const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i]; michael@0: michael@0: // @alternate michael@0: aOutStr.AppendLiteral(" @"); michael@0: nsAutoString functAlt; michael@0: nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt); michael@0: aOutStr.Append(functAlt); michael@0: aOutStr.AppendLiteral(" {"); michael@0: michael@0: // for each ident-values tuple michael@0: uint32_t j, numValues = fv.valuelist.Length(); michael@0: for (j = 0; j < numValues; j++) { michael@0: aOutStr.AppendLiteral(" "); michael@0: const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j]; michael@0: nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr); michael@0: aOutStr.AppendLiteral(":"); michael@0: michael@0: uint32_t k, numSelectors = vlist.featureSelectors.Length(); michael@0: for (k = 0; k < numSelectors; k++) { michael@0: aOutStr.AppendLiteral(" "); michael@0: aOutStr.AppendInt(vlist.featureSelectors[k]); michael@0: } michael@0: michael@0: aOutStr.AppendLiteral(";"); michael@0: } michael@0: aOutStr.AppendLiteral(" }\n"); michael@0: } michael@0: } michael@0: michael@0: static void michael@0: FontFeatureValuesRuleToString( michael@0: const nsTArray& aFamilyList, michael@0: const nsTArray& aFeatureValues, michael@0: nsAString& aOutStr) michael@0: { michael@0: aOutStr.AssignLiteral("@font-feature-values "); michael@0: nsAutoString familyListStr, valueTextStr; michael@0: FamilyListToString(aFamilyList, familyListStr); michael@0: aOutStr.Append(familyListStr); michael@0: aOutStr.AppendLiteral(" {\n"); michael@0: FeatureValuesToString(aFeatureValues, valueTextStr); michael@0: aOutStr.Append(valueTextStr); michael@0: aOutStr.AppendLiteral("}"); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: nsAutoString text; michael@0: FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text); michael@0: NS_ConvertUTF16toUTF8 utf8(text); michael@0: michael@0: // replace newlines with newlines plus indent spaces michael@0: char* indent = new char[(aIndent + 1) * 2]; michael@0: int32_t i; michael@0: for (i = 1; i < (aIndent + 1) * 2 - 1; i++) { michael@0: indent[i] = 0x20; michael@0: } michael@0: indent[0] = 0xa; michael@0: indent[aIndent * 2 + 1] = 0; michael@0: utf8.ReplaceSubstring("\n", indent); michael@0: delete [] indent; michael@0: michael@0: for (i = aIndent; --i >= 0; ) fputs(" ", out); michael@0: fprintf(out, "%s\n", utf8.get()); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: nsCSSFontFeatureValuesRule::GetType() const michael@0: { michael@0: return Rule::FONT_FEATURE_VALUES_RULE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: // FIXME: implement??? michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFontFamily) michael@0: { michael@0: FamilyListToString(mFamilyList, aFontFamily); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText) michael@0: { michael@0: FeatureValuesToString(mFeatureValues, aValueText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: struct MakeFamilyArray { michael@0: MakeFamilyArray(nsTArray& aFamilyArray) michael@0: : familyArray(aFamilyArray), hasGeneric(false) michael@0: {} michael@0: michael@0: static bool michael@0: AddFamily(const nsString& aFamily, bool aGeneric, void* aData) michael@0: { michael@0: MakeFamilyArray *familyArr = reinterpret_cast (aData); michael@0: if (!aGeneric && !aFamily.IsEmpty()) { michael@0: familyArr->familyArray.AppendElement(aFamily); michael@0: } michael@0: if (aGeneric) { michael@0: familyArr->hasGeneric = true; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: nsTArray& familyArray; michael@0: bool hasGeneric; michael@0: }; michael@0: michael@0: void michael@0: nsCSSFontFeatureValuesRule::SetFamilyList(const nsAString& aFamilyList, michael@0: bool& aContainsGeneric) michael@0: { michael@0: nsFont font(aFamilyList, 0, 0, 0, 0, 0, 0); michael@0: MakeFamilyArray families(mFamilyList); michael@0: font.EnumerateFamilies(MakeFamilyArray::AddFamily, (void*) &families); michael@0: aContainsGeneric = families.hasGeneric; michael@0: } michael@0: michael@0: void michael@0: nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate, michael@0: nsTArray& aValueList) michael@0: { michael@0: uint32_t i, len = mFeatureValues.Length(); michael@0: bool foundAlternate = false; michael@0: michael@0: // add to an existing list for a given property value michael@0: for (i = 0; i < len; i++) { michael@0: gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i); michael@0: michael@0: if (f.alternate == uint32_t(aVariantAlternate)) { michael@0: f.valuelist.AppendElements(aValueList); michael@0: foundAlternate = true; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // create a new list for a given property value michael@0: if (!foundAlternate) { michael@0: gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement(); michael@0: f.alternate = aVariantAlternate; michael@0: f.valuelist.AppendElements(aValueList); michael@0: } michael@0: } michael@0: michael@0: size_t michael@0: nsCSSFontFeatureValuesRule::SizeOfIncludingThis( michael@0: MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSKeyframeStyleDeclaration michael@0: // michael@0: michael@0: nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule) michael@0: : mRule(aRule) michael@0: { michael@0: } michael@0: michael@0: nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration() michael@0: { michael@0: NS_ASSERTION(!mRule, "DropReference not called."); michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration) michael@0: NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY michael@0: NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) michael@0: michael@0: css::Declaration* michael@0: nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(bool aAllocate) michael@0: { michael@0: if (mRule) { michael@0: return mRule->Declaration(); michael@0: } else { michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) michael@0: { michael@0: GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParent); michael@0: michael@0: NS_IF_ADDREF(*aParent = mRule); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl) michael@0: { michael@0: NS_ABORT_IF_FALSE(aDecl, "must be non-null"); michael@0: mRule->ChangeDeclaration(aDecl); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIDocument* michael@0: nsCSSKeyframeStyleDeclaration::DocToUpdate() michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsINode* michael@0: nsCSSKeyframeStyleDeclaration::GetParentObject() michael@0: { michael@0: return mRule ? mRule->GetDocument() : nullptr; michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSKeyframeRule michael@0: // michael@0: michael@0: nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy) michael@0: // copy everything except our reference count and mDOMDeclaration michael@0: : Rule(aCopy) michael@0: , mKeys(aCopy.mKeys) michael@0: , mDeclaration(new css::Declaration(*aCopy.mDeclaration)) michael@0: { michael@0: } michael@0: michael@0: nsCSSKeyframeRule::~nsCSSKeyframeRule() michael@0: { michael@0: if (mDOMDeclaration) { michael@0: mDOMDeclaration->DropReference(); michael@0: } michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: nsCSSKeyframeRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new nsCSSKeyframeRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSKeyframeRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule) michael@0: if (tmp->mDOMDeclaration) { michael@0: tmp->mDOMDeclaration->DropReference(); michael@0: tmp->mDOMDeclaration = nullptr; michael@0: } michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_END michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule) michael@0: michael@0: // QueryInterface implementation for nsCSSKeyframeRule michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframeRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule) michael@0: michael@0: /* virtual */ void michael@0: nsCSSKeyframeRule::MapRuleInfoInto(nsRuleData* aRuleData) michael@0: { michael@0: // We need to implement MapRuleInfoInto because the animation manager michael@0: // constructs a rule node pointing to us in order to compute the michael@0: // styles it needs to animate. michael@0: michael@0: // The spec says that !important declarations should just be ignored michael@0: NS_ASSERTION(!mDeclaration->HasImportantData(), michael@0: "Keyframe rules has !important data"); michael@0: michael@0: mDeclaration->MapNormalRuleInfoInto(aRuleData); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); michael@0: michael@0: nsAutoString tmp; michael@0: DoGetKeyText(tmp); michael@0: fputs(NS_ConvertUTF16toUTF8(tmp).get(), out); michael@0: fputs(" ", out); michael@0: mDeclaration->List(out, aIndent); michael@0: fputs("\n", out); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: nsCSSKeyframeRule::GetType() const michael@0: { michael@0: return Rule::KEYFRAME_RULE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::KEYFRAME_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: DoGetKeyText(aCssText); michael@0: aCssText.AppendLiteral(" { "); michael@0: nsAutoString tmp; michael@0: mDeclaration->ToString(tmp); michael@0: aCssText.Append(tmp); michael@0: aCssText.AppendLiteral(" }"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: // FIXME: implement??? michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText) michael@0: { michael@0: DoGetKeyText(aKeyText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const michael@0: { michael@0: aKeyText.Truncate(); michael@0: uint32_t i = 0, i_end = mKeys.Length(); michael@0: NS_ABORT_IF_FALSE(i_end != 0, "must have some keys"); michael@0: for (;;) { michael@0: aKeyText.AppendFloat(mKeys[i] * 100.0f); michael@0: aKeyText.Append(char16_t('%')); michael@0: if (++i == i_end) { michael@0: break; michael@0: } michael@0: aKeyText.AppendLiteral(", "); michael@0: } michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) michael@0: { michael@0: nsCSSParser parser; michael@0: michael@0: InfallibleTArray newSelectors; michael@0: // FIXME: pass filename and line number michael@0: if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) { michael@0: // for now, we don't do anything if the parse fails michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIDocument* doc = GetDocument(); michael@0: MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); michael@0: michael@0: newSelectors.SwapElements(mKeys); michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: michael@0: if (doc) { michael@0: doc->StyleRuleChanged(sheet, this, this); michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) michael@0: { michael@0: if (!mDOMDeclaration) { michael@0: mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this); michael@0: } michael@0: NS_ADDREF(*aStyle = mDOMDeclaration); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) michael@0: { michael@0: // Our caller already did a BeginUpdate/EndUpdate, but with michael@0: // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in michael@0: // PresShell::EndUpdate. michael@0: nsIDocument* doc = GetDocument(); michael@0: MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); michael@0: michael@0: // Be careful to not assign to an nsAutoPtr if we would be assigning michael@0: // the thing it already holds. michael@0: if (aDeclaration != mDeclaration) { michael@0: mDeclaration = aDeclaration; michael@0: } michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: michael@0: if (doc) { michael@0: doc->StyleRuleChanged(sheet, this, this); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mKeys michael@0: // - mDeclaration michael@0: // - mDOMDeclaration michael@0: } michael@0: michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSKeyframesRule michael@0: // michael@0: michael@0: nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy) michael@0: // copy everything except our reference count. GroupRule's copy michael@0: // constructor also doesn't copy the lazily-constructed michael@0: // mRuleCollection. michael@0: : GroupRule(aCopy), michael@0: mName(aCopy.mName) michael@0: { michael@0: } michael@0: michael@0: nsCSSKeyframesRule::~nsCSSKeyframesRule() michael@0: { michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: nsCSSKeyframesRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new nsCSSKeyframesRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, css::GroupRule) michael@0: NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, css::GroupRule) michael@0: michael@0: DOMCI_DATA(MozCSSKeyframesRule, nsCSSKeyframesRule) michael@0: michael@0: // QueryInterface implementation for nsCSSKeyframesRule michael@0: NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframesRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframesRule) michael@0: NS_INTERFACE_MAP_END_INHERITING(GroupRule) michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: fprintf(out, "@keyframes %s", NS_ConvertUTF16toUTF8(mName).get()); michael@0: GroupRule::List(out, aIndent); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: nsCSSKeyframesRule::GetType() const michael@0: { michael@0: return Rule::KEYFRAMES_RULE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::KEYFRAMES_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@keyframes "); michael@0: aCssText.Append(mName); michael@0: aCssText.AppendLiteral(" {\n"); michael@0: nsAutoString tmp; michael@0: for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) { michael@0: static_cast(mRules[i])->GetCssText(tmp); michael@0: aCssText.Append(tmp); michael@0: aCssText.AppendLiteral("\n"); michael@0: } michael@0: aCssText.AppendLiteral("}"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: // FIXME: implement??? michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return GroupRule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return GroupRule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetName(nsAString& aName) michael@0: { michael@0: aName = mName; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::SetName(const nsAString& aName) michael@0: { michael@0: if (mName == aName) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIDocument* doc = GetDocument(); michael@0: MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); michael@0: michael@0: mName = aName; michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: michael@0: if (doc) { michael@0: doc->StyleRuleChanged(sheet, this, this); michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) michael@0: { michael@0: return GroupRule::GetCssRules(aRuleList); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::AppendRule(const nsAString& aRule) michael@0: { michael@0: // The spec is confusing, and I think we should just append the rule, michael@0: // which also turns out to match WebKit: michael@0: // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html michael@0: nsCSSParser parser; michael@0: michael@0: // FIXME: pass filename and line number michael@0: nsRefPtr rule = michael@0: parser.ParseKeyframeRule(aRule, nullptr, 0); michael@0: if (rule) { michael@0: nsIDocument* doc = GetDocument(); michael@0: MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); michael@0: michael@0: AppendStyleRule(rule); michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: michael@0: if (doc) { michael@0: doc->StyleRuleChanged(sheet, this, this); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: static const uint32_t RULE_NOT_FOUND = uint32_t(-1); michael@0: michael@0: uint32_t michael@0: nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey) michael@0: { michael@0: nsCSSParser parser; michael@0: michael@0: InfallibleTArray keys; michael@0: // FIXME: pass filename and line number michael@0: if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) { michael@0: // The spec isn't clear, but we'll match on the key list, which michael@0: // mostly matches what WebKit does, except we'll do last-match michael@0: // instead of first-match, and handling parsing differences better. michael@0: // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html michael@0: // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html michael@0: for (uint32_t i = mRules.Count(); i-- != 0; ) { michael@0: if (static_cast(mRules[i])->GetKeys() == keys) { michael@0: return i; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return RULE_NOT_FOUND; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::DeleteRule(const nsAString& aKey) michael@0: { michael@0: uint32_t index = FindRuleIndexForKey(aKey); michael@0: if (index != RULE_NOT_FOUND) { michael@0: nsIDocument* doc = GetDocument(); michael@0: MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); michael@0: michael@0: mRules.RemoveObjectAt(index); michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: michael@0: if (doc) { michael@0: doc->StyleRuleChanged(sheet, this, this); michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSKeyframesRule::FindRule(const nsAString& aKey, michael@0: nsIDOMMozCSSKeyframeRule** aResult) michael@0: { michael@0: uint32_t index = FindRuleIndexForKey(aKey); michael@0: if (index == RULE_NOT_FOUND) { michael@0: *aResult = nullptr; michael@0: } else { michael@0: NS_ADDREF(*aResult = static_cast(mRules[index])); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: // GroupRule interface michael@0: /* virtual */ bool michael@0: nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext, michael@0: nsMediaQueryResultCacheKey& aKey) michael@0: { michael@0: NS_ABORT_IF_FALSE(false, "should not be called"); michael@0: return false; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: size_t n = aMallocSizeOf(this); michael@0: n += GroupRule::SizeOfExcludingThis(aMallocSizeOf); michael@0: michael@0: // Measurement of the following members may be added later if DMD finds it is michael@0: // worthwhile: michael@0: // - mName michael@0: michael@0: return n; michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSPageStyleDeclaration michael@0: // michael@0: michael@0: nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule) michael@0: : mRule(aRule) michael@0: { michael@0: } michael@0: michael@0: nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration() michael@0: { michael@0: NS_ASSERTION(!mRule, "DropReference not called."); michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration) michael@0: NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY michael@0: NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) michael@0: michael@0: css::Declaration* michael@0: nsCSSPageStyleDeclaration::GetCSSDeclaration(bool aAllocate) michael@0: { michael@0: if (mRule) { michael@0: return mRule->Declaration(); michael@0: } else { michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) michael@0: { michael@0: GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParent); michael@0: michael@0: NS_IF_ADDREF(*aParent = mRule); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl) michael@0: { michael@0: NS_ABORT_IF_FALSE(aDecl, "must be non-null"); michael@0: mRule->ChangeDeclaration(aDecl); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIDocument* michael@0: nsCSSPageStyleDeclaration::DocToUpdate() michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsINode* michael@0: nsCSSPageStyleDeclaration::GetParentObject() michael@0: { michael@0: return mRule ? mRule->GetDocument() : nullptr; michael@0: } michael@0: michael@0: // ------------------------------------------- michael@0: // nsCSSPageRule michael@0: // michael@0: michael@0: nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy) michael@0: // copy everything except our reference count and mDOMDeclaration michael@0: : Rule(aCopy) michael@0: , mDeclaration(new css::Declaration(*aCopy.mDeclaration)) michael@0: { michael@0: } michael@0: michael@0: nsCSSPageRule::~nsCSSPageRule() michael@0: { michael@0: if (mDOMDeclaration) { michael@0: mDOMDeclaration->DropReference(); michael@0: } michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: nsCSSPageRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new nsCSSPageRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageRule) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSPageRule) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSPageRule) michael@0: if (tmp->mDOMDeclaration) { michael@0: tmp->mDOMDeclaration->DropReference(); michael@0: tmp->mDOMDeclaration = nullptr; michael@0: } michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_END michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSPageRule) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: DOMCI_DATA(CSSPageRule, nsCSSPageRule) michael@0: michael@0: // QueryInterface implementation for nsCSSPageRule michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule) michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: nsCSSPageRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: fputs("@page ", out); michael@0: mDeclaration->List(out, aIndent); michael@0: fputs("\n", out); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: nsCSSPageRule::GetType() const michael@0: { michael@0: return Rule::PAGE_RULE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::PAGE_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AppendLiteral("@page { "); michael@0: nsAutoString tmp; michael@0: mDeclaration->ToString(tmp); michael@0: aCssText.Append(tmp); michael@0: aCssText.AppendLiteral(" }"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: // FIXME: implement??? michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return Rule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return Rule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: css::ImportantRule* michael@0: nsCSSPageRule::GetImportantRule() michael@0: { michael@0: if (!mDeclaration->HasImportantData()) { michael@0: return nullptr; michael@0: } michael@0: if (!mImportantRule) { michael@0: mImportantRule = new css::ImportantRule(mDeclaration); michael@0: } michael@0: return mImportantRule; michael@0: } michael@0: michael@0: /* virtual */ void michael@0: nsCSSPageRule::MapRuleInfoInto(nsRuleData* aRuleData) michael@0: { michael@0: mDeclaration->MapNormalRuleInfoInto(aRuleData); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) michael@0: { michael@0: if (!mDOMDeclaration) { michael@0: mDOMDeclaration = new nsCSSPageStyleDeclaration(this); michael@0: } michael@0: NS_ADDREF(*aStyle = mDOMDeclaration); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration) michael@0: { michael@0: mImportantRule = nullptr; michael@0: // Be careful to not assign to an nsAutoPtr if we would be assigning michael@0: // the thing it already holds. michael@0: if (aDeclaration != mDeclaration) { michael@0: mDeclaration = aDeclaration; michael@0: } michael@0: michael@0: nsCSSStyleSheet* sheet = GetStyleSheet(); michael@0: if (sheet) { michael@0: sheet->SetModifiedByChildRule(); michael@0: } michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this); michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: CSSSupportsRule::CSSSupportsRule(bool aConditionMet, michael@0: const nsString& aCondition) michael@0: : mUseGroup(aConditionMet), michael@0: mCondition(aCondition) michael@0: { michael@0: } michael@0: michael@0: CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy) michael@0: : css::GroupRule(aCopy), michael@0: mUseGroup(aCopy.mUseGroup), michael@0: mCondition(aCopy.mCondition) michael@0: { michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: /* virtual */ void michael@0: CSSSupportsRule::List(FILE* out, int32_t aIndent) const michael@0: { michael@0: for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out); michael@0: michael@0: fputs("@supports ", out); michael@0: fputs(NS_ConvertUTF16toUTF8(mCondition).get(), out); michael@0: css::GroupRule::List(out, aIndent); michael@0: } michael@0: #endif michael@0: michael@0: /* virtual */ int32_t michael@0: CSSSupportsRule::GetType() const michael@0: { michael@0: return Rule::SUPPORTS_RULE; michael@0: } michael@0: michael@0: /* virtual */ already_AddRefed michael@0: CSSSupportsRule::Clone() const michael@0: { michael@0: nsRefPtr clone = new CSSSupportsRule(*this); michael@0: return clone.forget(); michael@0: } michael@0: michael@0: /* virtual */ bool michael@0: CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext, michael@0: nsMediaQueryResultCacheKey& aKey) michael@0: { michael@0: return mUseGroup; michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule) michael@0: NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule) michael@0: michael@0: // QueryInterface implementation for CSSSupportsRule michael@0: NS_INTERFACE_MAP_BEGIN(CSSSupportsRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStyleRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule) michael@0: NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule) michael@0: NS_INTERFACE_MAP_END_INHERITING(GroupRule) michael@0: michael@0: // nsIDOMCSSRule methods michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetType(uint16_t* aType) michael@0: { michael@0: *aType = nsIDOMCSSRule::SUPPORTS_RULE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetCssText(nsAString& aCssText) michael@0: { michael@0: aCssText.AssignLiteral("@supports "); michael@0: aCssText.Append(mCondition); michael@0: css::GroupRule::AppendRulesToCssText(aCssText); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::SetCssText(const nsAString& aCssText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) michael@0: { michael@0: return css::GroupRule::GetParentStyleSheet(aSheet); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetParentRule(nsIDOMCSSRule** aParentRule) michael@0: { michael@0: return css::GroupRule::GetParentRule(aParentRule); michael@0: } michael@0: michael@0: // nsIDOMCSSGroupingRule methods michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) michael@0: { michael@0: return css::GroupRule::GetCssRules(aRuleList); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval) michael@0: { michael@0: return css::GroupRule::InsertRule(aRule, aIndex, _retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::DeleteRule(uint32_t aIndex) michael@0: { michael@0: return css::GroupRule::DeleteRule(aIndex); michael@0: } michael@0: michael@0: // nsIDOMCSSConditionRule methods michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::GetConditionText(nsAString& aConditionText) michael@0: { michael@0: aConditionText.Assign(mCondition); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CSSSupportsRule::SetConditionText(const nsAString& aConditionText) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: size_t n = aMallocSizeOf(this); michael@0: n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf); michael@0: n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf); michael@0: return n; michael@0: } michael@0: michael@0: } // namespace mozilla michael@0: michael@0: // Must be outside namespace michael@0: DOMCI_DATA(CSSSupportsRule, mozilla::CSSSupportsRule)