LCOV - code coverage report
Current view: directory - layout/style - nsStyleSet.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 679 0 0.0 %
Date: 2012-06-02 Functions: 71 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Daniel Glazman <glazman@netscape.com>
      24                 :  *   Brian Ryner    <bryner@brianryner.com>
      25                 :  *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : /*
      42                 :  * the container for the style sheets that apply to a presentation, and
      43                 :  * the internal API that the style system exposes for creating (and
      44                 :  * potentially re-creating) style contexts
      45                 :  */
      46                 : 
      47                 : #include "mozilla/Util.h"
      48                 : 
      49                 : #include "nsStyleSet.h"
      50                 : #include "nsNetUtil.h"
      51                 : #include "nsCSSStyleSheet.h"
      52                 : #include "nsIDocument.h"
      53                 : #include "nsRuleWalker.h"
      54                 : #include "nsStyleContext.h"
      55                 : #include "mozilla/css/StyleRule.h"
      56                 : #include "nsCSSAnonBoxes.h"
      57                 : #include "nsCSSPseudoElements.h"
      58                 : #include "nsCSSRuleProcessor.h"
      59                 : #include "nsIContent.h"
      60                 : #include "nsIFrame.h"
      61                 : #include "nsContentUtils.h"
      62                 : #include "nsRuleData.h"
      63                 : #include "nsRuleProcessorData.h"
      64                 : #include "nsTransitionManager.h"
      65                 : #include "nsAnimationManager.h"
      66                 : #include "nsEventStates.h"
      67                 : #include "mozilla/dom/Element.h"
      68                 : 
      69                 : using namespace mozilla;
      70                 : using namespace mozilla::dom;
      71                 : 
      72               0 : NS_IMPL_ISUPPORTS1(nsEmptyStyleRule, nsIStyleRule)
      73                 : 
      74                 : /* virtual */ void
      75               0 : nsEmptyStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
      76                 : {
      77               0 : }
      78                 : 
      79                 : #ifdef DEBUG
      80                 : /* virtual */ void
      81               0 : nsEmptyStyleRule::List(FILE* out, PRInt32 aIndent) const
      82                 : {
      83               0 : }
      84                 : #endif
      85                 : 
      86               0 : NS_IMPL_ISUPPORTS1(nsInitialStyleRule, nsIStyleRule)
      87                 : 
      88                 : /* virtual */ void
      89               0 : nsInitialStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
      90                 : {
      91                 :   // Iterate over the property groups
      92               0 :   for (nsStyleStructID sid = nsStyleStructID(0);
      93                 :        sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
      94               0 :     if (aRuleData->mSIDs & (1 << sid)) {
      95                 :       // Iterate over nsCSSValues within the property group
      96                 :       nsCSSValue * const value_start =
      97               0 :         aRuleData->mValueStorage + aRuleData->mValueOffsets[sid];
      98               0 :       for (nsCSSValue *value = value_start,
      99               0 :            *value_end = value + nsCSSProps::PropertyCountInStruct(sid);
     100                 :            value != value_end; ++value) {
     101                 :         // If MathML is disabled take care not to set MathML properties (or we
     102                 :         // will trigger assertions in nsRuleNode)
     103               0 :         if (sid == eStyleStruct_Font &&
     104               0 :             !aRuleData->mPresContext->Document()->GetMathMLEnabled()) {
     105               0 :           size_t index = value - value_start;
     106               0 :           if (index == nsCSSProps::PropertyIndexInStruct(
     107               0 :                           eCSSProperty_script_level) ||
     108                 :               index == nsCSSProps::PropertyIndexInStruct(
     109               0 :                           eCSSProperty_script_size_multiplier) ||
     110                 :               index == nsCSSProps::PropertyIndexInStruct(
     111               0 :                           eCSSProperty_script_min_size)) {
     112               0 :             continue;
     113                 :           }
     114                 :         }
     115               0 :         if (value->GetUnit() == eCSSUnit_Null) {
     116               0 :           value->SetInitialValue();
     117                 :         }
     118                 :       }
     119                 :     }
     120                 :   }
     121               0 : }
     122                 : 
     123                 : #ifdef DEBUG
     124                 : /* virtual */ void
     125               0 : nsInitialStyleRule::List(FILE* out, PRInt32 aIndent) const
     126                 : {
     127               0 : }
     128                 : #endif
     129                 : 
     130                 : static const nsStyleSet::sheetType gCSSSheetTypes[] = {
     131                 :   nsStyleSet::eAgentSheet,
     132                 :   nsStyleSet::eUserSheet,
     133                 :   nsStyleSet::eDocSheet,
     134                 :   nsStyleSet::eOverrideSheet
     135                 : };
     136                 : 
     137               0 : nsStyleSet::nsStyleSet()
     138                 :   : mRuleTree(nsnull),
     139                 :     mUnusedRuleNodeCount(0),
     140                 :     mBatching(0),
     141                 :     mInShutdown(false),
     142                 :     mAuthorStyleDisabled(false),
     143                 :     mInReconstruct(false),
     144               0 :     mDirty(0)
     145                 : {
     146               0 : }
     147                 : 
     148                 : size_t
     149               0 : nsStyleSet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
     150                 : {
     151               0 :   size_t n = aMallocSizeOf(this);
     152                 : 
     153               0 :   for (int i = 0; i < eSheetTypeCount; i++) {
     154               0 :     if (mRuleProcessors[i]) {
     155               0 :       n += mRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
     156                 :     }
     157                 :   }
     158                 : 
     159               0 :   return n;
     160                 : }
     161                 : 
     162                 : nsresult
     163               0 : nsStyleSet::Init(nsPresContext *aPresContext)
     164                 : {
     165               0 :   mFirstLineRule = new nsEmptyStyleRule;
     166               0 :   mFirstLetterRule = new nsEmptyStyleRule;
     167               0 :   if (!mFirstLineRule || !mFirstLetterRule) {
     168               0 :     return NS_ERROR_OUT_OF_MEMORY;
     169                 :   }
     170                 : 
     171               0 :   if (!BuildDefaultStyleData(aPresContext)) {
     172               0 :     mDefaultStyleData.Destroy(0, aPresContext);
     173               0 :     return NS_ERROR_OUT_OF_MEMORY;
     174                 :   }
     175                 : 
     176               0 :   mRuleTree = nsRuleNode::CreateRootNode(aPresContext);
     177               0 :   if (!mRuleTree) {
     178               0 :     mDefaultStyleData.Destroy(0, aPresContext);
     179               0 :     return NS_ERROR_OUT_OF_MEMORY;
     180                 :   }
     181                 : 
     182               0 :   GatherRuleProcessors(eAnimationSheet);
     183               0 :   GatherRuleProcessors(eTransitionSheet);
     184                 : 
     185               0 :   return NS_OK;
     186                 : }
     187                 : 
     188                 : nsresult
     189               0 : nsStyleSet::BeginReconstruct()
     190                 : {
     191               0 :   NS_ASSERTION(!mInReconstruct, "Unmatched begin/end?");
     192               0 :   NS_ASSERTION(mRuleTree, "Reconstructing before first construction?");
     193                 : 
     194                 :   // Create a new rule tree root
     195                 :   nsRuleNode* newTree =
     196               0 :     nsRuleNode::CreateRootNode(mRuleTree->GetPresContext());
     197               0 :   if (!newTree)
     198               0 :     return NS_ERROR_OUT_OF_MEMORY;
     199                 : 
     200                 :   // Save the old rule tree so we can destroy it later
     201               0 :   if (!mOldRuleTrees.AppendElement(mRuleTree)) {
     202               0 :     newTree->Destroy();
     203               0 :     return NS_ERROR_OUT_OF_MEMORY;
     204                 :   }
     205                 : 
     206                 :   // We need to keep mRoots so that the rule tree GC will only free the
     207                 :   // rule trees that really aren't referenced anymore (which should be
     208                 :   // all of them, if there are no bugs in reresolution code).
     209                 : 
     210               0 :   mInReconstruct = true;
     211               0 :   mRuleTree = newTree;
     212                 : 
     213               0 :   return NS_OK;
     214                 : }
     215                 : 
     216                 : void
     217               0 : nsStyleSet::EndReconstruct()
     218                 : {
     219               0 :   NS_ASSERTION(mInReconstruct, "Unmatched begin/end?");
     220               0 :   mInReconstruct = false;
     221                 : #ifdef DEBUG
     222               0 :   for (PRInt32 i = mRoots.Length() - 1; i >= 0; --i) {
     223               0 :     nsRuleNode *n = mRoots[i]->GetRuleNode();
     224               0 :     while (n->GetParent()) {
     225               0 :       n = n->GetParent();
     226                 :     }
     227                 :     // Since nsStyleContext's mParent and mRuleNode are immutable, and
     228                 :     // style contexts own their parents, and nsStyleContext asserts in
     229                 :     // its constructor that the style context and its parent are in the
     230                 :     // same rule tree, we don't need to check any of the children of
     231                 :     // mRoots; we only need to check the rule nodes of mRoots
     232                 :     // themselves.
     233                 : 
     234               0 :     NS_ASSERTION(n == mRuleTree, "style context has old rule node");
     235                 :   }
     236                 : #endif
     237                 :   // This *should* destroy the only element of mOldRuleTrees, but in
     238                 :   // case of some bugs (which would trigger the above assertions), it
     239                 :   // won't.
     240               0 :   GCRuleTrees();
     241               0 : }
     242                 : 
     243                 : void
     244               0 : nsStyleSet::SetQuirkStyleSheet(nsIStyleSheet* aQuirkStyleSheet)
     245                 : {
     246               0 :   NS_ASSERTION(aQuirkStyleSheet, "Must have quirk sheet if this is called");
     247               0 :   NS_ASSERTION(!mQuirkStyleSheet, "Multiple calls to SetQuirkStyleSheet?");
     248               0 :   NS_ASSERTION(mSheets[eAgentSheet].IndexOf(aQuirkStyleSheet) != -1,
     249                 :                "Quirk style sheet not one of our agent sheets?");
     250               0 :   mQuirkStyleSheet = aQuirkStyleSheet;
     251               0 : }
     252                 : 
     253                 : nsresult
     254               0 : nsStyleSet::GatherRuleProcessors(sheetType aType)
     255                 : {
     256               0 :   mRuleProcessors[aType] = nsnull;
     257               0 :   if (mAuthorStyleDisabled && (aType == eDocSheet || 
     258                 :                                aType == ePresHintSheet ||
     259                 :                                aType == eStyleAttrSheet)) {
     260                 :     //don't regather if this level is disabled
     261               0 :     return NS_OK;
     262                 :   }
     263               0 :   if (aType == eAnimationSheet) {
     264                 :     // We have no sheet for the animations level; just a rule
     265                 :     // processor.  (XXX: We should probably do this for the other
     266                 :     // non-CSS levels too!)
     267               0 :     mRuleProcessors[aType] = PresContext()->AnimationManager();
     268               0 :     return NS_OK;
     269                 :   }
     270               0 :   if (aType == eTransitionSheet) {
     271                 :     // We have no sheet for the transitions level; just a rule
     272                 :     // processor.  (XXX: We should probably do this for the other
     273                 :     // non-CSS levels too!)
     274               0 :     mRuleProcessors[aType] = PresContext()->TransitionManager();
     275               0 :     return NS_OK;
     276                 :   }
     277               0 :   if (mSheets[aType].Count()) {
     278               0 :     switch (aType) {
     279                 :       case eAgentSheet:
     280                 :       case eUserSheet:
     281                 :       case eDocSheet:
     282                 :       case eOverrideSheet: {
     283                 :         // levels containing CSS stylesheets
     284               0 :         nsCOMArray<nsIStyleSheet>& sheets = mSheets[aType];
     285               0 :         nsTArray<nsRefPtr<nsCSSStyleSheet> > cssSheets(sheets.Count());
     286               0 :         for (PRInt32 i = 0, i_end = sheets.Count(); i < i_end; ++i) {
     287               0 :           nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(sheets[i]);
     288               0 :           NS_ASSERTION(cssSheet, "not a CSS sheet");
     289               0 :           cssSheets.AppendElement(cssSheet);
     290                 :         }
     291               0 :         mRuleProcessors[aType] = new nsCSSRuleProcessor(cssSheets, 
     292               0 :                                                         PRUint8(aType));
     293               0 :       } break;
     294                 : 
     295                 :       default:
     296                 :         // levels containing non-CSS stylesheets
     297               0 :         NS_ASSERTION(mSheets[aType].Count() == 1, "only one sheet per level");
     298               0 :         mRuleProcessors[aType] = do_QueryInterface(mSheets[aType][0]);
     299               0 :         break;
     300                 :     }
     301                 :   }
     302                 : 
     303               0 :   return NS_OK;
     304                 : }
     305                 : 
     306                 : nsresult
     307               0 : nsStyleSet::AppendStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
     308                 : {
     309               0 :   NS_PRECONDITION(aSheet, "null arg");
     310               0 :   NS_ASSERTION(aSheet->IsApplicable(),
     311                 :                "Inapplicable sheet being placed in style set");
     312               0 :   mSheets[aType].RemoveObject(aSheet);
     313               0 :   if (!mSheets[aType].AppendObject(aSheet))
     314               0 :     return NS_ERROR_OUT_OF_MEMORY;
     315                 : 
     316               0 :   if (!mBatching)
     317               0 :     return GatherRuleProcessors(aType);
     318                 : 
     319               0 :   mDirty |= 1 << aType;
     320               0 :   return NS_OK;
     321                 : }
     322                 : 
     323                 : nsresult
     324               0 : nsStyleSet::PrependStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
     325                 : {
     326               0 :   NS_PRECONDITION(aSheet, "null arg");
     327               0 :   NS_ASSERTION(aSheet->IsApplicable(),
     328                 :                "Inapplicable sheet being placed in style set");
     329               0 :   mSheets[aType].RemoveObject(aSheet);
     330               0 :   if (!mSheets[aType].InsertObjectAt(aSheet, 0))
     331               0 :     return NS_ERROR_OUT_OF_MEMORY;
     332                 : 
     333               0 :   if (!mBatching)
     334               0 :     return GatherRuleProcessors(aType);
     335                 : 
     336               0 :   mDirty |= 1 << aType;
     337               0 :   return NS_OK;
     338                 : }
     339                 : 
     340                 : nsresult
     341               0 : nsStyleSet::RemoveStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
     342                 : {
     343               0 :   NS_PRECONDITION(aSheet, "null arg");
     344               0 :   NS_ASSERTION(aSheet->IsComplete(),
     345                 :                "Incomplete sheet being removed from style set");
     346               0 :   mSheets[aType].RemoveObject(aSheet);
     347               0 :   if (!mBatching)
     348               0 :     return GatherRuleProcessors(aType);
     349                 : 
     350               0 :   mDirty |= 1 << aType;
     351               0 :   return NS_OK;
     352                 : }
     353                 : 
     354                 : nsresult
     355               0 : nsStyleSet::ReplaceSheets(sheetType aType,
     356                 :                           const nsCOMArray<nsIStyleSheet> &aNewSheets)
     357                 : {
     358               0 :   mSheets[aType].Clear();
     359               0 :   if (!mSheets[aType].AppendObjects(aNewSheets))
     360               0 :     return NS_ERROR_OUT_OF_MEMORY;
     361                 : 
     362               0 :   if (!mBatching)
     363               0 :     return GatherRuleProcessors(aType);
     364                 : 
     365               0 :   mDirty |= 1 << aType;
     366               0 :   return NS_OK;
     367                 : }
     368                 : 
     369                 : bool
     370               0 : nsStyleSet::GetAuthorStyleDisabled()
     371                 : {
     372               0 :   return mAuthorStyleDisabled;
     373                 : }
     374                 : 
     375                 : nsresult
     376               0 : nsStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled)
     377                 : {
     378               0 :   if (aStyleDisabled == !mAuthorStyleDisabled) {
     379               0 :     mAuthorStyleDisabled = aStyleDisabled;
     380               0 :     BeginUpdate();
     381                 :     mDirty |= 1 << eDocSheet |
     382                 :               1 << ePresHintSheet |
     383               0 :               1 << eStyleAttrSheet;
     384               0 :     return EndUpdate();
     385                 :   }
     386               0 :   return NS_OK;
     387                 : }
     388                 : 
     389                 : // -------- Doc Sheets
     390                 : 
     391                 : nsresult
     392               0 : nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument)
     393                 : {
     394               0 :   NS_PRECONDITION(aSheet && aDocument, "null arg");
     395               0 :   NS_ASSERTION(aSheet->IsApplicable(),
     396                 :                "Inapplicable sheet being placed in style set");
     397                 : 
     398               0 :   nsCOMArray<nsIStyleSheet>& docSheets = mSheets[eDocSheet];
     399                 : 
     400               0 :   docSheets.RemoveObject(aSheet);
     401                 :   // lowest index first
     402               0 :   PRInt32 newDocIndex = aDocument->GetIndexOfStyleSheet(aSheet);
     403               0 :   PRInt32 count = docSheets.Count();
     404                 :   PRInt32 index;
     405               0 :   for (index = 0; index < count; index++) {
     406               0 :     nsIStyleSheet* sheet = docSheets.ObjectAt(index);
     407               0 :     PRInt32 sheetDocIndex = aDocument->GetIndexOfStyleSheet(sheet);
     408               0 :     if (sheetDocIndex > newDocIndex)
     409               0 :       break;
     410                 :   }
     411               0 :   if (!docSheets.InsertObjectAt(aSheet, index))
     412               0 :     return NS_ERROR_OUT_OF_MEMORY;
     413               0 :   if (!mBatching)
     414               0 :     return GatherRuleProcessors(eDocSheet);
     415                 : 
     416               0 :   mDirty |= 1 << eDocSheet;
     417               0 :   return NS_OK;
     418                 : }
     419                 : 
     420                 : // Batching
     421                 : void
     422               0 : nsStyleSet::BeginUpdate()
     423                 : {
     424               0 :   ++mBatching;
     425               0 : }
     426                 : 
     427                 : nsresult
     428               0 : nsStyleSet::EndUpdate()
     429                 : {
     430               0 :   NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate");
     431               0 :   if (--mBatching) {
     432                 :     // We're not completely done yet.
     433               0 :     return NS_OK;
     434                 :   }
     435                 : 
     436               0 :   for (int i = 0; i < eSheetTypeCount; ++i) {
     437               0 :     if (mDirty & (1 << i)) {
     438               0 :       nsresult rv = GatherRuleProcessors(sheetType(i));
     439               0 :       NS_ENSURE_SUCCESS(rv, rv);
     440                 :     }
     441                 :   }
     442                 : 
     443               0 :   mDirty = 0;
     444               0 :   return NS_OK;
     445                 : }
     446                 : 
     447                 : void
     448               0 : nsStyleSet::EnableQuirkStyleSheet(bool aEnable)
     449                 : {
     450                 : #ifdef DEBUG
     451                 :   bool oldEnabled;
     452                 :   {
     453                 :     nsCOMPtr<nsIDOMCSSStyleSheet> domSheet =
     454               0 :       do_QueryInterface(mQuirkStyleSheet);
     455               0 :     domSheet->GetDisabled(&oldEnabled);
     456               0 :     oldEnabled = !oldEnabled;
     457                 :   }
     458                 : #endif
     459               0 :   mQuirkStyleSheet->SetEnabled(aEnable);
     460                 : #ifdef DEBUG
     461                 :   // This should always be OK, since SetEnabled should call
     462                 :   // ClearRuleCascades.
     463                 :   // Note that we can hit this codepath multiple times when document.open()
     464                 :   // (potentially implied) happens multiple times.
     465               0 :   if (mRuleProcessors[eAgentSheet] && aEnable != oldEnabled) {
     466                 :     static_cast<nsCSSRuleProcessor*>(static_cast<nsIStyleRuleProcessor*>(
     467               0 :       mRuleProcessors[eAgentSheet]))->AssertQuirksChangeOK();
     468                 :   }
     469                 : #endif
     470               0 : }
     471                 : 
     472                 : template<class T>
     473                 : static bool
     474               0 : EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
     475                 : {
     476               0 :   T* data = static_cast<T*>(aData);
     477               0 :   aProcessor->RulesMatching(data);
     478               0 :   return true;
     479                 : }
     480                 : 
     481                 : static inline bool
     482               0 : IsMoreSpecificThanAnimation(nsRuleNode *aRuleNode)
     483                 : {
     484               0 :   return !aRuleNode->IsRoot() &&
     485               0 :          (aRuleNode->GetLevel() == nsStyleSet::eTransitionSheet ||
     486               0 :           (aRuleNode->IsImportantRule() &&
     487               0 :            (aRuleNode->GetLevel() == nsStyleSet::eAgentSheet ||
     488               0 :             aRuleNode->GetLevel() == nsStyleSet::eUserSheet)));
     489                 : }
     490                 : 
     491                 : static nsIStyleRule*
     492               0 : GetAnimationRule(nsRuleNode *aRuleNode)
     493                 : {
     494               0 :   nsRuleNode *n = aRuleNode;
     495               0 :   while (IsMoreSpecificThanAnimation(n)) {
     496               0 :     n = n->GetParent();
     497                 :   }
     498                 : 
     499               0 :   if (n->IsRoot() || n->GetLevel() != nsStyleSet::eAnimationSheet) {
     500               0 :     return nsnull;
     501                 :   }
     502                 : 
     503               0 :   return n->GetRule();
     504                 : }
     505                 : 
     506                 : static nsRuleNode*
     507               0 : ReplaceAnimationRule(nsRuleNode *aOldRuleNode,
     508                 :                      nsIStyleRule *aOldAnimRule,
     509                 :                      nsIStyleRule *aNewAnimRule)
     510                 : {
     511               0 :   nsTArray<nsRuleNode*> moreSpecificNodes;
     512                 : 
     513               0 :   nsRuleNode *n = aOldRuleNode;
     514               0 :   while (IsMoreSpecificThanAnimation(n)) {
     515               0 :     moreSpecificNodes.AppendElement(n);
     516               0 :     n = n->GetParent();
     517                 :   }
     518                 : 
     519               0 :   if (aOldAnimRule) {
     520               0 :     NS_ABORT_IF_FALSE(n->GetRule() == aOldAnimRule, "wrong rule");
     521               0 :     NS_ABORT_IF_FALSE(n->GetLevel() == nsStyleSet::eAnimationSheet,
     522                 :                       "wrong level");
     523               0 :     n = n->GetParent();
     524                 :   }
     525                 : 
     526               0 :   NS_ABORT_IF_FALSE(!IsMoreSpecificThanAnimation(n) &&
     527                 :                     n->GetLevel() != nsStyleSet::eAnimationSheet,
     528                 :                     "wrong level");
     529                 : 
     530               0 :   if (aNewAnimRule) {
     531               0 :     n = n->Transition(aNewAnimRule, nsStyleSet::eAnimationSheet, false);
     532                 :   }
     533                 : 
     534               0 :   for (PRUint32 i = moreSpecificNodes.Length(); i-- != 0; ) {
     535               0 :     nsRuleNode *oldNode = moreSpecificNodes[i];
     536               0 :     n = n->Transition(oldNode->GetRule(), oldNode->GetLevel(),
     537               0 :                       oldNode->IsImportantRule());
     538                 :   }
     539                 : 
     540               0 :   return n;
     541                 : }
     542                 : 
     543                 : /**
     544                 :  * |GetContext| implements sharing of style contexts (not just the data
     545                 :  * on the rule nodes) between siblings and cousins of the same
     546                 :  * generation.  (It works for cousins of the same generation since
     547                 :  * |aParentContext| could itself be a shared context.)
     548                 :  */
     549                 : already_AddRefed<nsStyleContext>
     550               0 : nsStyleSet::GetContext(nsStyleContext* aParentContext,
     551                 :                        nsRuleNode* aRuleNode,
     552                 :                        // aVisitedRuleNode may be null; if it is null
     553                 :                        // it means that we don't need to force creation
     554                 :                        // of a StyleIfVisited.  (But if we make one
     555                 :                        // because aParentContext has one, then aRuleNode
     556                 :                        // should be used.)
     557                 :                        nsRuleNode* aVisitedRuleNode,
     558                 :                        bool aIsLink,
     559                 :                        bool aIsVisitedLink,
     560                 :                        nsIAtom* aPseudoTag,
     561                 :                        nsCSSPseudoElements::Type aPseudoType,
     562                 :                        bool aDoAnimations,
     563                 :                        Element* aElementForAnimation)
     564                 : {
     565               0 :   NS_PRECONDITION((!aPseudoTag &&
     566                 :                    aPseudoType ==
     567                 :                      nsCSSPseudoElements::ePseudo_NotPseudoElement) ||
     568                 :                   (aPseudoTag &&
     569                 :                    nsCSSPseudoElements::GetPseudoType(aPseudoTag) ==
     570                 :                      aPseudoType),
     571                 :                   "Pseudo mismatch");
     572                 : 
     573               0 :   if (aVisitedRuleNode == aRuleNode) {
     574                 :     // No need to force creation of a visited style in this case.
     575               0 :     aVisitedRuleNode = nsnull;
     576                 :   }
     577                 : 
     578                 :   // Ensure |aVisitedRuleNode != nsnull| corresponds to the need to
     579                 :   // create an if-visited style context, and that in that case, we have
     580                 :   // parentIfVisited set correctly.
     581                 :   nsStyleContext *parentIfVisited =
     582               0 :     aParentContext ? aParentContext->GetStyleIfVisited() : nsnull;
     583               0 :   if (parentIfVisited) {
     584               0 :     if (!aVisitedRuleNode) {
     585               0 :       aVisitedRuleNode = aRuleNode;
     586                 :     }
     587                 :   } else {
     588               0 :     if (aVisitedRuleNode) {
     589               0 :       parentIfVisited = aParentContext;
     590                 :     }
     591                 :   }
     592                 : 
     593               0 :   if (aIsLink) {
     594                 :     // If this node is a link, we want its visited's style context's
     595                 :     // parent to be the regular style context of its parent, because
     596                 :     // only the visitedness of the relevant link should influence style.
     597               0 :     parentIfVisited = aParentContext;
     598                 :   }
     599                 : 
     600               0 :   nsRefPtr<nsStyleContext> result;
     601               0 :   if (aParentContext)
     602                 :     result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode,
     603                 :                                                 aVisitedRuleNode,
     604               0 :                                                 aIsVisitedLink);
     605                 : 
     606                 : #ifdef NOISY_DEBUG
     607                 :   if (result)
     608                 :     fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
     609                 :   else
     610                 :     fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount);
     611                 : #endif
     612                 : 
     613               0 :   if (!result) {
     614                 :     result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType,
     615               0 :                                 aRuleNode, PresContext());
     616               0 :     if (!result)
     617               0 :       return nsnull;
     618               0 :     if (aVisitedRuleNode) {
     619                 :       nsRefPtr<nsStyleContext> resultIfVisited =
     620                 :         NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType,
     621               0 :                            aVisitedRuleNode, PresContext());
     622               0 :       if (!resultIfVisited) {
     623               0 :         return nsnull;
     624                 :       }
     625               0 :       if (!parentIfVisited) {
     626               0 :         mRoots.AppendElement(resultIfVisited);
     627                 :       }
     628               0 :       resultIfVisited->SetIsStyleIfVisited();
     629               0 :       result->SetStyleIfVisited(resultIfVisited.forget());
     630                 : 
     631                 :       bool relevantLinkVisited =
     632                 :         aIsLink ? aIsVisitedLink
     633               0 :                 : (aParentContext && aParentContext->RelevantLinkVisited());
     634               0 :       if (relevantLinkVisited) {
     635               0 :         result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
     636                 :       }
     637                 :     }
     638               0 :     if (!aParentContext)
     639               0 :       mRoots.AppendElement(result);
     640                 :   }
     641                 :   else {
     642               0 :     NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type");
     643               0 :     NS_ASSERTION(result->GetPseudo() == aPseudoTag, "Unexpected pseudo");
     644                 :   }
     645                 : 
     646               0 :   if (aDoAnimations) {
     647                 :     // Normally the animation manager has already added the correct
     648                 :     // style rule.  However, if the animation-name just changed, it
     649                 :     // might have been wrong.  So ask it to double-check based on the
     650                 :     // resulting style context.
     651               0 :     nsIStyleRule *oldAnimRule = GetAnimationRule(aRuleNode);
     652                 :     nsIStyleRule *animRule = PresContext()->AnimationManager()->
     653               0 :       CheckAnimationRule(result, aElementForAnimation);
     654               0 :     NS_ABORT_IF_FALSE(result->GetRuleNode() == aRuleNode,
     655                 :                       "unexpected rule node");
     656               0 :     NS_ABORT_IF_FALSE(!result->GetStyleIfVisited() == !aVisitedRuleNode,
     657                 :                       "unexpected visited rule node");
     658               0 :     NS_ABORT_IF_FALSE(!aVisitedRuleNode ||
     659                 :                       result->GetStyleIfVisited()->GetRuleNode() ==
     660                 :                         aVisitedRuleNode,
     661                 :                       "unexpected visited rule node");
     662               0 :     if (oldAnimRule != animRule) {
     663                 :       nsRuleNode *ruleNode =
     664               0 :         ReplaceAnimationRule(aRuleNode, oldAnimRule, animRule);
     665                 :       nsRuleNode *visitedRuleNode = aVisitedRuleNode
     666                 :         ? ReplaceAnimationRule(aVisitedRuleNode, oldAnimRule, animRule)
     667               0 :         : nsnull;
     668                 :       result = GetContext(aParentContext, ruleNode, visitedRuleNode,
     669                 :                           aIsLink, aIsVisitedLink,
     670               0 :                           aPseudoTag, aPseudoType, false, nsnull);
     671                 :     }
     672                 :   }
     673                 : 
     674               0 :   if (aElementForAnimation && aElementForAnimation->IsHTML(nsGkAtoms::body) &&
     675                 :       aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement &&
     676               0 :       PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
     677               0 :     nsIDocument* doc = aElementForAnimation->GetCurrentDoc();
     678               0 :     if (doc && doc->GetBodyElement() == aElementForAnimation) {
     679                 :       // Update the prescontext's body color
     680               0 :       PresContext()->SetBodyTextColor(result->GetStyleColor()->mColor);
     681                 :     }
     682                 :   }
     683                 : 
     684               0 :   return result.forget();
     685                 : }
     686                 : 
     687                 : void
     688               0 : nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
     689                 :                               nsRuleNode* aLastPrevLevelNode,
     690                 :                               nsRuleWalker* aRuleWalker)
     691                 : {
     692               0 :   NS_ASSERTION(aCurrLevelNode &&
     693                 :                aCurrLevelNode != aLastPrevLevelNode, "How did we get here?");
     694                 : 
     695               0 :   nsAutoTArray<nsIStyleRule*, 16> importantRules;
     696               0 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
     697                 :        node = node->GetParent()) {
     698                 :     // We guarantee that we never walk the root node here, so no need
     699                 :     // to null-check GetRule().  Furthermore, it must be a CSS rule.
     700               0 :     NS_ASSERTION(nsRefPtr<css::StyleRule>(do_QueryObject(node->GetRule())),
     701                 :                  "Unexpected non-CSS rule");
     702                 : 
     703                 :     nsIStyleRule* impRule =
     704               0 :       static_cast<css::StyleRule*>(node->GetRule())->GetImportantRule();
     705               0 :     if (impRule)
     706               0 :       importantRules.AppendElement(impRule);
     707                 :   }
     708                 : 
     709               0 :   NS_ASSERTION(importantRules.Length() != 0,
     710                 :                "Why did we think there were important rules?");
     711                 : 
     712               0 :   for (PRUint32 i = importantRules.Length(); i-- != 0; ) {
     713               0 :     aRuleWalker->Forward(importantRules[i]);
     714                 :   }
     715               0 : }
     716                 : 
     717                 : #ifdef DEBUG
     718                 : void
     719               0 : nsStyleSet::AssertNoImportantRules(nsRuleNode* aCurrLevelNode,
     720                 :                                    nsRuleNode* aLastPrevLevelNode)
     721                 : {
     722               0 :   if (!aCurrLevelNode)
     723               0 :     return;
     724                 : 
     725               0 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
     726                 :        node = node->GetParent()) {
     727               0 :     nsRefPtr<css::StyleRule> rule(do_QueryObject(node->GetRule()));
     728               0 :     NS_ASSERTION(rule, "Unexpected non-CSS rule");
     729                 : 
     730               0 :     NS_ASSERTION(!rule->GetImportantRule(), "Unexpected important rule");
     731                 :   }
     732                 : }
     733                 : 
     734                 : void
     735               0 : nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
     736                 :                              nsRuleNode* aLastPrevLevelNode)
     737                 : {
     738               0 :   if (!aCurrLevelNode)
     739               0 :     return;
     740                 : 
     741               0 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
     742                 :        node = node->GetParent()) {
     743               0 :     nsIStyleRule *rule = node->GetRule();
     744               0 :     nsRefPtr<css::StyleRule> cssRule(do_QueryObject(rule));
     745               0 :     NS_ASSERTION(!cssRule || !cssRule->Selector(), "Unexpected CSS rule");
     746                 :   }
     747                 : }
     748                 : #endif
     749                 : 
     750                 : // Enumerate the rules in a way that cares about the order of the rules.
     751                 : void
     752               0 : nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, 
     753                 :                       void* aData, nsIContent* aContent,
     754                 :                       nsRuleWalker* aRuleWalker)
     755                 : {
     756                 :   // Cascading order:
     757                 :   // [least important]
     758                 :   //  1. UA normal rules                    = Agent        normal
     759                 :   //  2. User normal rules                  = User         normal
     760                 :   //  3. Presentation hints                 = PresHint     normal
     761                 :   //  4. Author normal rules                = Document     normal
     762                 :   //  5. Override normal rules              = Override     normal
     763                 :   //  6. Author !important rules            = Document     !important
     764                 :   //  7. Override !important rules          = Override     !important
     765                 :   //  -. animation rules                    = Animation    normal
     766                 :   //  8. User !important rules              = User         !important
     767                 :   //  9. UA !important rules                = Agent        !important
     768                 :   //  -. transition rules                   = Transition   normal
     769                 :   // [most important]
     770                 : 
     771                 :   // Save off the last rule before we start walking our agent sheets;
     772                 :   // this will be either the root or one of the restriction rules.
     773               0 :   nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
     774                 : 
     775               0 :   aRuleWalker->SetLevel(eAgentSheet, false, true);
     776               0 :   if (mRuleProcessors[eAgentSheet])
     777               0 :     (*aCollectorFunc)(mRuleProcessors[eAgentSheet], aData);
     778               0 :   nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode();
     779               0 :   bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules();
     780                 : 
     781               0 :   aRuleWalker->SetLevel(eUserSheet, false, true);
     782                 :   bool skipUserStyles =
     783               0 :     aContent && aContent->IsInNativeAnonymousSubtree();
     784               0 :   if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
     785               0 :     (*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
     786               0 :   nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
     787               0 :   bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
     788                 : 
     789               0 :   aRuleWalker->SetLevel(ePresHintSheet, false, false);
     790               0 :   if (mRuleProcessors[ePresHintSheet])
     791               0 :     (*aCollectorFunc)(mRuleProcessors[ePresHintSheet], aData);
     792               0 :   nsRuleNode* lastPresHintRN = aRuleWalker->CurrentNode();
     793                 :   
     794               0 :   aRuleWalker->SetLevel(eDocSheet, false, true);
     795               0 :   bool cutOffInheritance = false;
     796               0 :   if (mBindingManager && aContent) {
     797                 :     // We can supply additional document-level sheets that should be walked.
     798                 :     mBindingManager->WalkRules(aCollectorFunc,
     799                 :                                static_cast<RuleProcessorData*>(aData),
     800               0 :                                &cutOffInheritance);
     801                 :   }
     802               0 :   if (!skipUserStyles && !cutOffInheritance &&
     803               0 :       mRuleProcessors[eDocSheet]) // NOTE: different
     804               0 :     (*aCollectorFunc)(mRuleProcessors[eDocSheet], aData);
     805                 :   aRuleWalker->SetLevel(eStyleAttrSheet, false,
     806               0 :                         aRuleWalker->GetCheckForImportantRules());
     807               0 :   if (mRuleProcessors[eStyleAttrSheet])
     808               0 :     (*aCollectorFunc)(mRuleProcessors[eStyleAttrSheet], aData);
     809               0 :   nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
     810               0 :   bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
     811                 : 
     812               0 :   aRuleWalker->SetLevel(eOverrideSheet, false, true);
     813               0 :   if (mRuleProcessors[eOverrideSheet])
     814               0 :     (*aCollectorFunc)(mRuleProcessors[eOverrideSheet], aData);
     815               0 :   nsRuleNode* lastOvrRN = aRuleWalker->CurrentNode();
     816               0 :   bool haveImportantOverrideRules = !aRuleWalker->GetCheckForImportantRules();
     817                 : 
     818               0 :   if (haveImportantDocRules) {
     819               0 :     aRuleWalker->SetLevel(eDocSheet, true, false);
     820               0 :     AddImportantRules(lastDocRN, lastPresHintRN, aRuleWalker);  // doc
     821                 :   }
     822                 : #ifdef DEBUG
     823                 :   else {
     824               0 :     AssertNoImportantRules(lastDocRN, lastPresHintRN);
     825                 :   }
     826                 : #endif
     827                 : 
     828               0 :   if (haveImportantOverrideRules) {
     829               0 :     aRuleWalker->SetLevel(eOverrideSheet, true, false);
     830               0 :     AddImportantRules(lastOvrRN, lastDocRN, aRuleWalker);  // override
     831                 :   }
     832                 : #ifdef DEBUG
     833                 :   else {
     834               0 :     AssertNoImportantRules(lastOvrRN, lastDocRN);
     835                 :   }
     836                 : #endif
     837                 : 
     838                 :   // This needs to match IsMoreSpecificThanAnimation() above.
     839               0 :   aRuleWalker->SetLevel(eAnimationSheet, false, false);
     840               0 :   (*aCollectorFunc)(mRuleProcessors[eAnimationSheet], aData);
     841                 : 
     842                 : #ifdef DEBUG
     843               0 :   AssertNoCSSRules(lastPresHintRN, lastUserRN);
     844                 : #endif
     845                 : 
     846               0 :   if (haveImportantUserRules) {
     847               0 :     aRuleWalker->SetLevel(eUserSheet, true, false);
     848               0 :     AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user
     849                 :   }
     850                 : #ifdef DEBUG
     851                 :   else {
     852               0 :     AssertNoImportantRules(lastUserRN, lastAgentRN);
     853                 :   }
     854                 : #endif
     855                 : 
     856               0 :   if (haveImportantUARules) {
     857               0 :     aRuleWalker->SetLevel(eAgentSheet, true, false);
     858               0 :     AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent
     859                 :   }
     860                 : #ifdef DEBUG
     861                 :   else {
     862               0 :     AssertNoImportantRules(lastAgentRN, lastRestrictionRN);
     863                 :   }
     864                 : #endif
     865                 : 
     866                 : #ifdef DEBUG
     867               0 :   AssertNoCSSRules(lastRestrictionRN, mRuleTree);
     868                 : #endif
     869                 : 
     870                 : #ifdef DEBUG
     871               0 :   nsRuleNode *lastImportantRN = aRuleWalker->CurrentNode();
     872                 : #endif
     873               0 :   aRuleWalker->SetLevel(eTransitionSheet, false, false);
     874               0 :   (*aCollectorFunc)(mRuleProcessors[eTransitionSheet], aData);
     875                 : #ifdef DEBUG
     876               0 :   AssertNoCSSRules(aRuleWalker->CurrentNode(), lastImportantRN);
     877                 : #endif
     878                 : 
     879               0 : }
     880                 : 
     881                 : // Enumerate all the rules in a way that doesn't care about the order
     882                 : // of the rules and doesn't walk !important-rules.
     883                 : void
     884               0 : nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
     885                 :                                RuleProcessorData* aData,
     886                 :                                bool aWalkAllXBLStylesheets)
     887                 : {
     888               0 :   if (mRuleProcessors[eAgentSheet])
     889               0 :     (*aFunc)(mRuleProcessors[eAgentSheet], aData);
     890                 : 
     891               0 :   bool skipUserStyles = aData->mElement->IsInNativeAnonymousSubtree();
     892               0 :   if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
     893               0 :     (*aFunc)(mRuleProcessors[eUserSheet], aData);
     894                 : 
     895               0 :   if (mRuleProcessors[ePresHintSheet])
     896               0 :     (*aFunc)(mRuleProcessors[ePresHintSheet], aData);
     897                 :   
     898               0 :   bool cutOffInheritance = false;
     899               0 :   if (mBindingManager) {
     900                 :     // We can supply additional document-level sheets that should be walked.
     901               0 :     if (aWalkAllXBLStylesheets) {
     902               0 :       mBindingManager->WalkAllRules(aFunc, aData);
     903                 :     } else {
     904               0 :       mBindingManager->WalkRules(aFunc, aData, &cutOffInheritance);
     905                 :     }
     906                 :   }
     907               0 :   if (!skipUserStyles && !cutOffInheritance &&
     908               0 :       mRuleProcessors[eDocSheet]) // NOTE: different
     909               0 :     (*aFunc)(mRuleProcessors[eDocSheet], aData);
     910               0 :   if (mRuleProcessors[eStyleAttrSheet])
     911               0 :     (*aFunc)(mRuleProcessors[eStyleAttrSheet], aData);
     912               0 :   if (mRuleProcessors[eOverrideSheet])
     913               0 :     (*aFunc)(mRuleProcessors[eOverrideSheet], aData);
     914               0 :   (*aFunc)(mRuleProcessors[eAnimationSheet], aData);
     915               0 :   (*aFunc)(mRuleProcessors[eTransitionSheet], aData);
     916               0 : }
     917                 : 
     918               0 : bool nsStyleSet::BuildDefaultStyleData(nsPresContext* aPresContext)
     919                 : {
     920               0 :   NS_ASSERTION(!mDefaultStyleData.mResetData &&
     921                 :                !mDefaultStyleData.mInheritedData,
     922                 :                "leaking default style data");
     923               0 :   mDefaultStyleData.mResetData = new (aPresContext) nsResetStyleData;
     924               0 :   if (!mDefaultStyleData.mResetData)
     925               0 :     return false;
     926               0 :   mDefaultStyleData.mInheritedData = new (aPresContext) nsInheritedStyleData;
     927               0 :   if (!mDefaultStyleData.mInheritedData)
     928               0 :     return false;
     929                 : 
     930                 : #define SSARG_PRESCONTEXT aPresContext
     931                 : 
     932                 : #define CREATE_DATA(name, type, args) \
     933                 :   if (!(mDefaultStyleData.m##type##Data->mStyleStructs[eStyleStruct_##name] = \
     934                 :           new (aPresContext) nsStyle##name args)) \
     935                 :     return false;
     936                 : 
     937                 : #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \
     938                 :   CREATE_DATA(name, Inherited, ctor_args)
     939                 : #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \
     940                 :   CREATE_DATA(name, Reset, ctor_args)
     941                 : 
     942                 : #include "nsStyleStructList.h"
     943                 : 
     944                 : #undef STYLE_STRUCT_INHERITED
     945                 : #undef STYLE_STRUCT_RESET
     946                 : #undef SSARG_PRESCONTEXT
     947                 : 
     948               0 :   return true;
     949                 : }
     950                 : 
     951                 : already_AddRefed<nsStyleContext>
     952               0 : nsStyleSet::ResolveStyleFor(Element* aElement,
     953                 :                             nsStyleContext* aParentContext)
     954                 : {
     955                 :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
     956               0 :                                aElement->OwnerDoc());
     957               0 :   return ResolveStyleFor(aElement, aParentContext, treeContext);
     958                 : }
     959                 : 
     960                 : already_AddRefed<nsStyleContext>
     961               0 : nsStyleSet::ResolveStyleFor(Element* aElement,
     962                 :                             nsStyleContext* aParentContext,
     963                 :                             TreeMatchContext& aTreeMatchContext)
     964                 : {
     965               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
     966               0 :   NS_ASSERTION(aElement, "aElement must not be null");
     967                 : 
     968               0 :   nsRuleWalker ruleWalker(mRuleTree);
     969               0 :   aTreeMatchContext.ResetForUnvisitedMatching();
     970                 :   ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker,
     971               0 :                                 aTreeMatchContext);
     972                 :   FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
     973               0 :             &ruleWalker);
     974                 : 
     975               0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
     976               0 :   nsRuleNode *visitedRuleNode = nsnull;
     977                 : 
     978               0 :   if (aTreeMatchContext.HaveRelevantLink()) {
     979               0 :     aTreeMatchContext.ResetForVisitedMatching();
     980               0 :     ruleWalker.Reset();
     981                 :     FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
     982               0 :               &ruleWalker);
     983               0 :     visitedRuleNode = ruleWalker.CurrentNode();
     984                 :   }
     985                 : 
     986                 :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
     987               0 :                     nsCSSRuleProcessor::IsLink(aElement),
     988                 :                     nsCSSRuleProcessor::GetContentState(aElement).
     989               0 :                       HasState(NS_EVENT_STATE_VISITED),
     990                 :                     nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement,
     991               0 :                     true, aElement);
     992                 : }
     993                 : 
     994                 : already_AddRefed<nsStyleContext>
     995               0 : nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
     996                 :                                  const nsCOMArray<nsIStyleRule> &aRules)
     997                 : {
     998               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
     999                 : 
    1000               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1001                 :   // FIXME: Perhaps this should be passed in, but it probably doesn't
    1002                 :   // matter.
    1003               0 :   ruleWalker.SetLevel(eDocSheet, false, false);
    1004               0 :   for (PRInt32 i = 0; i < aRules.Count(); i++) {
    1005               0 :     ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
    1006                 :   }
    1007                 : 
    1008                 :   return GetContext(aParentContext, ruleWalker.CurrentNode(), nsnull,
    1009                 :                     false, false,
    1010                 :                     nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement,
    1011               0 :                     false, nsnull);
    1012                 : }
    1013                 : 
    1014                 : already_AddRefed<nsStyleContext>
    1015               0 : nsStyleSet::ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
    1016                 :                                       const nsCOMArray<nsIStyleRule> &aRules)
    1017                 : {
    1018               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
    1019                 : 
    1020               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1021               0 :   ruleWalker.SetCurrentNode(aBaseContext->GetRuleNode());
    1022                 :   // FIXME: Perhaps this should be passed in, but it probably doesn't
    1023                 :   // matter.
    1024               0 :   ruleWalker.SetLevel(eDocSheet, false, false);
    1025               0 :   for (PRInt32 i = 0; i < aRules.Count(); i++) {
    1026               0 :     ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
    1027                 :   }
    1028                 : 
    1029               0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1030               0 :   nsRuleNode *visitedRuleNode = nsnull;
    1031                 : 
    1032               0 :   if (aBaseContext->GetStyleIfVisited()) {
    1033               0 :     ruleWalker.SetCurrentNode(aBaseContext->GetStyleIfVisited()->GetRuleNode());
    1034               0 :     for (PRInt32 i = 0; i < aRules.Count(); i++) {
    1035               0 :       ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
    1036                 :     }
    1037               0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1038                 :   }
    1039                 : 
    1040                 :   return GetContext(aBaseContext->GetParent(), ruleNode, visitedRuleNode,
    1041               0 :                     aBaseContext->IsLinkContext(),
    1042               0 :                     aBaseContext->RelevantLinkVisited(),
    1043                 :                     aBaseContext->GetPseudo(),
    1044                 :                     aBaseContext->GetPseudoType(),
    1045               0 :                     false, nsnull);
    1046                 : }
    1047                 : 
    1048                 : already_AddRefed<nsStyleContext>
    1049               0 : nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
    1050                 : {
    1051                 :   return GetContext(aParentContext, mRuleTree, nsnull,
    1052                 :                     false, false,
    1053                 :                     nsCSSAnonBoxes::mozNonElement,
    1054               0 :                     nsCSSPseudoElements::ePseudo_AnonBox, false, nsnull);
    1055                 : }
    1056                 : 
    1057                 : void
    1058               0 : nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
    1059                 :                                 nsRuleWalker* aRuleWalker)
    1060                 : {
    1061                 :   // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
    1062               0 :   aRuleWalker->SetLevel(eAgentSheet, false, false);
    1063               0 :   if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter)
    1064               0 :     aRuleWalker->Forward(mFirstLetterRule);
    1065               0 :   else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine)
    1066               0 :     aRuleWalker->Forward(mFirstLineRule);
    1067               0 : }
    1068                 : 
    1069                 : already_AddRefed<nsStyleContext>
    1070               0 : nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
    1071                 :                                       nsCSSPseudoElements::Type aType,
    1072                 :                                       nsStyleContext* aParentContext)
    1073                 : {
    1074               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
    1075                 : 
    1076               0 :   NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
    1077                 :                "must have pseudo element type");
    1078               0 :   NS_ASSERTION(aParentElement, "Must have parent element");
    1079                 : 
    1080               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1081                 :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1082               0 :                                aParentElement->OwnerDoc());
    1083                 :   PseudoElementRuleProcessorData data(PresContext(), aParentElement,
    1084               0 :                                       &ruleWalker, aType, treeContext);
    1085               0 :   WalkRestrictionRule(aType, &ruleWalker);
    1086                 :   FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1087               0 :             aParentElement, &ruleWalker);
    1088                 : 
    1089               0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1090               0 :   nsRuleNode *visitedRuleNode = nsnull;
    1091                 : 
    1092               0 :   if (treeContext.HaveRelevantLink()) {
    1093               0 :     treeContext.ResetForVisitedMatching();
    1094               0 :     ruleWalker.Reset();
    1095               0 :     WalkRestrictionRule(aType, &ruleWalker);
    1096                 :     FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1097               0 :               aParentElement, &ruleWalker);
    1098               0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1099                 :   }
    1100                 : 
    1101                 :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
    1102                 :                     // For pseudos, |data.IsLink()| being true means that
    1103                 :                     // our parent node is a link.
    1104                 :                     false, false,
    1105                 :                     nsCSSPseudoElements::GetPseudoAtom(aType), aType,
    1106                 :                     aType == nsCSSPseudoElements::ePseudo_before ||
    1107                 :                     aType == nsCSSPseudoElements::ePseudo_after,
    1108               0 :                     aParentElement);
    1109                 : }
    1110                 : 
    1111                 : already_AddRefed<nsStyleContext>
    1112               0 : nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
    1113                 :                                     nsCSSPseudoElements::Type aType,
    1114                 :                                     nsStyleContext* aParentContext)
    1115                 : {
    1116                 :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1117               0 :                                aParentElement->OwnerDoc());
    1118                 :   return ProbePseudoElementStyle(aParentElement, aType, aParentContext,
    1119               0 :                                  treeContext);
    1120                 : }
    1121                 : 
    1122                 : already_AddRefed<nsStyleContext>
    1123               0 : nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
    1124                 :                                     nsCSSPseudoElements::Type aType,
    1125                 :                                     nsStyleContext* aParentContext,
    1126                 :                                     TreeMatchContext& aTreeMatchContext)
    1127                 : {
    1128               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
    1129                 : 
    1130               0 :   NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
    1131                 :                "must have pseudo element type");
    1132               0 :   NS_ASSERTION(aParentElement, "aParentElement must not be null");
    1133                 : 
    1134               0 :   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
    1135               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1136               0 :   aTreeMatchContext.ResetForUnvisitedMatching();
    1137                 :   PseudoElementRuleProcessorData data(PresContext(), aParentElement,
    1138               0 :                                       &ruleWalker, aType, aTreeMatchContext);
    1139               0 :   WalkRestrictionRule(aType, &ruleWalker);
    1140                 :   // not the root if there was a restriction rule
    1141               0 :   nsRuleNode *adjustedRoot = ruleWalker.CurrentNode();
    1142                 :   FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1143               0 :             aParentElement, &ruleWalker);
    1144                 : 
    1145               0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1146               0 :   if (ruleNode == adjustedRoot) {
    1147               0 :     return nsnull;
    1148                 :   }
    1149                 : 
    1150               0 :   nsRuleNode *visitedRuleNode = nsnull;
    1151                 : 
    1152               0 :   if (aTreeMatchContext.HaveRelevantLink()) {
    1153               0 :     aTreeMatchContext.ResetForVisitedMatching();
    1154               0 :     ruleWalker.Reset();
    1155               0 :     WalkRestrictionRule(aType, &ruleWalker);
    1156                 :     FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1157               0 :               aParentElement, &ruleWalker);
    1158               0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1159                 :   }
    1160                 : 
    1161                 :   nsRefPtr<nsStyleContext> result =
    1162                 :     GetContext(aParentContext, ruleNode, visitedRuleNode,
    1163                 :                // For pseudos, |data.IsLink()| being true means that
    1164                 :                // our parent node is a link.
    1165                 :                false, false,
    1166                 :                pseudoTag, aType,
    1167                 :                aType == nsCSSPseudoElements::ePseudo_before ||
    1168                 :                aType == nsCSSPseudoElements::ePseudo_after,
    1169               0 :                aParentElement);
    1170                 : 
    1171                 :   // For :before and :after pseudo-elements, having display: none or no
    1172                 :   // 'content' property is equivalent to not having the pseudo-element
    1173                 :   // at all.
    1174               0 :   if (result &&
    1175                 :       (pseudoTag == nsCSSPseudoElements::before ||
    1176               0 :        pseudoTag == nsCSSPseudoElements::after)) {
    1177               0 :     const nsStyleDisplay *display = result->GetStyleDisplay();
    1178               0 :     const nsStyleContent *content = result->GetStyleContent();
    1179                 :     // XXXldb What is contentCount for |content: ""|?
    1180               0 :     if (display->mDisplay == NS_STYLE_DISPLAY_NONE ||
    1181               0 :         content->ContentCount() == 0) {
    1182               0 :       result = nsnull;
    1183                 :     }
    1184                 :   }
    1185                 : 
    1186               0 :   return result.forget();
    1187                 : }
    1188                 : 
    1189                 : already_AddRefed<nsStyleContext>
    1190               0 : nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
    1191                 :                                      nsStyleContext* aParentContext)
    1192                 : {
    1193               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
    1194                 : 
    1195                 : #ifdef DEBUG
    1196               0 :     bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag)
    1197                 : #ifdef MOZ_XUL
    1198               0 :                  && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
    1199                 : #endif
    1200                 :       ;
    1201               0 :     NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
    1202                 : #endif
    1203                 : 
    1204               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1205               0 :   AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker);
    1206                 :   FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nsnull,
    1207               0 :             &ruleWalker);
    1208                 : 
    1209                 :   return GetContext(aParentContext, ruleWalker.CurrentNode(), nsnull,
    1210                 :                     false, false,
    1211                 :                     aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox,
    1212               0 :                     false, nsnull);
    1213                 : }
    1214                 : 
    1215                 : #ifdef MOZ_XUL
    1216                 : already_AddRefed<nsStyleContext>
    1217               0 : nsStyleSet::ResolveXULTreePseudoStyle(Element* aParentElement,
    1218                 :                                       nsIAtom* aPseudoTag,
    1219                 :                                       nsStyleContext* aParentContext,
    1220                 :                                       nsICSSPseudoComparator* aComparator)
    1221                 : {
    1222               0 :   NS_ENSURE_FALSE(mInShutdown, nsnull);
    1223                 : 
    1224               0 :   NS_ASSERTION(aPseudoTag, "must have pseudo tag");
    1225               0 :   NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
    1226                 :                "Unexpected pseudo");
    1227                 : 
    1228               0 :   nsRuleWalker ruleWalker(mRuleTree);
    1229                 :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1230               0 :                                aParentElement->OwnerDoc());
    1231                 :   XULTreeRuleProcessorData data(PresContext(), aParentElement, &ruleWalker,
    1232               0 :                                 aPseudoTag, aComparator, treeContext);
    1233                 :   FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, aParentElement,
    1234               0 :             &ruleWalker);
    1235                 : 
    1236               0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1237               0 :   nsRuleNode *visitedRuleNode = nsnull;
    1238                 : 
    1239               0 :   if (treeContext.HaveRelevantLink()) {
    1240               0 :     treeContext.ResetForVisitedMatching();
    1241               0 :     ruleWalker.Reset();
    1242                 :     FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data,
    1243               0 :               aParentElement, &ruleWalker);
    1244               0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1245                 :   }
    1246                 : 
    1247                 :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
    1248                 :                     // For pseudos, |data.IsLink()| being true means that
    1249                 :                     // our parent node is a link.
    1250                 :                     false, false,
    1251                 :                     aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree,
    1252               0 :                     false, nsnull);
    1253                 : }
    1254                 : #endif
    1255                 : 
    1256                 : bool
    1257               0 : nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext,
    1258                 :                                 nsTArray<nsFontFaceRuleContainer>& aArray)
    1259                 : {
    1260               0 :   NS_ENSURE_FALSE(mInShutdown, false);
    1261                 : 
    1262               0 :   for (PRUint32 i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    1263                 :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    1264               0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    1265               0 :     if (ruleProc && !ruleProc->AppendFontFaceRules(aPresContext, aArray))
    1266               0 :       return false;
    1267                 :   }
    1268               0 :   return true;
    1269                 : }
    1270                 : 
    1271                 : bool
    1272               0 : nsStyleSet::AppendKeyframesRules(nsPresContext* aPresContext,
    1273                 :                                  nsTArray<nsCSSKeyframesRule*>& aArray)
    1274                 : {
    1275               0 :   NS_ENSURE_FALSE(mInShutdown, false);
    1276                 : 
    1277               0 :   for (PRUint32 i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    1278                 :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    1279               0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    1280               0 :     if (ruleProc && !ruleProc->AppendKeyframesRules(aPresContext, aArray))
    1281               0 :       return false;
    1282                 :   }
    1283               0 :   return true;
    1284                 : }
    1285                 : 
    1286                 : void
    1287               0 : nsStyleSet::BeginShutdown(nsPresContext* aPresContext)
    1288                 : {
    1289               0 :   mInShutdown = 1;
    1290               0 :   mRoots.Clear(); // no longer valid, since we won't keep it up to date
    1291               0 : }
    1292                 : 
    1293                 : void
    1294               0 : nsStyleSet::Shutdown(nsPresContext* aPresContext)
    1295                 : {
    1296               0 :   mRuleTree->Destroy();
    1297               0 :   mRuleTree = nsnull;
    1298                 : 
    1299                 :   // We can have old rule trees either because:
    1300                 :   //   (1) we failed the assertions in EndReconstruct, or
    1301                 :   //   (2) we're shutting down within a reconstruct (see bug 462392)
    1302               0 :   for (PRUint32 i = mOldRuleTrees.Length(); i > 0; ) {
    1303               0 :     --i;
    1304               0 :     mOldRuleTrees[i]->Destroy();
    1305                 :   }
    1306               0 :   mOldRuleTrees.Clear();
    1307                 : 
    1308               0 :   mDefaultStyleData.Destroy(0, aPresContext);
    1309               0 : }
    1310                 : 
    1311                 : static const PRUint32 kGCInterval = 300;
    1312                 : 
    1313                 : void
    1314               0 : nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
    1315                 :                                         nsStyleContext* aStyleContext)
    1316                 : {
    1317               0 :   if (mInShutdown)
    1318               0 :     return;
    1319                 : 
    1320                 :   // Remove style contexts from mRoots even if mOldRuleTree is non-null.  This
    1321                 :   // could be a style context from the new ruletree!
    1322               0 :   if (!aStyleContext->GetParent()) {
    1323               0 :     mRoots.RemoveElement(aStyleContext);
    1324                 :   }
    1325                 : 
    1326               0 :   if (mInReconstruct)
    1327               0 :     return;
    1328                 : 
    1329               0 :   if (mUnusedRuleNodeCount >= kGCInterval) {
    1330               0 :     GCRuleTrees();
    1331                 :   }
    1332                 : }
    1333                 : 
    1334                 : void
    1335               0 : nsStyleSet::GCRuleTrees()
    1336                 : {
    1337               0 :   mUnusedRuleNodeCount = 0;
    1338                 : 
    1339                 :   // Mark the style context tree by marking all style contexts which
    1340                 :   // have no parent, which will mark all descendants.  This will reach
    1341                 :   // style contexts in the undisplayed map and "additional style
    1342                 :   // contexts" since they are descendants of the roots.
    1343               0 :   for (PRInt32 i = mRoots.Length() - 1; i >= 0; --i) {
    1344               0 :     mRoots[i]->Mark();
    1345                 :   }
    1346                 : 
    1347                 :   // Sweep the rule tree.
    1348                 : #ifdef DEBUG
    1349                 :   bool deleted =
    1350                 : #endif
    1351               0 :     mRuleTree->Sweep();
    1352               0 :   NS_ASSERTION(!deleted, "Root node must not be gc'd");
    1353                 : 
    1354                 :   // Sweep the old rule trees.
    1355               0 :   for (PRUint32 i = mOldRuleTrees.Length(); i > 0; ) {
    1356               0 :     --i;
    1357               0 :     if (mOldRuleTrees[i]->Sweep()) {
    1358                 :       // It was deleted, as it should be.
    1359               0 :       mOldRuleTrees.RemoveElementAt(i);
    1360                 :     } else {
    1361               0 :       NS_NOTREACHED("old rule tree still referenced");
    1362                 :     }
    1363                 :   }
    1364               0 : }
    1365                 : 
    1366                 : static inline nsRuleNode*
    1367               0 : SkipAnimationRules(nsRuleNode* aRuleNode, Element* aElement, bool isPseudo)
    1368                 : {
    1369               0 :   nsRuleNode* ruleNode = aRuleNode;
    1370               0 :   while (!ruleNode->IsRoot() &&
    1371               0 :          (ruleNode->GetLevel() == nsStyleSet::eTransitionSheet ||
    1372               0 :           ruleNode->GetLevel() == nsStyleSet::eAnimationSheet)) {
    1373               0 :     ruleNode = ruleNode->GetParent();
    1374                 :   }
    1375               0 :   if (ruleNode != aRuleNode) {
    1376               0 :     NS_ASSERTION(aElement, "How can we have transition rules but no element?");
    1377                 :     // Need to do an animation restyle, just like
    1378                 :     // nsTransitionManager::WalkTransitionRule and
    1379                 :     // nsAnimationManager::GetAnimationRule would.
    1380               0 :     nsRestyleHint hint = isPseudo ? eRestyle_Subtree : eRestyle_Self;
    1381                 :     aRuleNode->GetPresContext()->PresShell()->RestyleForAnimation(aElement,
    1382               0 :                                                                   hint);
    1383                 :   }
    1384               0 :   return ruleNode;
    1385                 : }
    1386                 : 
    1387                 : already_AddRefed<nsStyleContext>
    1388               0 : nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
    1389                 :                                  nsStyleContext* aNewParentContext,
    1390                 :                                  Element* aElement)
    1391                 : {
    1392               0 :   if (!aStyleContext) {
    1393               0 :     NS_NOTREACHED("must have style context");
    1394               0 :     return nsnull;
    1395                 :   }
    1396                 : 
    1397                 :   // This short-circuit is OK because we don't call TryStartingTransition
    1398                 :   // during style reresolution if the style context pointer hasn't changed.
    1399               0 :   if (aStyleContext->GetParent() == aNewParentContext) {
    1400               0 :     aStyleContext->AddRef();
    1401               0 :     return aStyleContext;
    1402                 :   }
    1403                 : 
    1404               0 :   nsIAtom* pseudoTag = aStyleContext->GetPseudo();
    1405               0 :   nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType();
    1406               0 :   nsRuleNode* ruleNode = aStyleContext->GetRuleNode();
    1407                 : 
    1408                 :   // Skip transition rules as needed just like
    1409                 :   // nsTransitionManager::WalkTransitionRule would.
    1410               0 :   bool skipAnimationRules = PresContext()->IsProcessingRestyles() &&
    1411               0 :     !PresContext()->IsProcessingAnimationStyleChange();
    1412               0 :   if (skipAnimationRules) {
    1413                 :     // Make sure that we're not using transition rules or animation rules for
    1414                 :     // our new style context.  If we need them, an animation restyle will
    1415                 :     // provide.
    1416                 :     ruleNode =
    1417                 :       SkipAnimationRules(ruleNode, aElement,
    1418                 :                          pseudoType !=
    1419               0 :                            nsCSSPseudoElements::ePseudo_NotPseudoElement);
    1420                 :   }
    1421                 : 
    1422               0 :   nsRuleNode* visitedRuleNode = nsnull;
    1423               0 :   nsStyleContext* visitedContext = aStyleContext->GetStyleIfVisited();
    1424                 :   // Reparenting a style context just changes where we inherit from,
    1425                 :   // not what rules we match or what our DOM looks like.  In
    1426                 :   // particular, it doesn't change whether this is a style context for
    1427                 :   // a link.
    1428               0 :   if (visitedContext) {
    1429               0 :      visitedRuleNode = visitedContext->GetRuleNode();
    1430                 :      // Again, skip transition rules as needed
    1431               0 :      if (skipAnimationRules) {
    1432                 :       // FIXME do something here for animations?
    1433                 :        visitedRuleNode =
    1434                 :          SkipAnimationRules(visitedRuleNode, aElement,
    1435                 :                             pseudoType !=
    1436               0 :                               nsCSSPseudoElements::ePseudo_NotPseudoElement);
    1437                 :      }
    1438                 :   }
    1439                 : 
    1440                 :   // If we're a style context for a link, then we already know whether
    1441                 :   // our relevant link is visited, since that does not depend on our
    1442                 :   // parent.  Otherwise, we need to match aNewParentContext.
    1443               0 :   bool relevantLinkVisited = aStyleContext->IsLinkContext() ?
    1444                 :     aStyleContext->RelevantLinkVisited() :
    1445               0 :     aNewParentContext->RelevantLinkVisited();
    1446                 : 
    1447                 :   return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
    1448               0 :                     aStyleContext->IsLinkContext(),
    1449                 :                     relevantLinkVisited,
    1450                 :                     pseudoTag, pseudoType,
    1451                 :                     pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
    1452                 :                     pseudoType == nsCSSPseudoElements::ePseudo_before ||
    1453                 :                     pseudoType == nsCSSPseudoElements::ePseudo_after,
    1454               0 :                     aElement);
    1455                 : }
    1456                 : 
    1457                 : struct StatefulData : public StateRuleProcessorData {
    1458               0 :   StatefulData(nsPresContext* aPresContext, Element* aElement,
    1459                 :                nsEventStates aStateMask, TreeMatchContext& aTreeMatchContext)
    1460                 :     : StateRuleProcessorData(aPresContext, aElement, aStateMask,
    1461                 :                              aTreeMatchContext),
    1462               0 :       mHint(nsRestyleHint(0))
    1463               0 :   {}
    1464                 :   nsRestyleHint   mHint;
    1465                 : };
    1466                 : 
    1467               0 : static bool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor,
    1468                 :                                          void *aData)
    1469                 : {
    1470               0 :   StatefulData* data = (StatefulData*)aData;
    1471               0 :   if (aProcessor->HasDocumentStateDependentStyle(data)) {
    1472               0 :     data->mHint = eRestyle_Self;
    1473               0 :     return false; // don't continue
    1474                 :   }
    1475               0 :   return true; // continue
    1476                 : }
    1477                 : 
    1478                 : // Test if style is dependent on a document state.
    1479                 : bool
    1480               0 : nsStyleSet::HasDocumentStateDependentStyle(nsPresContext* aPresContext,
    1481                 :                                            nsIContent*    aContent,
    1482                 :                                            nsEventStates  aStateMask)
    1483                 : {
    1484               0 :   if (!aContent || !aContent->IsElement())
    1485               0 :     return false;
    1486                 : 
    1487                 :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    1488               0 :                                aContent->OwnerDoc());
    1489                 :   StatefulData data(aPresContext, aContent->AsElement(), aStateMask,
    1490               0 :                     treeContext);
    1491               0 :   WalkRuleProcessors(SheetHasDocumentStateStyle, &data, true);
    1492               0 :   return data.mHint != 0;
    1493                 : }
    1494                 : 
    1495               0 : static bool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor,
    1496                 :                                     void *aData)
    1497                 : {
    1498               0 :   StatefulData* data = (StatefulData*)aData;
    1499               0 :   nsRestyleHint hint = aProcessor->HasStateDependentStyle(data);
    1500               0 :   data->mHint = nsRestyleHint(data->mHint | hint);
    1501               0 :   return true; // continue
    1502                 : }
    1503                 : 
    1504                 : // Test if style is dependent on content state
    1505                 : nsRestyleHint
    1506               0 : nsStyleSet::HasStateDependentStyle(nsPresContext*       aPresContext,
    1507                 :                                    Element*             aElement,
    1508                 :                                    nsEventStates        aStateMask)
    1509                 : {
    1510                 :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    1511               0 :                                aElement->OwnerDoc());
    1512               0 :   StatefulData data(aPresContext, aElement, aStateMask, treeContext);
    1513               0 :   WalkRuleProcessors(SheetHasStatefulStyle, &data, false);
    1514               0 :   return data.mHint;
    1515                 : }
    1516                 : 
    1517                 : struct AttributeData : public AttributeRuleProcessorData {
    1518               0 :   AttributeData(nsPresContext* aPresContext,
    1519                 :                 Element* aElement, nsIAtom* aAttribute, PRInt32 aModType,
    1520                 :                 bool aAttrHasChanged, TreeMatchContext& aTreeMatchContext)
    1521                 :     : AttributeRuleProcessorData(aPresContext, aElement, aAttribute, aModType,
    1522                 :                                  aAttrHasChanged, aTreeMatchContext),
    1523               0 :       mHint(nsRestyleHint(0))
    1524               0 :   {}
    1525                 :   nsRestyleHint   mHint;
    1526                 : }; 
    1527                 : 
    1528                 : static bool
    1529               0 : SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)
    1530                 : {
    1531               0 :   AttributeData* data = (AttributeData*)aData;
    1532               0 :   nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data);
    1533               0 :   data->mHint = nsRestyleHint(data->mHint | hint);
    1534               0 :   return true; // continue
    1535                 : }
    1536                 : 
    1537                 : // Test if style is dependent on content state
    1538                 : nsRestyleHint
    1539               0 : nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext,
    1540                 :                                        Element*       aElement,
    1541                 :                                        nsIAtom*       aAttribute,
    1542                 :                                        PRInt32        aModType,
    1543                 :                                        bool           aAttrHasChanged)
    1544                 : {
    1545                 :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    1546               0 :                                aElement->OwnerDoc());
    1547                 :   AttributeData data(aPresContext, aElement, aAttribute,
    1548               0 :                      aModType, aAttrHasChanged, treeContext);
    1549               0 :   WalkRuleProcessors(SheetHasAttributeStyle, &data, false);
    1550               0 :   return data.mHint;
    1551                 : }
    1552                 : 
    1553                 : bool
    1554               0 : nsStyleSet::MediumFeaturesChanged(nsPresContext* aPresContext)
    1555                 : {
    1556                 :   // We can't use WalkRuleProcessors without a content node.
    1557               0 :   bool stylesChanged = false;
    1558               0 :   for (PRUint32 i = 0; i < ArrayLength(mRuleProcessors); ++i) {
    1559               0 :     nsIStyleRuleProcessor *processor = mRuleProcessors[i];
    1560               0 :     if (!processor) {
    1561               0 :       continue;
    1562                 :     }
    1563               0 :     bool thisChanged = processor->MediumFeaturesChanged(aPresContext);
    1564               0 :     stylesChanged = stylesChanged || thisChanged;
    1565                 :   }
    1566                 : 
    1567               0 :   if (mBindingManager) {
    1568               0 :     bool thisChanged = false;
    1569               0 :     mBindingManager->MediumFeaturesChanged(aPresContext, &thisChanged);
    1570               0 :     stylesChanged = stylesChanged || thisChanged;
    1571                 :   }
    1572                 : 
    1573               0 :   return stylesChanged;
    1574                 : }
    1575                 : 
    1576                 : nsCSSStyleSheet::EnsureUniqueInnerResult
    1577               0 : nsStyleSet::EnsureUniqueInnerOnCSSSheets()
    1578                 : {
    1579               0 :   nsAutoTArray<nsCSSStyleSheet*, 32> queue;
    1580               0 :   for (PRUint32 i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    1581               0 :     nsCOMArray<nsIStyleSheet> &sheets = mSheets[gCSSSheetTypes[i]];
    1582               0 :     for (PRUint32 j = 0, j_end = sheets.Count(); j < j_end; ++j) {
    1583               0 :       nsCSSStyleSheet *sheet = static_cast<nsCSSStyleSheet*>(sheets[j]);
    1584               0 :       if (!queue.AppendElement(sheet)) {
    1585               0 :         return nsCSSStyleSheet::eUniqueInner_CloneFailed;
    1586                 :       }
    1587                 :     }
    1588                 :   }
    1589                 : 
    1590               0 :   if (mBindingManager) {
    1591               0 :     mBindingManager->AppendAllSheets(queue);
    1592                 :   }
    1593                 : 
    1594                 :   nsCSSStyleSheet::EnsureUniqueInnerResult res =
    1595               0 :     nsCSSStyleSheet::eUniqueInner_AlreadyUnique;
    1596               0 :   while (!queue.IsEmpty()) {
    1597               0 :     PRUint32 idx = queue.Length() - 1;
    1598               0 :     nsCSSStyleSheet *sheet = queue[idx];
    1599               0 :     queue.RemoveElementAt(idx);
    1600                 : 
    1601                 :     nsCSSStyleSheet::EnsureUniqueInnerResult sheetRes =
    1602               0 :       sheet->EnsureUniqueInner();
    1603               0 :     if (sheetRes == nsCSSStyleSheet::eUniqueInner_CloneFailed) {
    1604               0 :       return sheetRes;
    1605                 :     }
    1606               0 :     if (sheetRes == nsCSSStyleSheet::eUniqueInner_ClonedInner) {
    1607               0 :       res = sheetRes;
    1608                 :     }
    1609                 : 
    1610                 :     // Enqueue all the sheet's children.
    1611               0 :     if (!sheet->AppendAllChildSheets(queue)) {
    1612               0 :       return nsCSSStyleSheet::eUniqueInner_CloneFailed;
    1613                 :     }
    1614                 :   }
    1615               0 :   return res;
    1616                 : }
    1617                 : 
    1618                 : nsIStyleRule*
    1619               0 : nsStyleSet::InitialStyleRule()
    1620                 : {
    1621               0 :   if (!mInitialStyleRule) {
    1622               0 :     mInitialStyleRule = new nsInitialStyleRule;
    1623                 :   }
    1624               0 :   return mInitialStyleRule;
    1625                 : }

Generated by: LCOV version 1.7