LCOV - code coverage report
Current view: top level - layout/style - GroupRule.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 32 181 17.7 %
Date: 2017-07-14 16:53:18 Functions: 10 41 24.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * internal interface representing CSS style rules that contain other
       9             :  * rules, such as @media rules
      10             :  */
      11             : 
      12             : #include "mozilla/css/GroupRule.h"
      13             : 
      14             : #include "mozilla/dom/CSSRuleList.h"
      15             : 
      16             : using namespace mozilla::dom;
      17             : 
      18             : namespace mozilla {
      19             : namespace css {
      20             : 
      21             : #define CALL_INNER(inner_, call_)               \
      22             :   ((inner_).is<GeckoGroupRuleRules>()           \
      23             :     ? (inner_).as<GeckoGroupRuleRules>().call_  \
      24             :     : (inner_).as<ServoGroupRuleRules>().call_)
      25             : 
      26             : // -------------------------------
      27             : // Style Rule List for group rules
      28             : //
      29             : 
      30             : class GroupRuleRuleList final : public dom::CSSRuleList
      31             : {
      32             : public:
      33             :   explicit GroupRuleRuleList(GroupRule *aGroupRule);
      34             : 
      35             :   virtual CSSStyleSheet* GetParentObject() override;
      36             : 
      37             :   virtual Rule*
      38             :   IndexedGetter(uint32_t aIndex, bool& aFound) override;
      39             :   virtual uint32_t
      40             :   Length() override;
      41             : 
      42           0 :   void DropReference() { mGroupRule = nullptr; }
      43             : 
      44             : private:
      45             :   ~GroupRuleRuleList();
      46             : 
      47             : private:
      48             :   GroupRule* mGroupRule;
      49             : };
      50             : 
      51           0 : GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule)
      52             : {
      53             :   // Not reference counted to avoid circular references.
      54             :   // The rule will tell us when its going away.
      55           0 :   mGroupRule = aGroupRule;
      56           0 : }
      57             : 
      58           0 : GroupRuleRuleList::~GroupRuleRuleList()
      59             : {
      60           0 : }
      61             : 
      62             : CSSStyleSheet*
      63           0 : GroupRuleRuleList::GetParentObject()
      64             : {
      65           0 :   if (!mGroupRule) {
      66           0 :     return nullptr;
      67             :   }
      68           0 :   StyleSheet* sheet = mGroupRule->GetStyleSheet();
      69           0 :   return sheet ? sheet->AsGecko() : nullptr;
      70             : }
      71             : 
      72             : uint32_t
      73           0 : GroupRuleRuleList::Length()
      74             : {
      75           0 :   if (!mGroupRule) {
      76           0 :     return 0;
      77             :   }
      78             : 
      79           0 :   return AssertedCast<uint32_t>(mGroupRule->StyleRuleCount());
      80             : }
      81             : 
      82             : Rule*
      83           0 : GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
      84             : {
      85           0 :   aFound = false;
      86             : 
      87           0 :   if (mGroupRule) {
      88           0 :     RefPtr<Rule> rule = mGroupRule->GetStyleRuleAt(aIndex);
      89           0 :     if (rule) {
      90           0 :       aFound = true;
      91           0 :       return rule;
      92             :     }
      93             :   }
      94             : 
      95           0 :   return nullptr;
      96             : }
      97             : 
      98             : // -------------------------------
      99             : // GeckoGroupRuleRules
     100             : //
     101             : 
     102          81 : GeckoGroupRuleRules::GeckoGroupRuleRules()
     103             : {
     104          81 : }
     105             : 
     106          81 : GeckoGroupRuleRules::GeckoGroupRuleRules(GeckoGroupRuleRules&& aOther)
     107          81 :   : mRules(Move(aOther.mRules))
     108          81 :   , mRuleCollection(Move(aOther.mRuleCollection))
     109             : {
     110          81 : }
     111             : 
     112           0 : GeckoGroupRuleRules::GeckoGroupRuleRules(const GeckoGroupRuleRules& aCopy)
     113             : {
     114           0 :   for (const Rule* rule : aCopy.mRules) {
     115           0 :     RefPtr<Rule> clone = rule->Clone();
     116           0 :     mRules.AppendObject(clone);
     117             :   }
     118           0 : }
     119             : 
     120         162 : GeckoGroupRuleRules::~GeckoGroupRuleRules()
     121             : {
     122          81 :   for (Rule* rule : mRules) {
     123           0 :     rule->SetParentRule(nullptr);
     124             :   }
     125          81 :   if (mRuleCollection) {
     126           0 :     mRuleCollection->DropReference();
     127             :   }
     128          81 : }
     129             : 
     130             : void
     131           0 : GeckoGroupRuleRules::Clear()
     132             : {
     133           0 :   mRules.Clear();
     134           0 :   if (mRuleCollection) {
     135           0 :     mRuleCollection->DropReference();
     136           0 :     mRuleCollection = nullptr;
     137             :   }
     138           0 : }
     139             : 
     140             : void
     141           0 : GeckoGroupRuleRules::Traverse(nsCycleCollectionTraversalCallback& cb)
     142             : {
     143           0 :   IncrementalClearCOMRuleArray& rules = mRules;
     144           0 :   for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
     145           0 :     if (!rules[i]->IsCCLeaf()) {
     146           0 :       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
     147           0 :       cb.NoteXPCOMChild(rules[i]);
     148             :     }
     149             :   }
     150           0 :   ImplCycleCollectionTraverse(cb, mRuleCollection, "mRuleCollection");
     151           0 : }
     152             : 
     153             : #ifdef DEBUG
     154             : void
     155           0 : GeckoGroupRuleRules::List(FILE* out, int32_t aIndent) const
     156             : {
     157           0 :   for (const Rule* rule : mRules) {
     158           0 :     rule->List(out, aIndent + 1);
     159             :   }
     160           0 : }
     161             : #endif
     162             : 
     163             : nsresult
     164           0 : GeckoGroupRuleRules::DeleteStyleRuleAt(uint32_t aIndex)
     165             : {
     166           0 :   Rule* rule = mRules.SafeObjectAt(aIndex);
     167           0 :   if (rule) {
     168           0 :     rule->SetStyleSheet(nullptr);
     169           0 :     rule->SetParentRule(nullptr);
     170             :   }
     171           0 :   return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
     172             : }
     173             : 
     174             : CSSRuleList*
     175           0 : GeckoGroupRuleRules::CssRules(GroupRule* aParentRule)
     176             : {
     177           0 :   if (!mRuleCollection) {
     178           0 :     mRuleCollection = new GroupRuleRuleList(aParentRule);
     179             :   }
     180           0 :   return mRuleCollection;
     181             : }
     182             : 
     183             : size_t
     184           0 : GeckoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
     185             : {
     186           0 :   size_t n = mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
     187           0 :   for (const Rule* rule : mRules) {
     188           0 :     n += rule->SizeOfIncludingThis(aMallocSizeOf);
     189             :   }
     190             : 
     191             :   // Measurement of the following members may be added later if DMD finds it is
     192             :   // worthwhile:
     193             :   // - mRuleCollection
     194           0 :   return n;
     195             : }
     196             : 
     197             : // -------------------------------
     198             : // ServoGroupRuleRules
     199             : //
     200             : 
     201             : #ifdef DEBUG
     202             : void
     203           0 : ServoGroupRuleRules::List(FILE* out, int32_t aIndent) const
     204             : {
     205             :   // TODO list something reasonable?
     206           0 : }
     207             : #endif
     208             : 
     209             : size_t
     210           0 : ServoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
     211             : {
     212             :   // TODO how to implement?
     213           0 :   return 0;
     214             : }
     215             : 
     216             : // -------------------------------
     217             : // GroupRule
     218             : //
     219             : 
     220          81 : GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
     221             :   : Rule(aLineNumber, aColumnNumber)
     222          81 :   , mInner(GeckoGroupRuleRules())
     223             : {
     224          81 : }
     225             : 
     226           0 : GroupRule::GroupRule(already_AddRefed<ServoCssRules> aRules)
     227             :   : Rule(0, 0) // TODO
     228           0 :   , mInner(ServoGroupRuleRules(Move(aRules)))
     229             : {
     230           0 :   mInner.as<ServoGroupRuleRules>().SetParentRule(this);
     231           0 : }
     232             : 
     233           0 : GroupRule::GroupRule(const GroupRule& aCopy)
     234             :   : Rule(aCopy)
     235           0 :   , mInner(aCopy.mInner)
     236             : {
     237           0 :   CALL_INNER(mInner, SetParentRule(this));
     238           0 : }
     239             : 
     240           0 : GroupRule::~GroupRule()
     241             : {
     242           0 :   MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
     243           0 : }
     244             : 
     245         212 : NS_IMPL_ADDREF_INHERITED(GroupRule, Rule)
     246         131 : NS_IMPL_RELEASE_INHERITED(GroupRule, Rule)
     247             : 
     248          33 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GroupRule)
     249           0 : NS_INTERFACE_MAP_END_INHERITING(Rule)
     250             : 
     251             : bool
     252           0 : GroupRule::IsCCLeaf() const
     253             : {
     254             :   // Let's not worry for now about sorting out whether we're a leaf or not.
     255           0 :   return false;
     256             : }
     257             : 
     258             : NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
     259             : 
     260           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GroupRule, Rule)
     261           0 :   CALL_INNER(tmp->mInner, SetParentRule(nullptr));
     262             :   // If tmp does not have a stylesheet, neither do its descendants.  In that
     263             :   // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
     264             :   // depth of group rule nesting.  But if tmp _does_ have a stylesheet (which
     265             :   // can happen if it gets unlinked earlier than its owning stylesheet), then we
     266             :   // need to null out the stylesheet pointer on descendants now, before we clear
     267             :   // tmp->mRules.
     268           0 :   if (tmp->GetStyleSheet()) {
     269           0 :     CALL_INNER(tmp->mInner, SetStyleSheet(nullptr));
     270             :   }
     271           0 :   CALL_INNER(tmp->mInner, Clear());
     272           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     273             : 
     274           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GroupRule, Rule)
     275           0 :   CALL_INNER(tmp->mInner, Traverse(cb));
     276           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     277             : 
     278             : /* virtual */ void
     279          81 : GroupRule::SetStyleSheet(StyleSheet* aSheet)
     280             : {
     281             :   // Don't set the sheet on the kids if it's already the same as the sheet we
     282             :   // already have.  This is needed to avoid O(N^2) behavior in group nesting
     283             :   // depth when seting the sheet to null during unlink, if we happen to unlin in
     284             :   // order from most nested rule up to least nested rule.
     285          81 :   if (aSheet != GetStyleSheet()) {
     286          81 :     CALL_INNER(mInner, SetStyleSheet(aSheet));
     287          81 :     Rule::SetStyleSheet(aSheet);
     288             :   }
     289          81 : }
     290             : 
     291             : void
     292         207 : GroupRule::AppendStyleRule(Rule* aRule)
     293             : {
     294         207 :   GeckoRules().AppendObject(aRule);
     295         207 :   StyleSheet* sheet = GetStyleSheet();
     296         207 :   aRule->SetStyleSheet(sheet);
     297         207 :   aRule->SetParentRule(this);
     298         207 :   if (sheet) {
     299           0 :     sheet->AsGecko()->SetModifiedByChildRule();
     300             :   }
     301         207 : }
     302             : 
     303             : bool
     304         140 : GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
     305             : {
     306         498 :   for (const Rule* rule : GeckoRules()) {
     307         358 :     if (!aFunc(const_cast<Rule*>(rule), aData)) {
     308           0 :       return false;
     309             :     }
     310             :   }
     311         140 :   return true;
     312             : }
     313             : 
     314             : nsresult
     315           0 : GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
     316             : {
     317           0 :   aRule->SetStyleSheet(GetStyleSheet());
     318           0 :   aRule->SetParentRule(this);
     319           0 :   if (!GeckoRules().InsertObjectAt(aRule, aIndex)) {
     320           0 :     return NS_ERROR_FAILURE;
     321             :   }
     322           0 :   return NS_OK;
     323             : }
     324             : 
     325             : void
     326           0 : GroupRule::AppendRulesToCssText(nsAString& aCssText) const
     327             : {
     328           0 :   aCssText.AppendLiteral(" {\n");
     329           0 :   for (const Rule* rule : GeckoRules()) {
     330           0 :     nsAutoString cssText;
     331           0 :     rule->GetCssText(cssText);
     332           0 :     aCssText.AppendLiteral("  ");
     333           0 :     aCssText.Append(cssText);
     334           0 :     aCssText.Append('\n');
     335             :   }
     336           0 :   aCssText.Append('}');
     337           0 : }
     338             : 
     339             : // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
     340             : nsresult
     341           0 : GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
     342             : {
     343           0 :   NS_ADDREF(*aRuleList = CssRules());
     344           0 :   return NS_OK;
     345             : }
     346             : 
     347             : CSSRuleList*
     348           0 : GroupRule::CssRules()
     349             : {
     350           0 :   return CALL_INNER(mInner, CssRules(this));
     351             : }
     352             : 
     353             : nsresult
     354           0 : GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
     355             : {
     356           0 :   ErrorResult rv;
     357           0 :   *_retval = InsertRule(aRule, aIndex, rv);
     358           0 :   return rv.StealNSResult();
     359             : }
     360             : 
     361             : uint32_t
     362           0 : GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex, ErrorResult& aRv)
     363             : {
     364           0 :   StyleSheet* sheet = GetStyleSheet();
     365           0 :   if (NS_WARN_IF(!sheet)) {
     366           0 :     aRv.Throw(NS_ERROR_FAILURE);
     367           0 :     return 0;
     368             :   }
     369             : 
     370           0 :   uint32_t count = StyleRuleCount();
     371           0 :   if (aIndex > count) {
     372           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     373           0 :     return 0;
     374             :   }
     375             : 
     376           0 :   NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
     377             : 
     378           0 :   nsresult rv = sheet->InsertRuleIntoGroup(aRule, this, aIndex);
     379           0 :   if (NS_FAILED(rv)) {
     380           0 :     aRv.Throw(rv);
     381           0 :     return 0;
     382             :   }
     383           0 :   return aIndex;
     384             : }
     385             : 
     386             : nsresult
     387           0 : GroupRule::DeleteRule(uint32_t aIndex)
     388             : {
     389           0 :   ErrorResult rv;
     390           0 :   DeleteRule(aIndex, rv);
     391           0 :   return rv.StealNSResult();
     392             : }
     393             : 
     394             : void
     395           0 : GroupRule::DeleteRule(uint32_t aIndex, ErrorResult& aRv)
     396             : {
     397           0 :   StyleSheet* sheet = GetStyleSheet();
     398           0 :   if (NS_WARN_IF(!sheet)) {
     399           0 :     aRv.Throw(NS_ERROR_FAILURE);
     400           0 :     return;
     401             :   }
     402             : 
     403           0 :   uint32_t count = StyleRuleCount();
     404           0 :   if (aIndex >= count) {
     405           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     406           0 :     return;
     407             :   }
     408             : 
     409           0 :   NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
     410             : 
     411           0 :   nsresult rv = sheet->DeleteRuleFromGroup(this, aIndex);
     412           0 :   if (NS_FAILED(rv)) {
     413           0 :     aRv.Throw(rv);
     414             :   }
     415             : }
     416             : 
     417             : #undef CALL_INNER
     418             : 
     419             : } // namespace css
     420             : } // namespace mozilla

Generated by: LCOV version 1.13