layout/style/nsCSSRules.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
     8 #include "mozilla/Attributes.h"
    10 #include "nsCSSRules.h"
    11 #include "nsCSSValue.h"
    12 #include "mozilla/MemoryReporting.h"
    13 #include "mozilla/css/ImportRule.h"
    14 #include "mozilla/css/NameSpaceRule.h"
    16 #include "nsString.h"
    17 #include "nsIAtom.h"
    19 #include "nsCSSProps.h"
    20 #include "nsCSSStyleSheet.h"
    22 #include "nsCOMPtr.h"
    23 #include "nsIDOMCSSStyleSheet.h"
    24 #include "nsIMediaList.h"
    25 #include "nsICSSRuleList.h"
    26 #include "nsIDocument.h"
    27 #include "nsPresContext.h"
    29 #include "nsContentUtils.h"
    30 #include "nsError.h"
    31 #include "nsStyleUtil.h"
    32 #include "mozilla/css/Declaration.h"
    33 #include "nsCSSParser.h"
    34 #include "nsPrintfCString.h"
    35 #include "nsDOMClassInfoID.h"
    36 #include "mozilla/dom/CSSStyleDeclarationBinding.h"
    37 #include "StyleRule.h"
    38 #include "nsFont.h"
    39 #include "nsIURI.h"
    40 #include "mozAutoDocUpdate.h"
    42 using namespace mozilla;
    44 #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
    45   /* virtual */ nsIDOMCSSRule* class_::GetDOMRule()               \
    46   { return this; }                                                \
    47   /* virtual */ nsIDOMCSSRule* class_::GetExistingDOMRule()       \
    48   { return this; }
    49 #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \
    50 /* virtual */ void class_::MapRuleInfoInto(nsRuleData* aRuleData) \
    51   { NS_ABORT_IF_FALSE(false, "should not be called"); }
    53 #define IMPL_STYLE_RULE_INHERIT(class_, super_) \
    54 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
    55 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_)
    57 // base class for all rule types in a CSS style sheet
    59 namespace mozilla {
    60 namespace css {
    62 nsCSSStyleSheet*
    63 Rule::GetStyleSheet() const
    64 {
    65   if (!(mSheet & 0x1)) {
    66     return reinterpret_cast<nsCSSStyleSheet*>(mSheet);
    67   }
    69   return nullptr;
    70 }
    72 nsHTMLCSSStyleSheet*
    73 Rule::GetHTMLCSSStyleSheet() const
    74 {
    75   if (mSheet & 0x1) {
    76     return reinterpret_cast<nsHTMLCSSStyleSheet*>(mSheet & ~uintptr_t(0x1));
    77   }
    79   return nullptr;
    80 }
    82 /* virtual */ void
    83 Rule::SetStyleSheet(nsCSSStyleSheet* aSheet)
    84 {
    85   // We don't reference count this up reference. The style sheet
    86   // will tell us when it's going away or when we're detached from
    87   // it.
    88   mSheet = reinterpret_cast<uintptr_t>(aSheet);
    89 }
    91 void
    92 Rule::SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet)
    93 {
    94   // We don't reference count this up reference. The style sheet
    95   // will tell us when it's going away or when we're detached from
    96   // it.
    97   mSheet = reinterpret_cast<uintptr_t>(aSheet);
    98   mSheet |= 0x1;
    99 }
   101 nsresult
   102 Rule::GetParentRule(nsIDOMCSSRule** aParentRule)
   103 {
   104   if (mParentRule) {
   105     NS_IF_ADDREF(*aParentRule = mParentRule->GetDOMRule());
   106   } else {
   107     *aParentRule = nullptr;
   108   }
   109   return NS_OK;
   110 }
   112 nsresult
   113 Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
   114 {
   115   NS_ENSURE_ARG_POINTER(aSheet);
   117   NS_IF_ADDREF(*aSheet = GetStyleSheet());
   118   return NS_OK;
   119 }
   121 size_t
   122 Rule::SizeOfCOMArrayElementIncludingThis(css::Rule* aElement,
   123                                          MallocSizeOf aMallocSizeOf,
   124                                          void* aData)
   125 {
   126   return aElement->SizeOfIncludingThis(aMallocSizeOf);
   127 }
   129 // -------------------------------
   130 // Style Rule List for group rules
   131 //
   133 class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
   134 {
   135 public:
   136   GroupRuleRuleList(GroupRule *aGroupRule);
   138   NS_DECL_ISUPPORTS
   140   virtual nsIDOMCSSRule*
   141   IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
   142   virtual uint32_t
   143   Length() MOZ_OVERRIDE;
   145   void DropReference() { mGroupRule = nullptr; }
   147 private:
   148   ~GroupRuleRuleList();
   150 private:
   151   GroupRule* mGroupRule;
   152 };
   154 GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule)
   155 {
   156   // Not reference counted to avoid circular references.
   157   // The rule will tell us when its going away.
   158   mGroupRule = aGroupRule;
   159 }
   161 GroupRuleRuleList::~GroupRuleRuleList()
   162 {
   163 }
   165 // QueryInterface implementation for GroupRuleRuleList
   166 NS_INTERFACE_MAP_BEGIN(GroupRuleRuleList)
   167   NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
   168   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
   169   NS_INTERFACE_MAP_ENTRY(nsISupports)
   170   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList)
   171 NS_INTERFACE_MAP_END
   174 NS_IMPL_ADDREF(GroupRuleRuleList)
   175 NS_IMPL_RELEASE(GroupRuleRuleList)
   177 uint32_t
   178 GroupRuleRuleList::Length()
   179 {
   180   if (!mGroupRule) {
   181     return 0;
   182   }
   184   return SafeCast<uint32_t>(mGroupRule->StyleRuleCount());
   185 }
   187 nsIDOMCSSRule*
   188 GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
   189 {
   190   aFound = false;
   192   if (mGroupRule) {
   193     nsRefPtr<Rule> rule = mGroupRule->GetStyleRuleAt(aIndex);
   194     if (rule) {
   195       aFound = true;
   196       return rule->GetDOMRule();
   197     }
   198   }
   200   return nullptr;
   201 }
   203 } // namespace css
   204 } // namespace mozilla
   206 // -------------------------------------------
   207 // CharsetRule
   208 //
   210 // Must be outside namespace
   211 DOMCI_DATA(CSSCharsetRule, css::CharsetRule)
   213 namespace mozilla {
   214 namespace css {
   216 CharsetRule::CharsetRule(const nsAString& aEncoding)
   217   : Rule(),
   218     mEncoding(aEncoding)
   219 {
   220 }
   222 CharsetRule::CharsetRule(const CharsetRule& aCopy)
   223   : Rule(aCopy),
   224     mEncoding(aCopy.mEncoding)
   225 {
   226 }
   228 NS_IMPL_ADDREF(CharsetRule)
   229 NS_IMPL_RELEASE(CharsetRule)
   231 // QueryInterface implementation for CharsetRule
   232 NS_INTERFACE_MAP_BEGIN(CharsetRule)
   233   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   234   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
   235   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule)
   236   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
   237   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCharsetRule)
   238 NS_INTERFACE_MAP_END
   240 IMPL_STYLE_RULE_INHERIT(CharsetRule, Rule)
   242 #ifdef DEBUG
   243 /* virtual */ void
   244 CharsetRule::List(FILE* out, int32_t aIndent) const
   245 {
   246   // Indent
   247   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
   249   fputs("@charset \"", out);
   250   fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out);
   251   fputs("\"\n", out);
   252 }
   253 #endif
   255 /* virtual */ int32_t
   256 CharsetRule::GetType() const
   257 {
   258   return Rule::CHARSET_RULE;
   259 }
   261 /* virtual */ already_AddRefed<Rule>
   262 CharsetRule::Clone() const
   263 {
   264   nsRefPtr<Rule> clone = new CharsetRule(*this);
   265   return clone.forget();
   266 }
   268 NS_IMETHODIMP
   269 CharsetRule::GetEncoding(nsAString& aEncoding)
   270 {
   271   aEncoding = mEncoding;
   272   return NS_OK;
   273 }
   275 NS_IMETHODIMP
   276 CharsetRule::SetEncoding(const nsAString& aEncoding)
   277 {
   278   mEncoding = aEncoding;
   279   return NS_OK;
   280 }
   282 NS_IMETHODIMP
   283 CharsetRule::GetType(uint16_t* aType)
   284 {
   285   *aType = nsIDOMCSSRule::CHARSET_RULE;
   286   return NS_OK;
   287 }
   289 NS_IMETHODIMP
   290 CharsetRule::GetCssText(nsAString& aCssText)
   291 {
   292   aCssText.AssignLiteral("@charset \"");
   293   aCssText.Append(mEncoding);
   294   aCssText.AppendLiteral("\";");
   295   return NS_OK;
   296 }
   298 NS_IMETHODIMP
   299 CharsetRule::SetCssText(const nsAString& aCssText)
   300 {
   301   return NS_ERROR_NOT_IMPLEMENTED;
   302 }
   304 NS_IMETHODIMP
   305 CharsetRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
   306 {
   307   return Rule::GetParentStyleSheet(aSheet);
   308 }
   310 NS_IMETHODIMP
   311 CharsetRule::GetParentRule(nsIDOMCSSRule** aParentRule)
   312 {
   313   return Rule::GetParentRule(aParentRule);
   314 }
   316 /* virtual */ size_t
   317 CharsetRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   318 {
   319   return aMallocSizeOf(this);
   321   // Measurement of the following members may be added later if DMD finds it is
   322   // worthwhile:
   323   // - mEncoding
   324 }
   326 // -------------------------------------------
   327 // ImportRule
   328 //
   330 ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec)
   331   : Rule()
   332   , mURLSpec(aURLSpec)
   333   , mMedia(aMedia)
   334 {
   335   // XXXbz This is really silly.... the mMedia here will be replaced
   336   // with itself if we manage to load a sheet.  Which should really
   337   // never fail nowadays, in sane cases.
   338 }
   340 ImportRule::ImportRule(const ImportRule& aCopy)
   341   : Rule(aCopy),
   342     mURLSpec(aCopy.mURLSpec)
   343 {
   344   // Whether or not an @import rule has a null sheet is a permanent
   345   // property of that @import rule, since it is null only if the target
   346   // sheet failed security checks.
   347   if (aCopy.mChildSheet) {
   348     nsRefPtr<nsCSSStyleSheet> sheet =
   349       aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
   350     SetSheet(sheet);
   351     // SetSheet sets mMedia appropriately
   352   }
   353 }
   355 ImportRule::~ImportRule()
   356 {
   357   if (mChildSheet) {
   358     mChildSheet->SetOwnerRule(nullptr);
   359   }
   360 }
   362 NS_IMPL_ADDREF(ImportRule)
   363 NS_IMPL_RELEASE(ImportRule)
   365 // QueryInterface implementation for ImportRule
   366 NS_INTERFACE_MAP_BEGIN(ImportRule)
   367   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   368   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
   369   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
   370   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
   371   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
   372 NS_INTERFACE_MAP_END
   374 IMPL_STYLE_RULE_INHERIT(ImportRule, Rule)
   376 #ifdef DEBUG
   377 /* virtual */ void
   378 ImportRule::List(FILE* out, int32_t aIndent) const
   379 {
   380   // Indent
   381   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
   383   fputs("@import \"", out);
   384   fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
   385   fputs("\" ", out);
   387   nsAutoString mediaText;
   388   mMedia->GetText(mediaText);
   389   fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
   390   fputs("\n", out);
   391 }
   392 #endif
   394 /* virtual */ int32_t
   395 ImportRule::GetType() const
   396 {
   397   return Rule::IMPORT_RULE;
   398 }
   400 /* virtual */ already_AddRefed<Rule>
   401 ImportRule::Clone() const
   402 {
   403   nsRefPtr<Rule> clone = new ImportRule(*this);
   404   return clone.forget();
   405 }
   407 void
   408 ImportRule::SetSheet(nsCSSStyleSheet* aSheet)
   409 {
   410   NS_PRECONDITION(aSheet, "null arg");
   412   // set the new sheet
   413   mChildSheet = aSheet;
   414   aSheet->SetOwnerRule(this);
   416   // set our medialist to be the same as the sheet's medialist
   417   mMedia = mChildSheet->Media();
   418 }
   420 NS_IMETHODIMP
   421 ImportRule::GetType(uint16_t* aType)
   422 {
   423   NS_ENSURE_ARG_POINTER(aType);
   424   *aType = nsIDOMCSSRule::IMPORT_RULE;
   425   return NS_OK;
   426 }
   428 NS_IMETHODIMP
   429 ImportRule::GetCssText(nsAString& aCssText)
   430 {
   431   aCssText.AssignLiteral("@import url(");
   432   nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
   433   aCssText.Append(NS_LITERAL_STRING(")"));
   434   if (mMedia) {
   435     nsAutoString mediaText;
   436     mMedia->GetText(mediaText);
   437     if (!mediaText.IsEmpty()) {
   438       aCssText.AppendLiteral(" ");
   439       aCssText.Append(mediaText);
   440     }
   441   }
   442   aCssText.AppendLiteral(";");
   443   return NS_OK;
   444 }
   446 NS_IMETHODIMP
   447 ImportRule::SetCssText(const nsAString& aCssText)
   448 {
   449   return NS_ERROR_NOT_IMPLEMENTED;
   450 }
   452 NS_IMETHODIMP
   453 ImportRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
   454 {
   455   return Rule::GetParentStyleSheet(aSheet);
   456 }
   458 NS_IMETHODIMP
   459 ImportRule::GetParentRule(nsIDOMCSSRule** aParentRule)
   460 {
   461   return Rule::GetParentRule(aParentRule);
   462 }
   464 NS_IMETHODIMP
   465 ImportRule::GetHref(nsAString & aHref)
   466 {
   467   aHref = mURLSpec;
   468   return NS_OK;
   469 }
   471 NS_IMETHODIMP
   472 ImportRule::GetMedia(nsIDOMMediaList * *aMedia)
   473 {
   474   NS_ENSURE_ARG_POINTER(aMedia);
   476   NS_IF_ADDREF(*aMedia = mMedia);
   477   return NS_OK;
   478 }
   480 NS_IMETHODIMP
   481 ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
   482 {
   483   NS_ENSURE_ARG_POINTER(aStyleSheet);
   485   NS_IF_ADDREF(*aStyleSheet = mChildSheet);
   486   return NS_OK;
   487 }
   489 /* virtual */ size_t
   490 ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   491 {
   492   return aMallocSizeOf(this);
   494   // Measurement of the following members may be added later if DMD finds it is
   495   // worthwhile:
   496   // - mURLSpec
   497   //
   498   // The following members are not measured:
   499   // - mMedia, because it is measured via nsCSSStyleSheet::mMedia
   500   // - mChildSheet, because it is measured via nsCSSStyleSheetInner::mSheets
   501 }
   503 } // namespace css
   504 } // namespace mozilla
   506 // must be outside the namespace
   507 DOMCI_DATA(CSSImportRule, css::ImportRule)
   509 namespace mozilla {
   510 namespace css {
   512 GroupRule::GroupRule()
   513   : Rule()
   514 {
   515 }
   517 static bool
   518 SetParentRuleReference(Rule* aRule, void* aParentRule)
   519 {
   520   GroupRule* parentRule = static_cast<GroupRule*>(aParentRule);
   521   aRule->SetParentRule(parentRule);
   522   return true;
   523 }
   525 GroupRule::GroupRule(const GroupRule& aCopy)
   526   : Rule(aCopy)
   527 {
   528   const_cast<GroupRule&>(aCopy).mRules.EnumerateForwards(GroupRule::CloneRuleInto, &mRules);
   529   mRules.EnumerateForwards(SetParentRuleReference, this);
   530 }
   532 GroupRule::~GroupRule()
   533 {
   534   NS_ABORT_IF_FALSE(!mSheet, "SetStyleSheet should have been called");
   535   mRules.EnumerateForwards(SetParentRuleReference, nullptr);
   536   if (mRuleCollection) {
   537     mRuleCollection->DropReference();
   538   }
   539 }
   541 NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupRule)
   542 NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupRule)
   544 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
   545 NS_INTERFACE_MAP_END
   547 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(GroupRule, Rule)
   549 static bool
   550 SetStyleSheetReference(Rule* aRule, void* aSheet)
   551 {
   552   nsCSSStyleSheet* sheet = (nsCSSStyleSheet*)aSheet;
   553   aRule->SetStyleSheet(sheet);
   554   return true;
   555 }
   557 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
   559 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupRule)
   560   tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr);
   561   // If tmp does not have a stylesheet, neither do its descendants.  In that
   562   // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
   563   // depth of group rule nesting.  But if tmp _does_ have a stylesheet (which
   564   // can happen if it gets unlinked earlier than its owning stylesheet), then we
   565   // need to null out the stylesheet pointer on descendants now, before we clear
   566   // tmp->mRules.
   567   if (tmp->GetStyleSheet()) {
   568     tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr);
   569   }
   570   tmp->mRules.Clear();
   571   if (tmp->mRuleCollection) {
   572     tmp->mRuleCollection->DropReference();
   573     tmp->mRuleCollection = nullptr;
   574   }
   575 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   577 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupRule)
   578   const nsCOMArray<Rule>& rules = tmp->mRules;
   579   for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
   580     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
   581     cb.NoteXPCOMChild(rules[i]->GetExistingDOMRule());
   582   }
   583   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection)
   584 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   586 /* virtual */ void
   587 GroupRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
   588 {
   589   // Don't set the sheet on the kids if it's already the same as the sheet we
   590   // already have.  This is needed to avoid O(N^2) behavior in group nesting
   591   // depth when seting the sheet to null during unlink, if we happen to unlin in
   592   // order from most nested rule up to least nested rule.
   593   if (aSheet != GetStyleSheet()) {
   594     mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
   595     Rule::SetStyleSheet(aSheet);
   596   }
   597 }
   599 #ifdef DEBUG
   600 /* virtual */ void
   601 GroupRule::List(FILE* out, int32_t aIndent) const
   602 {
   603   fputs(" {\n", out);
   605   for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
   606     mRules.ObjectAt(index)->List(out, aIndent + 1);
   607   }
   609   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
   610   fputs("}\n", out);
   611 }
   612 #endif
   614 void
   615 GroupRule::AppendStyleRule(Rule* aRule)
   616 {
   617   mRules.AppendObject(aRule);
   618   nsCSSStyleSheet* sheet = GetStyleSheet();
   619   aRule->SetStyleSheet(sheet);
   620   aRule->SetParentRule(this);
   621   if (sheet) {
   622     sheet->SetModifiedByChildRule();
   623   }
   624 }
   626 Rule*
   627 GroupRule::GetStyleRuleAt(int32_t aIndex) const
   628 {
   629   return mRules.SafeObjectAt(aIndex);
   630 }
   632 bool
   633 GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
   634 {
   635   return
   636     const_cast<GroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
   637 }
   639 /*
   640  * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
   641  * should never be called unless you have first called WillDirty() on
   642  * the parents stylesheet.  After they are called, DidDirty() needs to
   643  * be called on the sheet
   644  */
   645 nsresult
   646 GroupRule::DeleteStyleRuleAt(uint32_t aIndex)
   647 {
   648   Rule* rule = mRules.SafeObjectAt(aIndex);
   649   if (rule) {
   650     rule->SetStyleSheet(nullptr);
   651     rule->SetParentRule(nullptr);
   652   }
   653   return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
   654 }
   656 nsresult
   657 GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
   658 {
   659   aRule->SetStyleSheet(GetStyleSheet());
   660   aRule->SetParentRule(this);
   661   if (! mRules.InsertObjectAt(aRule, aIndex)) {
   662     return NS_ERROR_FAILURE;
   663   }
   664   return NS_OK;
   665 }
   667 nsresult
   668 GroupRule::ReplaceStyleRule(Rule* aOld, Rule* aNew)
   669 {
   670   int32_t index = mRules.IndexOf(aOld);
   671   NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED);
   672   mRules.ReplaceObjectAt(aNew, index);
   673   aNew->SetStyleSheet(GetStyleSheet());
   674   aNew->SetParentRule(this);
   675   aOld->SetStyleSheet(nullptr);
   676   aOld->SetParentRule(nullptr);
   677   return NS_OK;
   678 }
   680 void
   681 GroupRule::AppendRulesToCssText(nsAString& aCssText)
   682 {
   683   aCssText.AppendLiteral(" {\n");
   685   // get all the rules
   686   for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
   687     Rule* rule = mRules.ObjectAt(index);
   688     nsIDOMCSSRule* domRule = rule->GetDOMRule();
   689     if (domRule) {
   690       nsAutoString cssText;
   691       domRule->GetCssText(cssText);
   692       aCssText.Append(NS_LITERAL_STRING("  ") +
   693                       cssText +
   694                       NS_LITERAL_STRING("\n"));
   695     }
   696   }
   698   aCssText.AppendLiteral("}");
   699 }
   701 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
   702 nsresult
   703 GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
   704 {
   705   if (!mRuleCollection) {
   706     mRuleCollection = new css::GroupRuleRuleList(this);
   707   }
   709   NS_ADDREF(*aRuleList = mRuleCollection);
   710   return NS_OK;
   711 }
   713 nsresult
   714 GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
   715 {
   716   nsCSSStyleSheet* sheet = GetStyleSheet();
   717   NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
   719   if (aIndex > uint32_t(mRules.Count()))
   720     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   722   NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
   723                "Too many style rules!");
   725   return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
   726 }
   728 nsresult
   729 GroupRule::DeleteRule(uint32_t aIndex)
   730 {
   731   nsCSSStyleSheet* sheet = GetStyleSheet();
   732   NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
   734   if (aIndex >= uint32_t(mRules.Count()))
   735     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   737   NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
   738                "Too many style rules!");
   740   return sheet->DeleteRuleFromGroup(this, aIndex);
   741 }
   743 /* virtual */ size_t
   744 GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   745 {
   746   return mRules.SizeOfExcludingThis(Rule::SizeOfCOMArrayElementIncludingThis,
   747                                     aMallocSizeOf);
   749   // Measurement of the following members may be added later if DMD finds it is
   750   // worthwhile:
   751   // - mRuleCollection
   752 }
   755 // -------------------------------------------
   756 // nsICSSMediaRule
   757 //
   758 MediaRule::MediaRule()
   759 {
   760 }
   762 MediaRule::MediaRule(const MediaRule& aCopy)
   763   : GroupRule(aCopy)
   764 {
   765   if (aCopy.mMedia) {
   766     mMedia = aCopy.mMedia->Clone();
   767     // XXXldb This doesn't really make sense.
   768     mMedia->SetStyleSheet(aCopy.GetStyleSheet());
   769   }
   770 }
   772 MediaRule::~MediaRule()
   773 {
   774   if (mMedia) {
   775     mMedia->SetStyleSheet(nullptr);
   776   }
   777 }
   779 NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule)
   780 NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule)
   782 // QueryInterface implementation for MediaRule
   783 NS_INTERFACE_MAP_BEGIN(MediaRule)
   784   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   785   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
   786   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
   787   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
   788   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
   789   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
   790   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
   791 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
   793 /* virtual */ void
   794 MediaRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
   795 {
   796   if (mMedia) {
   797     // Set to null so it knows it's leaving one sheet and joining another.
   798     mMedia->SetStyleSheet(nullptr);
   799     mMedia->SetStyleSheet(aSheet);
   800   }
   802   GroupRule::SetStyleSheet(aSheet);
   803 }
   805 #ifdef DEBUG
   806 /* virtual */ void
   807 MediaRule::List(FILE* out, int32_t aIndent) const
   808 {
   809   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
   811   nsAutoString  buffer;
   813   fputs("@media ", out);
   815   if (mMedia) {
   816     nsAutoString mediaText;
   817     mMedia->GetText(mediaText);
   818     fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
   819   }
   821   GroupRule::List(out, aIndent);
   822 }
   823 #endif
   825 /* virtual */ int32_t
   826 MediaRule::GetType() const
   827 {
   828   return Rule::MEDIA_RULE;
   829 }
   831 /* virtual */ already_AddRefed<Rule>
   832 MediaRule::Clone() const
   833 {
   834   nsRefPtr<Rule> clone = new MediaRule(*this);
   835   return clone.forget();
   836 }
   838 nsresult
   839 MediaRule::SetMedia(nsMediaList* aMedia)
   840 {
   841   mMedia = aMedia;
   842   if (aMedia)
   843     mMedia->SetStyleSheet(GetStyleSheet());
   844   return NS_OK;
   845 }
   847 // nsIDOMCSSRule methods
   848 NS_IMETHODIMP
   849 MediaRule::GetType(uint16_t* aType)
   850 {
   851   *aType = nsIDOMCSSRule::MEDIA_RULE;
   852   return NS_OK;
   853 }
   855 NS_IMETHODIMP
   856 MediaRule::GetCssText(nsAString& aCssText)
   857 {
   858   aCssText.AssignLiteral("@media ");
   859   AppendConditionText(aCssText);
   860   GroupRule::AppendRulesToCssText(aCssText);
   861   return NS_OK;
   862 }
   864 NS_IMETHODIMP
   865 MediaRule::SetCssText(const nsAString& aCssText)
   866 {
   867   return NS_ERROR_NOT_IMPLEMENTED;
   868 }
   870 NS_IMETHODIMP
   871 MediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
   872 {
   873   return GroupRule::GetParentStyleSheet(aSheet);
   874 }
   876 NS_IMETHODIMP
   877 MediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
   878 {
   879   return GroupRule::GetParentRule(aParentRule);
   880 }
   882 // nsIDOMCSSGroupingRule methods
   883 NS_IMETHODIMP
   884 MediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
   885 {
   886   return GroupRule::GetCssRules(aRuleList);
   887 }
   889 NS_IMETHODIMP
   890 MediaRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
   891 {
   892   return GroupRule::InsertRule(aRule, aIndex, _retval);
   893 }
   895 NS_IMETHODIMP
   896 MediaRule::DeleteRule(uint32_t aIndex)
   897 {
   898   return GroupRule::DeleteRule(aIndex);
   899 }
   901 // nsIDOMCSSConditionRule methods
   902 NS_IMETHODIMP
   903 MediaRule::GetConditionText(nsAString& aConditionText)
   904 {
   905   aConditionText.Truncate(0);
   906   AppendConditionText(aConditionText);
   907   return NS_OK;
   908 }
   910 NS_IMETHODIMP
   911 MediaRule::SetConditionText(const nsAString& aConditionText)
   912 {
   913   if (!mMedia) {
   914     nsRefPtr<nsMediaList> media = new nsMediaList();
   915     media->SetStyleSheet(GetStyleSheet());
   916     nsresult rv = media->SetMediaText(aConditionText);
   917     if (NS_SUCCEEDED(rv)) {
   918       mMedia = media;
   919     }
   920     return rv;
   921   }
   923   return mMedia->SetMediaText(aConditionText);
   924 }
   926 // nsIDOMCSSMediaRule methods
   927 NS_IMETHODIMP
   928 MediaRule::GetMedia(nsIDOMMediaList* *aMedia)
   929 {
   930   NS_ENSURE_ARG_POINTER(aMedia);
   931   NS_IF_ADDREF(*aMedia = mMedia);
   932   return NS_OK;
   933 }
   935 // GroupRule interface
   936 /* virtual */ bool
   937 MediaRule::UseForPresentation(nsPresContext* aPresContext,
   938                                    nsMediaQueryResultCacheKey& aKey)
   939 {
   940   if (mMedia) {
   941     return mMedia->Matches(aPresContext, &aKey);
   942   }
   943   return true;
   944 }
   946 /* virtual */ size_t
   947 MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   948 {
   949   size_t n = aMallocSizeOf(this);
   950   n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
   952   // Measurement of the following members may be added later if DMD finds it is
   953   // worthwhile:
   954   // - mMedia
   956   return n;
   957 }
   959 void
   960 MediaRule::AppendConditionText(nsAString& aOutput)
   961 {
   962   if (mMedia) {
   963     nsAutoString mediaText;
   964     mMedia->GetText(mediaText);
   965     aOutput.Append(mediaText);
   966   }
   967 }
   969 } // namespace css
   970 } // namespace mozilla
   972 // Must be outside namespace
   973 DOMCI_DATA(CSSMediaRule, css::MediaRule)
   975 namespace mozilla {
   976 namespace css {
   978 DocumentRule::DocumentRule()
   979 {
   980 }
   982 DocumentRule::DocumentRule(const DocumentRule& aCopy)
   983   : GroupRule(aCopy)
   984   , mURLs(new URL(*aCopy.mURLs))
   985 {
   986 }
   988 DocumentRule::~DocumentRule()
   989 {
   990 }
   992 NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule)
   993 NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule)
   995 // QueryInterface implementation for DocumentRule
   996 NS_INTERFACE_MAP_BEGIN(DocumentRule)
   997   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   998   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
   999   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
  1000   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
  1001   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
  1002   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  1003   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
  1004 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
  1006 #ifdef DEBUG
  1007 /* virtual */ void
  1008 DocumentRule::List(FILE* out, int32_t aIndent) const
  1010   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
  1012   nsAutoCString str;
  1013   str.AssignLiteral("@-moz-document ");
  1014   for (URL *url = mURLs; url; url = url->next) {
  1015     switch (url->func) {
  1016       case eURL:
  1017         str.AppendLiteral("url(\"");
  1018         break;
  1019       case eURLPrefix:
  1020         str.AppendLiteral("url-prefix(\"");
  1021         break;
  1022       case eDomain:
  1023         str.AppendLiteral("domain(\"");
  1024         break;
  1025       case eRegExp:
  1026         str.AppendLiteral("regexp(\"");
  1027         break;
  1029     nsAutoCString escapedURL(url->url);
  1030     escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
  1031     str.Append(escapedURL);
  1032     str.AppendLiteral("\"), ");
  1034   str.Cut(str.Length() - 2, 1); // remove last ,
  1035   fputs(str.get(), out);
  1037   GroupRule::List(out, aIndent);
  1039 #endif
  1041 /* virtual */ int32_t
  1042 DocumentRule::GetType() const
  1044   return Rule::DOCUMENT_RULE;
  1047 /* virtual */ already_AddRefed<Rule>
  1048 DocumentRule::Clone() const
  1050   nsRefPtr<Rule> clone = new DocumentRule(*this);
  1051   return clone.forget();
  1054 // nsIDOMCSSRule methods
  1055 NS_IMETHODIMP
  1056 DocumentRule::GetType(uint16_t* aType)
  1058   // XXX What should really happen here?
  1059   *aType = nsIDOMCSSRule::UNKNOWN_RULE;
  1060   return NS_OK;
  1063 NS_IMETHODIMP
  1064 DocumentRule::GetCssText(nsAString& aCssText)
  1066   aCssText.AssignLiteral("@-moz-document ");
  1067   AppendConditionText(aCssText);
  1068   GroupRule::AppendRulesToCssText(aCssText);
  1069   return NS_OK;
  1072 NS_IMETHODIMP
  1073 DocumentRule::SetCssText(const nsAString& aCssText)
  1075   return NS_ERROR_NOT_IMPLEMENTED;
  1078 NS_IMETHODIMP
  1079 DocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  1081   return GroupRule::GetParentStyleSheet(aSheet);
  1084 NS_IMETHODIMP
  1085 DocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  1087   return GroupRule::GetParentRule(aParentRule);
  1090 // nsIDOMCSSGroupingRule methods
  1091 NS_IMETHODIMP
  1092 DocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
  1094   return GroupRule::GetCssRules(aRuleList);
  1097 NS_IMETHODIMP
  1098 DocumentRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
  1100   return GroupRule::InsertRule(aRule, aIndex, _retval);
  1103 NS_IMETHODIMP
  1104 DocumentRule::DeleteRule(uint32_t aIndex)
  1106   return GroupRule::DeleteRule(aIndex);
  1109 // nsIDOMCSSConditionRule methods
  1110 NS_IMETHODIMP
  1111 DocumentRule::GetConditionText(nsAString& aConditionText)
  1113   aConditionText.Truncate(0);
  1114   AppendConditionText(aConditionText);
  1115   return NS_OK;
  1118 NS_IMETHODIMP
  1119 DocumentRule::SetConditionText(const nsAString& aConditionText)
  1121   return NS_ERROR_NOT_IMPLEMENTED;
  1124 // GroupRule interface
  1125 /* virtual */ bool
  1126 DocumentRule::UseForPresentation(nsPresContext* aPresContext,
  1127                                  nsMediaQueryResultCacheKey& aKey)
  1129   nsIDocument *doc = aPresContext->Document();
  1130   nsIURI *docURI = doc->GetDocumentURI();
  1131   nsAutoCString docURISpec;
  1132   if (docURI)
  1133     docURI->GetSpec(docURISpec);
  1135   for (URL *url = mURLs; url; url = url->next) {
  1136     switch (url->func) {
  1137       case eURL: {
  1138         if (docURISpec == url->url)
  1139           return true;
  1140       } break;
  1141       case eURLPrefix: {
  1142         if (StringBeginsWith(docURISpec, url->url))
  1143           return true;
  1144       } break;
  1145       case eDomain: {
  1146         nsAutoCString host;
  1147         if (docURI)
  1148           docURI->GetHost(host);
  1149         int32_t lenDiff = host.Length() - url->url.Length();
  1150         if (lenDiff == 0) {
  1151           if (host == url->url)
  1152             return true;
  1153         } else {
  1154           if (StringEndsWith(host, url->url) &&
  1155               host.CharAt(lenDiff - 1) == '.')
  1156             return true;
  1158       } break;
  1159       case eRegExp: {
  1160         NS_ConvertUTF8toUTF16 spec(docURISpec);
  1161         NS_ConvertUTF8toUTF16 regex(url->url);
  1162         if (nsContentUtils::IsPatternMatching(spec, regex, doc)) {
  1163           return true;
  1165       } break;
  1169   return false;
  1172 DocumentRule::URL::~URL()
  1174   NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
  1177 /* virtual */ size_t
  1178 DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  1180   size_t n = aMallocSizeOf(this);
  1181   n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
  1183   // Measurement of the following members may be added later if DMD finds it is
  1184   // worthwhile:
  1185   // - mURLs
  1187   return n;
  1190 void
  1191 DocumentRule::AppendConditionText(nsAString& aCssText)
  1193   for (URL *url = mURLs; url; url = url->next) {
  1194     switch (url->func) {
  1195       case eURL:
  1196         aCssText.AppendLiteral("url(");
  1197         break;
  1198       case eURLPrefix:
  1199         aCssText.AppendLiteral("url-prefix(");
  1200         break;
  1201       case eDomain:
  1202         aCssText.AppendLiteral("domain(");
  1203         break;
  1204       case eRegExp:
  1205         aCssText.AppendLiteral("regexp(");
  1206         break;
  1208     nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
  1209                                         aCssText);
  1210     aCssText.AppendLiteral("), ");
  1212   aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
  1215 } // namespace css
  1216 } // namespace mozilla
  1218 // Must be outside namespace
  1219 DOMCI_DATA(CSSMozDocumentRule, css::DocumentRule)
  1221 // -------------------------------------------
  1222 // NameSpaceRule
  1223 //
  1225 namespace mozilla {
  1226 namespace css {
  1228 NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec)
  1229   : Rule(),
  1230     mPrefix(aPrefix),
  1231     mURLSpec(aURLSpec)
  1235 NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
  1236   : Rule(aCopy),
  1237     mPrefix(aCopy.mPrefix),
  1238     mURLSpec(aCopy.mURLSpec)
  1242 NameSpaceRule::~NameSpaceRule()
  1246 NS_IMPL_ADDREF(NameSpaceRule)
  1247 NS_IMPL_RELEASE(NameSpaceRule)
  1249 // QueryInterface implementation for NameSpaceRule
  1250 NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
  1251   if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) {
  1252     *aInstancePtr = this;
  1253     NS_ADDREF_THIS();
  1254     return NS_OK;
  1256   else
  1257   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  1258   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  1259   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  1260   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule)
  1261 NS_INTERFACE_MAP_END
  1263 IMPL_STYLE_RULE_INHERIT(NameSpaceRule, Rule)
  1265 #ifdef DEBUG
  1266 /* virtual */ void
  1267 NameSpaceRule::List(FILE* out, int32_t aIndent) const
  1269   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
  1271   nsAutoString  buffer;
  1273   fputs("@namespace ", out);
  1275   if (mPrefix) {
  1276     mPrefix->ToString(buffer);
  1277     fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
  1278     fputs(" ", out);
  1281   fputs("url(", out);
  1282   fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
  1283   fputs(")\n", out);
  1285 #endif
  1287 /* virtual */ int32_t
  1288 NameSpaceRule::GetType() const
  1290   return Rule::NAMESPACE_RULE;
  1293 /* virtual */ already_AddRefed<Rule>
  1294 NameSpaceRule::Clone() const
  1296   nsRefPtr<Rule> clone = new NameSpaceRule(*this);
  1297   return clone.forget();
  1300 NS_IMETHODIMP
  1301 NameSpaceRule::GetType(uint16_t* aType)
  1303   *aType = nsIDOMCSSRule::NAMESPACE_RULE;
  1304   return NS_OK;
  1307 NS_IMETHODIMP
  1308 NameSpaceRule::GetCssText(nsAString& aCssText)
  1310   aCssText.AssignLiteral("@namespace ");
  1311   if (mPrefix) {
  1312     aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
  1314   aCssText.AppendLiteral("url(");
  1315   nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
  1316   aCssText.Append(NS_LITERAL_STRING(");"));
  1317   return NS_OK;
  1320 NS_IMETHODIMP
  1321 NameSpaceRule::SetCssText(const nsAString& aCssText)
  1323   return NS_ERROR_NOT_IMPLEMENTED;
  1326 NS_IMETHODIMP
  1327 NameSpaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  1329   return Rule::GetParentStyleSheet(aSheet);
  1332 NS_IMETHODIMP
  1333 NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  1335   return Rule::GetParentRule(aParentRule);
  1338 /* virtual */ size_t
  1339 NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  1341   return aMallocSizeOf(this);
  1343   // Measurement of the following members may be added later if DMD finds it is
  1344   // worthwhile:
  1345   // - mPrefix
  1346   // - mURLSpec
  1350 } // namespace css
  1351 } // namespace mozilla
  1353 // Must be outside namespace
  1354 DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule)
  1356 // -------------------------------------------
  1357 // nsCSSFontFaceStyleDecl and related routines
  1358 //
  1360 // A src: descriptor is represented as an array value; each entry in
  1361 // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
  1362 // eCSSUnit_Font_Format.  Blocks of eCSSUnit_Font_Format may appear
  1363 // only after one of the first two.  (css3-fonts only contemplates
  1364 // annotating URLs with formats, but we handle the general case.)
  1365 static void
  1366 AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult)
  1368   NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array,
  1369                   "improper value unit for src:");
  1371   const nsCSSValue::Array& sources = *src.GetArrayValue();
  1372   size_t i = 0;
  1374   while (i < sources.Count()) {
  1375     nsAutoString formats;
  1377     if (sources[i].GetUnit() == eCSSUnit_URL) {
  1378       aResult.AppendLiteral("url(");
  1379       nsDependentString url(sources[i].GetOriginalURLValue());
  1380       nsStyleUtil::AppendEscapedCSSString(url, aResult);
  1381       aResult.AppendLiteral(")");
  1382     } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
  1383       aResult.AppendLiteral("local(");
  1384       nsDependentString local(sources[i].GetStringBufferValue());
  1385       nsStyleUtil::AppendEscapedCSSString(local, aResult);
  1386       aResult.AppendLiteral(")");
  1387     } else {
  1388       NS_NOTREACHED("entry in src: descriptor with improper unit");
  1389       i++;
  1390       continue;
  1393     i++;
  1394     formats.Truncate();
  1395     while (i < sources.Count() &&
  1396            sources[i].GetUnit() == eCSSUnit_Font_Format) {
  1397       formats.Append('"');
  1398       formats.Append(sources[i].GetStringBufferValue());
  1399       formats.AppendLiteral("\", ");
  1400       i++;
  1402     if (formats.Length() > 0) {
  1403       formats.Truncate(formats.Length() - 2); // remove the last comma
  1404       aResult.AppendLiteral(" format(");
  1405       aResult.Append(formats);
  1406       aResult.Append(')');
  1408     aResult.AppendLiteral(", ");
  1410   aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
  1413 // print all characters with at least four hex digits
  1414 static void
  1415 AppendSerializedUnicodePoint(uint32_t aCode, nsACString &aBuf)
  1417   aBuf.Append(nsPrintfCString("%04X", aCode));
  1420 // A unicode-range: descriptor is represented as an array of integers,
  1421 // to be interpreted as a sequence of pairs: min max min max ...
  1422 // It is in source order.  (Possibly it should be sorted and overlaps
  1423 // consolidated, but right now we don't do that.)
  1424 static void
  1425 AppendSerializedUnicodeRange(nsCSSValue const & aValue,
  1426                              nsAString & aResult)
  1428   NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null ||
  1429                   aValue.GetUnit() == eCSSUnit_Array,
  1430                   "improper value unit for unicode-range:");
  1431   aResult.Truncate();
  1432   if (aValue.GetUnit() != eCSSUnit_Array)
  1433     return;
  1435   nsCSSValue::Array const & sources = *aValue.GetArrayValue();
  1436   nsAutoCString buf;
  1438   NS_ABORT_IF_FALSE(sources.Count() % 2 == 0,
  1439                     "odd number of entries in a unicode-range: array");
  1441   for (uint32_t i = 0; i < sources.Count(); i += 2) {
  1442     uint32_t min = sources[i].GetIntValue();
  1443     uint32_t max = sources[i+1].GetIntValue();
  1445     // We don't try to replicate the U+XX?? notation.
  1446     buf.AppendLiteral("U+");
  1447     AppendSerializedUnicodePoint(min, buf);
  1449     if (min != max) {
  1450       buf.Append('-');
  1451       AppendSerializedUnicodePoint(max, buf);
  1453     buf.AppendLiteral(", ");
  1455   buf.Truncate(buf.Length() - 2); // remove the last comma-space
  1456   CopyASCIItoUTF16(buf, aResult);
  1459 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
  1460 nsCSSValue nsCSSFontFaceStyleDecl::* const
  1461 nsCSSFontFaceStyleDecl::Fields[] = {
  1462 #define CSS_FONT_DESC(name_, method_) &nsCSSFontFaceStyleDecl::m##method_,
  1463 #include "nsCSSFontDescList.h"
  1464 #undef CSS_FONT_DESC
  1465 };
  1467 // QueryInterface implementation for nsCSSFontFaceStyleDecl
  1468 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
  1469   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  1470   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
  1471   NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
  1472   NS_INTERFACE_MAP_ENTRY(nsISupports)
  1473   // We forward the cycle collection interfaces to ContainingRule(), which is
  1474   // never null (in fact, we're part of that object!)
  1475   if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
  1476       aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
  1477     return ContainingRule()->QueryInterface(aIID, aInstancePtr);
  1479   else
  1480 NS_INTERFACE_MAP_END
  1482 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
  1483 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
  1485 // helper for string GetPropertyValue and RemovePropertyValue
  1486 nsresult
  1487 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
  1488                                          nsAString & aResult) const
  1490   NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
  1491                       eCSSFontDesc_COUNT - 1);
  1493   aResult.Truncate();
  1494   if (aFontDescID == eCSSFontDesc_UNKNOWN)
  1495     return NS_OK;
  1497   const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID];
  1499   if (val.GetUnit() == eCSSUnit_Null) {
  1500     // Avoid having to check no-value in the Family and Src cases below.
  1501     return NS_OK;
  1504   switch (aFontDescID) {
  1505   case eCSSFontDesc_Family: {
  1506       // we don't use nsCSSValue::AppendToString here because it doesn't
  1507       // canonicalize the way we want, and anyway it's overkill when
  1508       // we know we have eCSSUnit_String
  1509       NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
  1510       nsDependentString family(val.GetStringBufferValue());
  1511       nsStyleUtil::AppendEscapedCSSString(family, aResult);
  1512       return NS_OK;
  1515   case eCSSFontDesc_Style:
  1516     val.AppendToString(eCSSProperty_font_style, aResult,
  1517                         nsCSSValue::eNormalized);
  1518     return NS_OK;
  1520   case eCSSFontDesc_Weight:
  1521     val.AppendToString(eCSSProperty_font_weight, aResult,
  1522                        nsCSSValue::eNormalized);
  1523     return NS_OK;
  1525   case eCSSFontDesc_Stretch:
  1526     val.AppendToString(eCSSProperty_font_stretch, aResult,
  1527                        nsCSSValue::eNormalized);
  1528     return NS_OK;
  1530   case eCSSFontDesc_FontFeatureSettings:
  1531     nsStyleUtil::AppendFontFeatureSettings(val, aResult);
  1532     return NS_OK;
  1534   case eCSSFontDesc_FontLanguageOverride:
  1535     val.AppendToString(eCSSProperty_font_language_override, aResult,
  1536                        nsCSSValue::eNormalized);
  1537     return NS_OK;
  1539   case eCSSFontDesc_Src:
  1540     AppendSerializedFontSrc(val, aResult);
  1541     return NS_OK;
  1543   case eCSSFontDesc_UnicodeRange:
  1544     AppendSerializedUnicodeRange(val, aResult);
  1545     return NS_OK;
  1547   case eCSSFontDesc_UNKNOWN:
  1548   case eCSSFontDesc_COUNT:
  1551   NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
  1552                 "out-of-range value got to the switch");
  1553   return NS_ERROR_INVALID_ARG;
  1557 // attribute DOMString cssText;
  1558 NS_IMETHODIMP
  1559 nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
  1561   nsAutoString descStr;
  1563   aCssText.Truncate();
  1564   for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
  1565        id < eCSSFontDesc_COUNT;
  1566        id = nsCSSFontDesc(id + 1)) {
  1567     if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
  1568           != eCSSUnit_Null &&
  1569         NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
  1570       NS_ASSERTION(descStr.Length() > 0,
  1571                    "GetCssText: non-null unit, empty property value");
  1572       aCssText.AppendLiteral("  ");
  1573       aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
  1574       aCssText.AppendLiteral(": ");
  1575       aCssText.Append(descStr);
  1576       aCssText.AppendLiteral(";\n");
  1579   return NS_OK;
  1582 NS_IMETHODIMP
  1583 nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
  1585   return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
  1588 // DOMString getPropertyValue (in DOMString propertyName);
  1589 NS_IMETHODIMP
  1590 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
  1591                                          nsAString & aResult)
  1593   return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
  1596 NS_IMETHODIMP
  1597 nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName,
  1598                                                  nsAString& aResult)
  1600   // We don't return any authored property values different from
  1601   // GetPropertyValue, currently.
  1602   return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
  1605 // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
  1606 already_AddRefed<dom::CSSValue>
  1607 nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
  1608                                             ErrorResult& aRv)
  1610   // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
  1611   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
  1612   return nullptr;
  1615 // DOMString removeProperty (in DOMString propertyName) raises (DOMException);
  1616 NS_IMETHODIMP
  1617 nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
  1618                                        nsAString & aResult)
  1620   nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
  1621   NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
  1622                descID < eCSSFontDesc_COUNT,
  1623                "LookupFontDesc returned value out of range");
  1625   if (descID == eCSSFontDesc_UNKNOWN) {
  1626     aResult.Truncate();
  1627   } else {
  1628     nsresult rv = GetPropertyValue(descID, aResult);
  1629     NS_ENSURE_SUCCESS(rv, rv);
  1630     (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset();
  1632   return NS_OK;
  1635 // DOMString getPropertyPriority (in DOMString propertyName);
  1636 NS_IMETHODIMP
  1637 nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
  1638                                             nsAString & aResult)
  1640   // font descriptors do not have priorities at present
  1641   aResult.Truncate();
  1642   return NS_OK;
  1645 // void setProperty (in DOMString propertyName, in DOMString value,
  1646 //                   in DOMString priority)  raises (DOMException);
  1647 NS_IMETHODIMP
  1648 nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
  1649                                     const nsAString & value,
  1650                                     const nsAString & priority)
  1652   return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
  1655 // readonly attribute unsigned long length;
  1656 NS_IMETHODIMP
  1657 nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength)
  1659   uint32_t len = 0;
  1660   for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
  1661        id < eCSSFontDesc_COUNT;
  1662        id = nsCSSFontDesc(id + 1))
  1663     if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null)
  1664       len++;
  1666   *aLength = len;
  1667   return NS_OK;
  1670 // DOMString item (in unsigned long index);
  1671 NS_IMETHODIMP
  1672 nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn)
  1674   bool found;
  1675   IndexedGetter(aIndex, found, aReturn);
  1676   if (!found) {
  1677     aReturn.Truncate();
  1679   return NS_OK;
  1682 void
  1683 nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult)
  1685   int32_t nset = -1;
  1686   for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
  1687        id < eCSSFontDesc_COUNT;
  1688        id = nsCSSFontDesc(id + 1)) {
  1689     if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
  1690         != eCSSUnit_Null) {
  1691       nset++;
  1692       if (nset == int32_t(index)) {
  1693         aFound = true;
  1694         aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
  1695         return;
  1699   aFound = false;
  1702 // readonly attribute nsIDOMCSSRule parentRule;
  1703 NS_IMETHODIMP
  1704 nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
  1706   NS_IF_ADDREF(*aParentRule = ContainingRule()->GetDOMRule());
  1707   return NS_OK;
  1710 NS_IMETHODIMP
  1711 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSProperty aPropID,
  1712                                          nsAString& aValue)
  1714   return
  1715     GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
  1716                      aValue);
  1719 NS_IMETHODIMP
  1720 nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSProperty aPropID,
  1721                                          const nsAString& aValue)
  1723   return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
  1724                      aValue, EmptyString());
  1727 nsINode*
  1728 nsCSSFontFaceStyleDecl::GetParentObject()
  1730   return ContainingRule()->GetDocument();
  1733 JSObject*
  1734 nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx)
  1736   return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this);
  1739 // -------------------------------------------
  1740 // nsCSSFontFaceRule
  1741 // 
  1743 /* virtual */ already_AddRefed<css::Rule>
  1744 nsCSSFontFaceRule::Clone() const
  1746   nsRefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
  1747   return clone.forget();
  1750 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSFontFaceRule)
  1751 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSFontFaceRule)
  1753 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSFontFaceRule)
  1755 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule)
  1756   // Trace the wrapper for our declaration.  This just expands out
  1757   // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
  1758   // directly because the wrapper is on the declaration, not on us.
  1759   tmp->mDecl.TraceWrapper(aCallbacks, aClosure);
  1760 NS_IMPL_CYCLE_COLLECTION_TRACE_END
  1762 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule)
  1763   // Unlink the wrapper for our declaraton.  This just expands out
  1764   // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
  1765   // directly because the wrapper is on the declaration, not on us.
  1766   tmp->mDecl.ReleaseWrapper(static_cast<nsISupports*>(p));
  1767 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  1769 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule)
  1770   // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call
  1771   // into our Trace hook, where we do the right thing with declarations
  1772   // already.
  1773   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
  1774 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  1776 DOMCI_DATA(CSSFontFaceRule, nsCSSFontFaceRule)
  1778 // QueryInterface implementation for nsCSSFontFaceRule
  1779 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSFontFaceRule)
  1780   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  1781   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
  1782   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  1783   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  1784   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule)
  1785 NS_INTERFACE_MAP_END
  1787 IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, Rule)
  1789 #ifdef DEBUG
  1790 void
  1791 nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const
  1793   nsCString baseInd, descInd;
  1794   for (int32_t indent = aIndent; --indent >= 0; ) {
  1795     baseInd.AppendLiteral("  ");
  1796     descInd.AppendLiteral("  ");
  1798   descInd.AppendLiteral("  ");
  1800   nsString descStr;
  1802   fprintf(out, "%s@font-face {\n", baseInd.get());
  1803   for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
  1804        id < eCSSFontDesc_COUNT;
  1805        id = nsCSSFontDesc(id + 1))
  1806     if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
  1807         != eCSSUnit_Null) {
  1808       if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
  1809         descStr.AssignLiteral("#<serialization error>");
  1810       else if (descStr.Length() == 0)
  1811         descStr.AssignLiteral("#<serialization missing>");
  1812       fprintf(out, "%s%s: %s\n",
  1813               descInd.get(), nsCSSProps::GetStringValue(id).get(),
  1814               NS_ConvertUTF16toUTF8(descStr).get());
  1816   fprintf(out, "%s}\n", baseInd.get());
  1818 #endif
  1820 /* virtual */ int32_t
  1821 nsCSSFontFaceRule::GetType() const
  1823   return Rule::FONT_FACE_RULE;
  1826 NS_IMETHODIMP
  1827 nsCSSFontFaceRule::GetType(uint16_t* aType)
  1829   *aType = nsIDOMCSSRule::FONT_FACE_RULE;
  1830   return NS_OK;
  1833 NS_IMETHODIMP
  1834 nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
  1836   nsAutoString propText;
  1837   mDecl.GetCssText(propText);
  1839   aCssText.AssignLiteral("@font-face {\n");
  1840   aCssText.Append(propText);
  1841   aCssText.Append('}');
  1842   return NS_OK;
  1845 NS_IMETHODIMP
  1846 nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
  1848   return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
  1851 NS_IMETHODIMP
  1852 nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  1854   return Rule::GetParentStyleSheet(aSheet);
  1857 NS_IMETHODIMP
  1858 nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  1860   return Rule::GetParentRule(aParentRule);
  1863 NS_IMETHODIMP
  1864 nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
  1866   NS_IF_ADDREF(*aStyle = &mDecl);
  1867   return NS_OK;
  1870 // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
  1871 void
  1872 nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
  1874   NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
  1875                   aDescID < eCSSFontDesc_COUNT,
  1876                   "aDescID out of range in nsCSSFontFaceRule::SetDesc");
  1878   // FIXME: handle dynamic changes
  1880   mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue;
  1883 void
  1884 nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
  1886   NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
  1887                   aDescID < eCSSFontDesc_COUNT,
  1888                   "aDescID out of range in nsCSSFontFaceRule::GetDesc");
  1890   aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];
  1893 /* virtual */ size_t
  1894 nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  1896   return aMallocSizeOf(this);
  1898   // Measurement of the following members may be added later if DMD finds it is
  1899   // worthwhile:
  1900   // - mDecl
  1904 // -----------------------------------
  1905 // nsCSSFontFeatureValuesRule
  1906 //
  1908 /* virtual */ already_AddRefed<css::Rule>
  1909 nsCSSFontFeatureValuesRule::Clone() const
  1911   nsRefPtr<css::Rule> clone = new nsCSSFontFeatureValuesRule(*this);
  1912   return clone.forget();
  1915 NS_IMPL_ADDREF(nsCSSFontFeatureValuesRule)
  1916 NS_IMPL_RELEASE(nsCSSFontFeatureValuesRule)
  1918 DOMCI_DATA(CSSFontFeatureValuesRule, nsCSSFontFeatureValuesRule)
  1920 // QueryInterface implementation for nsCSSFontFeatureValuesRule
  1921 NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule)
  1922   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  1923   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
  1924   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  1925   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  1926   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFeatureValuesRule)
  1927 NS_INTERFACE_MAP_END
  1929 IMPL_STYLE_RULE_INHERIT(nsCSSFontFeatureValuesRule, Rule)
  1931 static void
  1932 FamilyListToString(const nsTArray<nsString>& aFamilyList, nsAString& aOutStr)
  1934   uint32_t i, n = aFamilyList.Length();
  1936   for (i = 0; i < n; i++) {
  1937     nsStyleUtil::AppendEscapedCSSString(aFamilyList[i], aOutStr);
  1938     if (i != n - 1) {
  1939       aOutStr.AppendLiteral(", ");
  1944 static void
  1945 FeatureValuesToString(
  1946   const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
  1947   nsAString& aOutStr)
  1949   uint32_t i, n;
  1951   // append values
  1952   n = aFeatureValues.Length();
  1953   for (i = 0; i < n; i++) {
  1954     const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i];
  1956     // @alternate
  1957     aOutStr.AppendLiteral("  @");
  1958     nsAutoString functAlt;
  1959     nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt);
  1960     aOutStr.Append(functAlt);
  1961     aOutStr.AppendLiteral(" {");
  1963     // for each ident-values tuple
  1964     uint32_t j, numValues = fv.valuelist.Length();
  1965     for (j = 0; j < numValues; j++) {
  1966       aOutStr.AppendLiteral(" ");
  1967       const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j];
  1968       nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr);
  1969       aOutStr.AppendLiteral(":");
  1971       uint32_t k, numSelectors = vlist.featureSelectors.Length();
  1972       for (k = 0; k < numSelectors; k++) {
  1973         aOutStr.AppendLiteral(" ");
  1974         aOutStr.AppendInt(vlist.featureSelectors[k]);
  1977       aOutStr.AppendLiteral(";");
  1979     aOutStr.AppendLiteral(" }\n");
  1983 static void
  1984 FontFeatureValuesRuleToString(
  1985   const nsTArray<nsString>& aFamilyList,
  1986   const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
  1987   nsAString& aOutStr)
  1989   aOutStr.AssignLiteral("@font-feature-values ");
  1990   nsAutoString familyListStr, valueTextStr;
  1991   FamilyListToString(aFamilyList, familyListStr);
  1992   aOutStr.Append(familyListStr);
  1993   aOutStr.AppendLiteral(" {\n");
  1994   FeatureValuesToString(aFeatureValues, valueTextStr);
  1995   aOutStr.Append(valueTextStr);
  1996   aOutStr.AppendLiteral("}");
  1999 #ifdef DEBUG
  2000 void
  2001 nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const
  2003   nsAutoString text;
  2004   FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text);
  2005   NS_ConvertUTF16toUTF8 utf8(text);
  2007   // replace newlines with newlines plus indent spaces
  2008   char* indent = new char[(aIndent + 1) * 2];
  2009   int32_t i;
  2010   for (i = 1; i < (aIndent + 1) * 2 - 1; i++) {
  2011     indent[i] = 0x20;
  2013   indent[0] = 0xa;
  2014   indent[aIndent * 2 + 1] = 0;
  2015   utf8.ReplaceSubstring("\n", indent);
  2016   delete [] indent;
  2018   for (i = aIndent; --i >= 0; ) fputs("  ", out);
  2019   fprintf(out, "%s\n", utf8.get());
  2021 #endif
  2023 /* virtual */ int32_t
  2024 nsCSSFontFeatureValuesRule::GetType() const
  2026   return Rule::FONT_FEATURE_VALUES_RULE;
  2029 NS_IMETHODIMP
  2030 nsCSSFontFeatureValuesRule::GetType(uint16_t* aType)
  2032   *aType = nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE;
  2033   return NS_OK;
  2036 NS_IMETHODIMP
  2037 nsCSSFontFeatureValuesRule::GetCssText(nsAString& aCssText)
  2039   FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText);
  2040   return NS_OK;
  2043 NS_IMETHODIMP
  2044 nsCSSFontFeatureValuesRule::SetCssText(const nsAString& aCssText)
  2046   // FIXME: implement???
  2047   return NS_ERROR_NOT_IMPLEMENTED;
  2050 NS_IMETHODIMP
  2051 nsCSSFontFeatureValuesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  2053   return Rule::GetParentStyleSheet(aSheet);
  2056 NS_IMETHODIMP
  2057 nsCSSFontFeatureValuesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  2059   return Rule::GetParentRule(aParentRule);
  2062 NS_IMETHODIMP
  2063 nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFontFamily)
  2065   FamilyListToString(mFamilyList, aFontFamily);
  2066   return NS_OK;
  2069 NS_IMETHODIMP
  2070 nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily)
  2072   return NS_ERROR_NOT_IMPLEMENTED;
  2075 NS_IMETHODIMP
  2076 nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText)
  2078   FeatureValuesToString(mFeatureValues, aValueText);
  2079   return NS_OK;
  2082 NS_IMETHODIMP
  2083 nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText)
  2085   return NS_ERROR_NOT_IMPLEMENTED;
  2088 struct MakeFamilyArray {
  2089   MakeFamilyArray(nsTArray<nsString>& aFamilyArray)
  2090     : familyArray(aFamilyArray), hasGeneric(false)
  2091   {}
  2093   static bool
  2094   AddFamily(const nsString& aFamily, bool aGeneric, void* aData)
  2096     MakeFamilyArray *familyArr = reinterpret_cast<MakeFamilyArray*> (aData);
  2097     if (!aGeneric && !aFamily.IsEmpty()) {
  2098       familyArr->familyArray.AppendElement(aFamily);
  2100     if (aGeneric) {
  2101       familyArr->hasGeneric = true;
  2103     return true;
  2106   nsTArray<nsString>& familyArray;
  2107   bool hasGeneric;
  2108 };
  2110 void
  2111 nsCSSFontFeatureValuesRule::SetFamilyList(const nsAString& aFamilyList,
  2112                                           bool& aContainsGeneric)
  2114   nsFont font(aFamilyList, 0, 0, 0, 0, 0, 0);
  2115   MakeFamilyArray families(mFamilyList);
  2116   font.EnumerateFamilies(MakeFamilyArray::AddFamily, (void*) &families);
  2117   aContainsGeneric = families.hasGeneric;
  2120 void
  2121 nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
  2122                      nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
  2124   uint32_t i, len = mFeatureValues.Length();
  2125   bool foundAlternate = false;
  2127   // add to an existing list for a given property value
  2128   for (i = 0; i < len; i++) {
  2129     gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i);
  2131     if (f.alternate == uint32_t(aVariantAlternate)) {
  2132       f.valuelist.AppendElements(aValueList);
  2133       foundAlternate = true;
  2134       break;
  2138   // create a new list for a given property value
  2139   if (!foundAlternate) {
  2140     gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement();
  2141     f.alternate = aVariantAlternate;
  2142     f.valuelist.AppendElements(aValueList);
  2146 size_t
  2147 nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
  2148   MallocSizeOf aMallocSizeOf) const
  2150   return aMallocSizeOf(this);
  2153 // -------------------------------------------
  2154 // nsCSSKeyframeStyleDeclaration
  2155 //
  2157 nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
  2158   : mRule(aRule)
  2162 nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration()
  2164   NS_ASSERTION(!mRule, "DropReference not called.");
  2167 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration)
  2168 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration)
  2170 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration)
  2172 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration)
  2173   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  2174 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
  2176 css::Declaration*
  2177 nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(bool aAllocate)
  2179   if (mRule) {
  2180     return mRule->Declaration();
  2181   } else {
  2182     return nullptr;
  2186 void
  2187 nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
  2189   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
  2192 NS_IMETHODIMP
  2193 nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
  2195   NS_ENSURE_ARG_POINTER(aParent);
  2197   NS_IF_ADDREF(*aParent = mRule);
  2198   return NS_OK;
  2201 nsresult
  2202 nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
  2204   NS_ABORT_IF_FALSE(aDecl, "must be non-null");
  2205   mRule->ChangeDeclaration(aDecl);
  2206   return NS_OK;
  2209 nsIDocument*
  2210 nsCSSKeyframeStyleDeclaration::DocToUpdate()
  2212   return nullptr;
  2215 nsINode*
  2216 nsCSSKeyframeStyleDeclaration::GetParentObject()
  2218   return mRule ? mRule->GetDocument() : nullptr;
  2221 // -------------------------------------------
  2222 // nsCSSKeyframeRule
  2223 //
  2225 nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
  2226   // copy everything except our reference count and mDOMDeclaration
  2227   : Rule(aCopy)
  2228   , mKeys(aCopy.mKeys)
  2229   , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
  2233 nsCSSKeyframeRule::~nsCSSKeyframeRule()
  2235   if (mDOMDeclaration) {
  2236     mDOMDeclaration->DropReference();
  2240 /* virtual */ already_AddRefed<css::Rule>
  2241 nsCSSKeyframeRule::Clone() const
  2243   nsRefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
  2244   return clone.forget();
  2247 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule)
  2248 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule)
  2250 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSKeyframeRule)
  2252 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule)
  2253   if (tmp->mDOMDeclaration) {
  2254     tmp->mDOMDeclaration->DropReference();
  2255     tmp->mDOMDeclaration = nullptr;
  2257 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  2258 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule)
  2259   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
  2260 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  2262 DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule)
  2264 // QueryInterface implementation for nsCSSKeyframeRule
  2265 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule)
  2266   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  2267   NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
  2268   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  2269   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  2270   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframeRule)
  2271 NS_INTERFACE_MAP_END
  2273 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule)
  2275 /* virtual */ void
  2276 nsCSSKeyframeRule::MapRuleInfoInto(nsRuleData* aRuleData)
  2278   // We need to implement MapRuleInfoInto because the animation manager
  2279   // constructs a rule node pointing to us in order to compute the
  2280   // styles it needs to animate.
  2282   // The spec says that !important declarations should just be ignored
  2283   NS_ASSERTION(!mDeclaration->HasImportantData(),
  2284                "Keyframe rules has !important data");
  2286   mDeclaration->MapNormalRuleInfoInto(aRuleData);
  2289 #ifdef DEBUG
  2290 void
  2291 nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const
  2293   for (int32_t index = aIndent; --index >= 0; ) fputs("  ", out);
  2295   nsAutoString tmp;
  2296   DoGetKeyText(tmp);
  2297   fputs(NS_ConvertUTF16toUTF8(tmp).get(), out);
  2298   fputs(" ", out);
  2299   mDeclaration->List(out, aIndent);
  2300   fputs("\n", out);
  2302 #endif
  2304 /* virtual */ int32_t
  2305 nsCSSKeyframeRule::GetType() const
  2307   return Rule::KEYFRAME_RULE;
  2310 NS_IMETHODIMP
  2311 nsCSSKeyframeRule::GetType(uint16_t* aType)
  2313   *aType = nsIDOMCSSRule::KEYFRAME_RULE;
  2314   return NS_OK;
  2317 NS_IMETHODIMP
  2318 nsCSSKeyframeRule::GetCssText(nsAString& aCssText)
  2320   DoGetKeyText(aCssText);
  2321   aCssText.AppendLiteral(" { ");
  2322   nsAutoString tmp;
  2323   mDeclaration->ToString(tmp);
  2324   aCssText.Append(tmp);
  2325   aCssText.AppendLiteral(" }");
  2326   return NS_OK;
  2329 NS_IMETHODIMP
  2330 nsCSSKeyframeRule::SetCssText(const nsAString& aCssText)
  2332   // FIXME: implement???
  2333   return NS_ERROR_NOT_IMPLEMENTED;
  2336 NS_IMETHODIMP
  2337 nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  2339   return Rule::GetParentStyleSheet(aSheet);
  2342 NS_IMETHODIMP
  2343 nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  2345   return Rule::GetParentRule(aParentRule);
  2348 NS_IMETHODIMP
  2349 nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText)
  2351   DoGetKeyText(aKeyText);
  2352   return NS_OK;
  2355 void
  2356 nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const
  2358   aKeyText.Truncate();
  2359   uint32_t i = 0, i_end = mKeys.Length();
  2360   NS_ABORT_IF_FALSE(i_end != 0, "must have some keys");
  2361   for (;;) {
  2362     aKeyText.AppendFloat(mKeys[i] * 100.0f);
  2363     aKeyText.Append(char16_t('%'));
  2364     if (++i == i_end) {
  2365       break;
  2367     aKeyText.AppendLiteral(", ");
  2371 NS_IMETHODIMP
  2372 nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
  2374   nsCSSParser parser;
  2376   InfallibleTArray<float> newSelectors;
  2377   // FIXME: pass filename and line number
  2378   if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) {
  2379     // for now, we don't do anything if the parse fails
  2380     return NS_OK;
  2383   nsIDocument* doc = GetDocument();
  2384   MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
  2386   newSelectors.SwapElements(mKeys);
  2388   nsCSSStyleSheet* sheet = GetStyleSheet();
  2389   if (sheet) {
  2390     sheet->SetModifiedByChildRule();
  2392     if (doc) {
  2393       doc->StyleRuleChanged(sheet, this, this);
  2397   return NS_OK;
  2400 NS_IMETHODIMP
  2401 nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
  2403   if (!mDOMDeclaration) {
  2404     mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this);
  2406   NS_ADDREF(*aStyle = mDOMDeclaration);
  2407   return NS_OK;
  2410 void
  2411 nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration)
  2413   // Our caller already did a BeginUpdate/EndUpdate, but with
  2414   // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in
  2415   // PresShell::EndUpdate.
  2416   nsIDocument* doc = GetDocument();
  2417   MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
  2419   // Be careful to not assign to an nsAutoPtr if we would be assigning
  2420   // the thing it already holds.
  2421   if (aDeclaration != mDeclaration) {
  2422     mDeclaration = aDeclaration;
  2425   nsCSSStyleSheet* sheet = GetStyleSheet();
  2426   if (sheet) {
  2427     sheet->SetModifiedByChildRule();
  2429     if (doc) {
  2430       doc->StyleRuleChanged(sheet, this, this);
  2435 /* virtual */ size_t
  2436 nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  2438   return aMallocSizeOf(this);
  2440   // Measurement of the following members may be added later if DMD finds it is
  2441   // worthwhile:
  2442   // - mKeys
  2443   // - mDeclaration
  2444   // - mDOMDeclaration
  2448 // -------------------------------------------
  2449 // nsCSSKeyframesRule
  2450 //
  2452 nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
  2453   // copy everything except our reference count.  GroupRule's copy
  2454   // constructor also doesn't copy the lazily-constructed
  2455   // mRuleCollection.
  2456   : GroupRule(aCopy),
  2457     mName(aCopy.mName)
  2461 nsCSSKeyframesRule::~nsCSSKeyframesRule()
  2465 /* virtual */ already_AddRefed<css::Rule>
  2466 nsCSSKeyframesRule::Clone() const
  2468   nsRefPtr<css::Rule> clone = new nsCSSKeyframesRule(*this);
  2469   return clone.forget();
  2472 NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, css::GroupRule)
  2473 NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, css::GroupRule)
  2475 DOMCI_DATA(MozCSSKeyframesRule, nsCSSKeyframesRule)
  2477 // QueryInterface implementation for nsCSSKeyframesRule
  2478 NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule)
  2479   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  2480   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  2481   NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
  2482   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  2483   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframesRule)
  2484 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
  2486 #ifdef DEBUG
  2487 void
  2488 nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const
  2490   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
  2492   fprintf(out, "@keyframes %s", NS_ConvertUTF16toUTF8(mName).get());
  2493   GroupRule::List(out, aIndent);
  2495 #endif
  2497 /* virtual */ int32_t
  2498 nsCSSKeyframesRule::GetType() const
  2500   return Rule::KEYFRAMES_RULE;
  2503 NS_IMETHODIMP
  2504 nsCSSKeyframesRule::GetType(uint16_t* aType)
  2506   *aType = nsIDOMCSSRule::KEYFRAMES_RULE;
  2507   return NS_OK;
  2510 NS_IMETHODIMP
  2511 nsCSSKeyframesRule::GetCssText(nsAString& aCssText)
  2513   aCssText.AssignLiteral("@keyframes ");
  2514   aCssText.Append(mName);
  2515   aCssText.AppendLiteral(" {\n");
  2516   nsAutoString tmp;
  2517   for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) {
  2518     static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp);
  2519     aCssText.Append(tmp);
  2520     aCssText.AppendLiteral("\n");
  2522   aCssText.AppendLiteral("}");
  2523   return NS_OK;
  2526 NS_IMETHODIMP
  2527 nsCSSKeyframesRule::SetCssText(const nsAString& aCssText)
  2529   // FIXME: implement???
  2530   return NS_ERROR_NOT_IMPLEMENTED;
  2533 NS_IMETHODIMP
  2534 nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  2536   return GroupRule::GetParentStyleSheet(aSheet);
  2539 NS_IMETHODIMP
  2540 nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  2542   return GroupRule::GetParentRule(aParentRule);
  2545 NS_IMETHODIMP
  2546 nsCSSKeyframesRule::GetName(nsAString& aName)
  2548   aName = mName;
  2549   return NS_OK;
  2552 NS_IMETHODIMP
  2553 nsCSSKeyframesRule::SetName(const nsAString& aName)
  2555   if (mName == aName) {
  2556     return NS_OK;
  2559   nsIDocument* doc = GetDocument();
  2560   MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
  2562   mName = aName;
  2564   nsCSSStyleSheet* sheet = GetStyleSheet();
  2565   if (sheet) {
  2566     sheet->SetModifiedByChildRule();
  2568     if (doc) {
  2569       doc->StyleRuleChanged(sheet, this, this);
  2573   return NS_OK;
  2576 NS_IMETHODIMP
  2577 nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
  2579   return GroupRule::GetCssRules(aRuleList);
  2582 NS_IMETHODIMP
  2583 nsCSSKeyframesRule::AppendRule(const nsAString& aRule)
  2585   // The spec is confusing, and I think we should just append the rule,
  2586   // which also turns out to match WebKit:
  2587   // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
  2588   nsCSSParser parser;
  2590   // FIXME: pass filename and line number
  2591   nsRefPtr<nsCSSKeyframeRule> rule =
  2592     parser.ParseKeyframeRule(aRule, nullptr, 0);
  2593   if (rule) {
  2594     nsIDocument* doc = GetDocument();
  2595     MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
  2597     AppendStyleRule(rule);
  2599     nsCSSStyleSheet* sheet = GetStyleSheet();
  2600     if (sheet) {
  2601       sheet->SetModifiedByChildRule();
  2603       if (doc) {
  2604         doc->StyleRuleChanged(sheet, this, this);
  2609   return NS_OK;
  2612 static const uint32_t RULE_NOT_FOUND = uint32_t(-1);
  2614 uint32_t
  2615 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
  2617   nsCSSParser parser;
  2619   InfallibleTArray<float> keys;
  2620   // FIXME: pass filename and line number
  2621   if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
  2622     // The spec isn't clear, but we'll match on the key list, which
  2623     // mostly matches what WebKit does, except we'll do last-match
  2624     // instead of first-match, and handling parsing differences better.
  2625     // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
  2626     // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
  2627     for (uint32_t i = mRules.Count(); i-- != 0; ) {
  2628       if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) {
  2629         return i;
  2634   return RULE_NOT_FOUND;
  2637 NS_IMETHODIMP
  2638 nsCSSKeyframesRule::DeleteRule(const nsAString& aKey)
  2640   uint32_t index = FindRuleIndexForKey(aKey);
  2641   if (index != RULE_NOT_FOUND) {
  2642     nsIDocument* doc = GetDocument();
  2643     MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
  2645     mRules.RemoveObjectAt(index);
  2647     nsCSSStyleSheet* sheet = GetStyleSheet();
  2648     if (sheet) {
  2649       sheet->SetModifiedByChildRule();
  2651       if (doc) {
  2652         doc->StyleRuleChanged(sheet, this, this);
  2656   return NS_OK;
  2659 NS_IMETHODIMP
  2660 nsCSSKeyframesRule::FindRule(const nsAString& aKey,
  2661                              nsIDOMMozCSSKeyframeRule** aResult)
  2663   uint32_t index = FindRuleIndexForKey(aKey);
  2664   if (index == RULE_NOT_FOUND) {
  2665     *aResult = nullptr;
  2666   } else {
  2667     NS_ADDREF(*aResult = static_cast<nsCSSKeyframeRule*>(mRules[index]));
  2669   return NS_OK;
  2672 // GroupRule interface
  2673 /* virtual */ bool
  2674 nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
  2675                                        nsMediaQueryResultCacheKey& aKey)
  2677   NS_ABORT_IF_FALSE(false, "should not be called");
  2678   return false;
  2681 /* virtual */ size_t
  2682 nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  2684   size_t n = aMallocSizeOf(this);
  2685   n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
  2687   // Measurement of the following members may be added later if DMD finds it is
  2688   // worthwhile:
  2689   // - mName
  2691   return n;
  2694 // -------------------------------------------
  2695 // nsCSSPageStyleDeclaration
  2696 //
  2698 nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
  2699   : mRule(aRule)
  2703 nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
  2705   NS_ASSERTION(!mRule, "DropReference not called.");
  2708 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
  2709 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
  2711 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
  2713 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
  2714   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  2715 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
  2717 css::Declaration*
  2718 nsCSSPageStyleDeclaration::GetCSSDeclaration(bool aAllocate)
  2720   if (mRule) {
  2721     return mRule->Declaration();
  2722   } else {
  2723     return nullptr;
  2727 void
  2728 nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
  2730   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
  2733 NS_IMETHODIMP
  2734 nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
  2736   NS_ENSURE_ARG_POINTER(aParent);
  2738   NS_IF_ADDREF(*aParent = mRule);
  2739   return NS_OK;
  2742 nsresult
  2743 nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
  2745   NS_ABORT_IF_FALSE(aDecl, "must be non-null");
  2746   mRule->ChangeDeclaration(aDecl);
  2747   return NS_OK;
  2750 nsIDocument*
  2751 nsCSSPageStyleDeclaration::DocToUpdate()
  2753   return nullptr;
  2756 nsINode*
  2757 nsCSSPageStyleDeclaration::GetParentObject()
  2759   return mRule ? mRule->GetDocument() : nullptr;
  2762 // -------------------------------------------
  2763 // nsCSSPageRule
  2764 //
  2766 nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
  2767   // copy everything except our reference count and mDOMDeclaration
  2768   : Rule(aCopy)
  2769   , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
  2773 nsCSSPageRule::~nsCSSPageRule()
  2775   if (mDOMDeclaration) {
  2776     mDOMDeclaration->DropReference();
  2780 /* virtual */ already_AddRefed<css::Rule>
  2781 nsCSSPageRule::Clone() const
  2783   nsRefPtr<css::Rule> clone = new nsCSSPageRule(*this);
  2784   return clone.forget();
  2787 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageRule)
  2788 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageRule)
  2790 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSPageRule)
  2792 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSPageRule)
  2793   if (tmp->mDOMDeclaration) {
  2794     tmp->mDOMDeclaration->DropReference();
  2795     tmp->mDOMDeclaration = nullptr;
  2797 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  2798 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSPageRule)
  2799   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
  2800 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  2802 DOMCI_DATA(CSSPageRule, nsCSSPageRule)
  2804 // QueryInterface implementation for nsCSSPageRule
  2805 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageRule)
  2806   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  2807   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule)
  2808   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  2809   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  2810   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule)
  2811 NS_INTERFACE_MAP_END
  2813 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule)
  2815 #ifdef DEBUG
  2816 void
  2817 nsCSSPageRule::List(FILE* out, int32_t aIndent) const
  2819   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
  2821   fputs("@page ", out);
  2822   mDeclaration->List(out, aIndent);
  2823   fputs("\n", out);
  2825 #endif
  2827 /* virtual */ int32_t
  2828 nsCSSPageRule::GetType() const
  2830   return Rule::PAGE_RULE;
  2833 NS_IMETHODIMP
  2834 nsCSSPageRule::GetType(uint16_t* aType)
  2836   *aType = nsIDOMCSSRule::PAGE_RULE;
  2837   return NS_OK;
  2840 NS_IMETHODIMP
  2841 nsCSSPageRule::GetCssText(nsAString& aCssText)
  2843   aCssText.AppendLiteral("@page { ");
  2844   nsAutoString tmp;
  2845   mDeclaration->ToString(tmp);
  2846   aCssText.Append(tmp);
  2847   aCssText.AppendLiteral(" }");
  2848   return NS_OK;
  2851 NS_IMETHODIMP
  2852 nsCSSPageRule::SetCssText(const nsAString& aCssText)
  2854   // FIXME: implement???
  2855   return NS_ERROR_NOT_IMPLEMENTED;
  2858 NS_IMETHODIMP
  2859 nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  2861   return Rule::GetParentStyleSheet(aSheet);
  2864 NS_IMETHODIMP
  2865 nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  2867   return Rule::GetParentRule(aParentRule);
  2870 css::ImportantRule*
  2871 nsCSSPageRule::GetImportantRule()
  2873   if (!mDeclaration->HasImportantData()) {
  2874     return nullptr;
  2876   if (!mImportantRule) {
  2877     mImportantRule = new css::ImportantRule(mDeclaration);
  2879   return mImportantRule;
  2882 /* virtual */ void
  2883 nsCSSPageRule::MapRuleInfoInto(nsRuleData* aRuleData)
  2885   mDeclaration->MapNormalRuleInfoInto(aRuleData);
  2888 NS_IMETHODIMP
  2889 nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
  2891   if (!mDOMDeclaration) {
  2892     mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
  2894   NS_ADDREF(*aStyle = mDOMDeclaration);
  2895   return NS_OK;
  2898 void
  2899 nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
  2901   mImportantRule = nullptr;
  2902   // Be careful to not assign to an nsAutoPtr if we would be assigning
  2903   // the thing it already holds.
  2904   if (aDeclaration != mDeclaration) {
  2905     mDeclaration = aDeclaration;
  2908   nsCSSStyleSheet* sheet = GetStyleSheet();
  2909   if (sheet) {
  2910     sheet->SetModifiedByChildRule();
  2914 /* virtual */ size_t
  2915 nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  2917   return aMallocSizeOf(this);
  2920 namespace mozilla {
  2922 CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
  2923                                  const nsString& aCondition)
  2924   : mUseGroup(aConditionMet),
  2925     mCondition(aCondition)
  2929 CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
  2930   : css::GroupRule(aCopy),
  2931     mUseGroup(aCopy.mUseGroup),
  2932     mCondition(aCopy.mCondition)
  2936 #ifdef DEBUG
  2937 /* virtual */ void
  2938 CSSSupportsRule::List(FILE* out, int32_t aIndent) const
  2940   for (int32_t indent = aIndent; --indent >= 0; ) fputs("  ", out);
  2942   fputs("@supports ", out);
  2943   fputs(NS_ConvertUTF16toUTF8(mCondition).get(), out);
  2944   css::GroupRule::List(out, aIndent);
  2946 #endif
  2948 /* virtual */ int32_t
  2949 CSSSupportsRule::GetType() const
  2951   return Rule::SUPPORTS_RULE;
  2954 /* virtual */ already_AddRefed<mozilla::css::Rule>
  2955 CSSSupportsRule::Clone() const
  2957   nsRefPtr<css::Rule> clone = new CSSSupportsRule(*this);
  2958   return clone.forget();
  2961 /* virtual */ bool
  2962 CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
  2963                                    nsMediaQueryResultCacheKey& aKey)
  2965   return mUseGroup;
  2968 NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule)
  2969 NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule)
  2971 // QueryInterface implementation for CSSSupportsRule
  2972 NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
  2973   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  2974   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  2975   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
  2976   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
  2977   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
  2978   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  2979   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule)
  2980 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
  2982 // nsIDOMCSSRule methods
  2983 NS_IMETHODIMP
  2984 CSSSupportsRule::GetType(uint16_t* aType)
  2986   *aType = nsIDOMCSSRule::SUPPORTS_RULE;
  2987   return NS_OK;
  2990 NS_IMETHODIMP
  2991 CSSSupportsRule::GetCssText(nsAString& aCssText)
  2993   aCssText.AssignLiteral("@supports ");
  2994   aCssText.Append(mCondition);
  2995   css::GroupRule::AppendRulesToCssText(aCssText);
  2996   return NS_OK;
  2999 NS_IMETHODIMP
  3000 CSSSupportsRule::SetCssText(const nsAString& aCssText)
  3002   return NS_ERROR_NOT_IMPLEMENTED;
  3005 NS_IMETHODIMP
  3006 CSSSupportsRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  3008   return css::GroupRule::GetParentStyleSheet(aSheet);
  3011 NS_IMETHODIMP
  3012 CSSSupportsRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  3014   return css::GroupRule::GetParentRule(aParentRule);
  3017 // nsIDOMCSSGroupingRule methods
  3018 NS_IMETHODIMP
  3019 CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
  3021   return css::GroupRule::GetCssRules(aRuleList);
  3024 NS_IMETHODIMP
  3025 CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
  3027   return css::GroupRule::InsertRule(aRule, aIndex, _retval);
  3030 NS_IMETHODIMP
  3031 CSSSupportsRule::DeleteRule(uint32_t aIndex)
  3033   return css::GroupRule::DeleteRule(aIndex);
  3036 // nsIDOMCSSConditionRule methods
  3037 NS_IMETHODIMP
  3038 CSSSupportsRule::GetConditionText(nsAString& aConditionText)
  3040   aConditionText.Assign(mCondition);
  3041   return NS_OK;
  3044 NS_IMETHODIMP
  3045 CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
  3047   return NS_ERROR_NOT_IMPLEMENTED;
  3050 /* virtual */ size_t
  3051 CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  3053   size_t n = aMallocSizeOf(this);
  3054   n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
  3055   n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  3056   return n;
  3059 } // namespace mozilla
  3061 // Must be outside namespace
  3062 DOMCI_DATA(CSSSupportsRule, mozilla::CSSSupportsRule)

mercurial