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

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : // vim:cindent:tabstop=2:expandtab:shiftwidth=2:
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   L. David Baron <dbaron@dbaron.org>
      25                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      26                 :  *   Daniel Glazman <glazman@netscape.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /* representation of a CSS style sheet */
      43                 : 
      44                 : #include "nsCSSStyleSheet.h"
      45                 : 
      46                 : #include "nsCRT.h"
      47                 : #include "nsIAtom.h"
      48                 : #include "nsCSSRuleProcessor.h"
      49                 : #include "mozilla/css/NameSpaceRule.h"
      50                 : #include "mozilla/css/GroupRule.h"
      51                 : #include "mozilla/css/ImportRule.h"
      52                 : #include "nsIMediaList.h"
      53                 : #include "nsIDocument.h"
      54                 : #include "nsPresContext.h"
      55                 : #include "nsGkAtoms.h"
      56                 : #include "nsString.h"
      57                 : #include "nsTArray.h"
      58                 : #include "nsIDOMCSSStyleSheet.h"
      59                 : #include "nsICSSRuleList.h"
      60                 : #include "nsIDOMMediaList.h"
      61                 : #include "nsIDOMNode.h"
      62                 : #include "nsDOMError.h"
      63                 : #include "nsCSSParser.h"
      64                 : #include "mozilla/css/Loader.h"
      65                 : #include "nsICSSLoaderObserver.h"
      66                 : #include "nsINameSpaceManager.h"
      67                 : #include "nsXMLNameSpaceMap.h"
      68                 : #include "nsCOMPtr.h"
      69                 : #include "nsContentUtils.h"
      70                 : #include "nsIScriptSecurityManager.h"
      71                 : #include "mozAutoDocUpdate.h"
      72                 : #include "mozilla/css/Declaration.h"
      73                 : #include "nsRuleNode.h"
      74                 : #include "nsMediaFeatures.h"
      75                 : 
      76                 : namespace css = mozilla::css;
      77                 : 
      78                 : // -------------------------------
      79                 : // Style Rule List for the DOM
      80                 : //
      81                 : class CSSRuleListImpl : public nsICSSRuleList
      82                 : {
      83                 : public:
      84                 :   CSSRuleListImpl(nsCSSStyleSheet *aStyleSheet);
      85                 : 
      86                 :   NS_DECL_ISUPPORTS
      87                 : 
      88                 :   // nsIDOMCSSRuleList interface
      89                 :   NS_IMETHOD    GetLength(PRUint32* aLength); 
      90                 :   NS_IMETHOD    Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn); 
      91                 : 
      92                 :   virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult);
      93                 : 
      94               0 :   void DropReference() { mStyleSheet = nsnull; }
      95                 : 
      96                 : protected:
      97                 :   virtual ~CSSRuleListImpl();
      98                 : 
      99                 :   nsCSSStyleSheet*  mStyleSheet;
     100                 : };
     101                 : 
     102               0 : CSSRuleListImpl::CSSRuleListImpl(nsCSSStyleSheet *aStyleSheet)
     103                 : {
     104                 :   // Not reference counted to avoid circular references.
     105                 :   // The style sheet will tell us when its going away.
     106               0 :   mStyleSheet = aStyleSheet;
     107               0 : }
     108                 : 
     109               0 : CSSRuleListImpl::~CSSRuleListImpl()
     110                 : {
     111               0 : }
     112                 : 
     113                 : DOMCI_DATA(CSSRuleList, CSSRuleListImpl)
     114                 : 
     115                 : // QueryInterface implementation for CSSRuleList
     116               0 : NS_INTERFACE_MAP_BEGIN(CSSRuleListImpl)
     117               0 :   NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
     118               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
     119               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     120               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList)
     121               0 : NS_INTERFACE_MAP_END
     122                 : 
     123                 : 
     124               0 : NS_IMPL_ADDREF(CSSRuleListImpl)
     125               0 : NS_IMPL_RELEASE(CSSRuleListImpl)
     126                 : 
     127                 : 
     128                 : NS_IMETHODIMP    
     129               0 : CSSRuleListImpl::GetLength(PRUint32* aLength)
     130                 : {
     131               0 :   if (nsnull != mStyleSheet) {
     132               0 :     PRInt32 count = mStyleSheet->StyleRuleCount();
     133               0 :     *aLength = (PRUint32)count;
     134                 :   }
     135                 :   else {
     136               0 :     *aLength = 0;
     137                 :   }
     138                 : 
     139               0 :   return NS_OK;
     140                 : }
     141                 : 
     142                 : nsIDOMCSSRule*    
     143               0 : CSSRuleListImpl::GetItemAt(PRUint32 aIndex, nsresult* aResult)
     144                 : {
     145               0 :   nsresult result = NS_OK;
     146                 : 
     147               0 :   if (mStyleSheet) {
     148                 :     // ensure rules have correct parent
     149               0 :     if (mStyleSheet->EnsureUniqueInner() !=
     150                 :           nsCSSStyleSheet::eUniqueInner_CloneFailed) {
     151               0 :       nsRefPtr<css::Rule> rule;
     152                 : 
     153               0 :       result = mStyleSheet->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
     154               0 :       if (rule) {
     155               0 :         *aResult = NS_OK;
     156               0 :         return rule->GetDOMRule();
     157                 :       }
     158               0 :       if (result == NS_ERROR_ILLEGAL_VALUE) {
     159               0 :         result = NS_OK; // per spec: "Return Value ... null if ... not a valid index."
     160                 :       }
     161                 :     }
     162                 :   }
     163                 : 
     164               0 :   *aResult = result;
     165               0 :   return nsnull;
     166                 : }
     167                 : 
     168                 : NS_IMETHODIMP    
     169               0 : CSSRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
     170                 : {
     171                 :   nsresult rv;
     172               0 :   nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
     173               0 :   if (!rule) {
     174               0 :     *aReturn = nsnull;
     175                 : 
     176               0 :     return rv;
     177                 :   }
     178                 : 
     179               0 :   NS_ADDREF(*aReturn = rule);
     180               0 :   return NS_OK;
     181                 : }
     182                 : 
     183                 : template <class Numeric>
     184               0 : PRInt32 DoCompare(Numeric a, Numeric b)
     185                 : {
     186               0 :   if (a == b)
     187               0 :     return 0;
     188               0 :   if (a < b)
     189               0 :     return -1;
     190               0 :   return 1;
     191                 : }
     192                 : 
     193                 : bool
     194               0 : nsMediaExpression::Matches(nsPresContext *aPresContext,
     195                 :                            const nsCSSValue& aActualValue) const
     196                 : {
     197               0 :   const nsCSSValue& actual = aActualValue;
     198               0 :   const nsCSSValue& required = mValue;
     199                 : 
     200                 :   // If we don't have the feature, the match fails.
     201               0 :   if (actual.GetUnit() == eCSSUnit_Null) {
     202               0 :     return false;
     203                 :   }
     204                 : 
     205                 :   // If the expression had no value to match, the match succeeds,
     206                 :   // unless the value is an integer 0 or a zero length.
     207               0 :   if (required.GetUnit() == eCSSUnit_Null) {
     208               0 :     if (actual.GetUnit() == eCSSUnit_Integer)
     209               0 :       return actual.GetIntValue() != 0;
     210               0 :     if (actual.IsLengthUnit())
     211               0 :       return actual.GetFloatValue() != 0;
     212               0 :     return true;
     213                 :   }
     214                 : 
     215               0 :   NS_ASSERTION(mFeature->mRangeType == nsMediaFeature::eMinMaxAllowed ||
     216                 :                mRange == nsMediaExpression::eEqual, "yikes");
     217                 :   PRInt32 cmp; // -1 (actual < required)
     218                 :                //  0 (actual == required)
     219                 :                //  1 (actual > required)
     220               0 :   switch (mFeature->mValueType) {
     221                 :     case nsMediaFeature::eLength:
     222                 :       {
     223               0 :         NS_ASSERTION(actual.IsLengthUnit(), "bad actual value");
     224               0 :         NS_ASSERTION(required.IsLengthUnit(), "bad required value");
     225                 :         nscoord actualCoord = nsRuleNode::CalcLengthWithInitialFont(
     226               0 :                                 aPresContext, actual);
     227                 :         nscoord requiredCoord = nsRuleNode::CalcLengthWithInitialFont(
     228               0 :                                   aPresContext, required);
     229               0 :         cmp = DoCompare(actualCoord, requiredCoord);
     230                 :       }
     231               0 :       break;
     232                 :     case nsMediaFeature::eInteger:
     233                 :     case nsMediaFeature::eBoolInteger:
     234                 :       {
     235               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Integer,
     236                 :                      "bad actual value");
     237               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Integer,
     238                 :                      "bad required value");
     239               0 :         NS_ASSERTION(mFeature->mValueType != nsMediaFeature::eBoolInteger ||
     240                 :                      actual.GetIntValue() == 0 || actual.GetIntValue() == 1,
     241                 :                      "bad actual bool integer value");
     242               0 :         NS_ASSERTION(mFeature->mValueType != nsMediaFeature::eBoolInteger ||
     243                 :                      required.GetIntValue() == 0 || required.GetIntValue() == 1,
     244                 :                      "bad required bool integer value");
     245               0 :         cmp = DoCompare(actual.GetIntValue(), required.GetIntValue());
     246                 :       }
     247               0 :       break;
     248                 :     case nsMediaFeature::eFloat:
     249                 :       {
     250               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Number,
     251                 :                      "bad actual value");
     252               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Number,
     253                 :                      "bad required value");
     254               0 :         cmp = DoCompare(actual.GetFloatValue(), required.GetFloatValue());
     255                 :       }
     256               0 :       break;
     257                 :     case nsMediaFeature::eIntRatio:
     258                 :       {
     259               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Array &&
     260                 :                      actual.GetArrayValue()->Count() == 2 &&
     261                 :                      actual.GetArrayValue()->Item(0).GetUnit() ==
     262                 :                        eCSSUnit_Integer &&
     263                 :                      actual.GetArrayValue()->Item(1).GetUnit() ==
     264                 :                        eCSSUnit_Integer,
     265                 :                      "bad actual value");
     266               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Array &&
     267                 :                      required.GetArrayValue()->Count() == 2 &&
     268                 :                      required.GetArrayValue()->Item(0).GetUnit() ==
     269                 :                        eCSSUnit_Integer &&
     270                 :                      required.GetArrayValue()->Item(1).GetUnit() ==
     271                 :                        eCSSUnit_Integer,
     272                 :                      "bad required value");
     273                 :         // Convert to PRInt64 so we can multiply without worry.  Note
     274                 :         // that while the spec requires that both halves of |required|
     275                 :         // be positive, the numerator or denominator of |actual| might
     276                 :         // be zero (e.g., when testing 'aspect-ratio' on a 0-width or
     277                 :         // 0-height iframe).
     278               0 :         PRInt64 actualNum = actual.GetArrayValue()->Item(0).GetIntValue(),
     279               0 :                 actualDen = actual.GetArrayValue()->Item(1).GetIntValue(),
     280               0 :                 requiredNum = required.GetArrayValue()->Item(0).GetIntValue(),
     281               0 :                 requiredDen = required.GetArrayValue()->Item(1).GetIntValue();
     282               0 :         cmp = DoCompare(actualNum * requiredDen, requiredNum * actualDen);
     283                 :       }
     284               0 :       break;
     285                 :     case nsMediaFeature::eResolution:
     286                 :       {
     287               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Inch ||
     288                 :                      actual.GetUnit() == eCSSUnit_Centimeter,
     289                 :                      "bad actual value");
     290               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Inch ||
     291                 :                      required.GetUnit() == eCSSUnit_Centimeter,
     292                 :                      "bad required value");
     293               0 :         float actualDPI = actual.GetFloatValue();
     294               0 :         if (actual.GetUnit() == eCSSUnit_Centimeter)
     295               0 :           actualDPI = actualDPI * 2.54f;
     296               0 :         float requiredDPI = required.GetFloatValue();
     297               0 :         if (required.GetUnit() == eCSSUnit_Centimeter)
     298               0 :           requiredDPI = requiredDPI * 2.54f;
     299               0 :         cmp = DoCompare(actualDPI, requiredDPI);
     300                 :       }
     301               0 :       break;
     302                 :     case nsMediaFeature::eEnumerated:
     303                 :       {
     304               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Enumerated,
     305                 :                      "bad actual value");
     306               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Enumerated,
     307                 :                      "bad required value");
     308               0 :         NS_ASSERTION(mFeature->mRangeType == nsMediaFeature::eMinMaxNotAllowed,
     309                 :                      "bad range"); // we asserted above about mRange
     310                 :         // We don't really need DoCompare, but it doesn't hurt (and
     311                 :         // maybe the compiler will condense this case with eInteger).
     312               0 :         cmp = DoCompare(actual.GetIntValue(), required.GetIntValue());
     313                 :       }
     314               0 :       break;
     315                 :     case nsMediaFeature::eIdent:
     316                 :       {
     317               0 :         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Ident,
     318                 :                      "bad actual value");
     319               0 :         NS_ASSERTION(required.GetUnit() == eCSSUnit_Ident,
     320                 :                      "bad required value");
     321               0 :         NS_ASSERTION(mFeature->mRangeType == nsMediaFeature::eMinMaxNotAllowed,
     322                 :                      "bad range"); 
     323               0 :         cmp = !(actual == required); // string comparison
     324                 :       }
     325               0 :       break;
     326                 :   }
     327               0 :   switch (mRange) {
     328                 :     case nsMediaExpression::eMin:
     329               0 :       return cmp != -1;
     330                 :     case nsMediaExpression::eMax:
     331               0 :       return cmp != 1;
     332                 :     case nsMediaExpression::eEqual:
     333               0 :       return cmp == 0;
     334                 :   }
     335               0 :   NS_NOTREACHED("unexpected mRange");
     336               0 :   return false;
     337                 : }
     338                 : 
     339                 : void
     340               0 : nsMediaQueryResultCacheKey::AddExpression(const nsMediaExpression* aExpression,
     341                 :                                           bool aExpressionMatches)
     342                 : {
     343               0 :   const nsMediaFeature *feature = aExpression->mFeature;
     344               0 :   FeatureEntry *entry = nsnull;
     345               0 :   for (PRUint32 i = 0; i < mFeatureCache.Length(); ++i) {
     346               0 :     if (mFeatureCache[i].mFeature == feature) {
     347               0 :       entry = &mFeatureCache[i];
     348               0 :       break;
     349                 :     }
     350                 :   }
     351               0 :   if (!entry) {
     352               0 :     entry = mFeatureCache.AppendElement();
     353               0 :     if (!entry) {
     354               0 :       return; /* out of memory */
     355                 :     }
     356               0 :     entry->mFeature = feature;
     357                 :   }
     358                 : 
     359               0 :   ExpressionEntry eentry = { *aExpression, aExpressionMatches };
     360               0 :   entry->mExpressions.AppendElement(eentry);
     361                 : }
     362                 : 
     363                 : bool
     364               0 : nsMediaQueryResultCacheKey::Matches(nsPresContext* aPresContext) const
     365                 : {
     366               0 :   if (aPresContext->Medium() != mMedium) {
     367               0 :     return false;
     368                 :   }
     369                 : 
     370               0 :   for (PRUint32 i = 0; i < mFeatureCache.Length(); ++i) {
     371               0 :     const FeatureEntry *entry = &mFeatureCache[i];
     372               0 :     nsCSSValue actual;
     373                 :     nsresult rv =
     374               0 :       (entry->mFeature->mGetter)(aPresContext, entry->mFeature, actual);
     375               0 :     NS_ENSURE_SUCCESS(rv, false); // any better ideas?
     376                 : 
     377               0 :     for (PRUint32 j = 0; j < entry->mExpressions.Length(); ++j) {
     378               0 :       const ExpressionEntry &eentry = entry->mExpressions[j];
     379               0 :       if (eentry.mExpression.Matches(aPresContext, actual) !=
     380                 :           eentry.mExpressionMatches) {
     381               0 :         return false;
     382                 :       }
     383                 :     }
     384                 :   }
     385                 : 
     386               0 :   return true;
     387                 : }
     388                 : 
     389                 : void
     390               0 : nsMediaQuery::AppendToString(nsAString& aString) const
     391                 : {
     392               0 :   if (mHadUnknownExpression) {
     393               0 :     aString.AppendLiteral("not all");
     394               0 :     return;
     395                 :   }
     396                 : 
     397               0 :   NS_ASSERTION(!mNegated || !mHasOnly, "can't have not and only");
     398               0 :   NS_ASSERTION(!mTypeOmitted || (!mNegated && !mHasOnly),
     399                 :                "can't have not or only when type is omitted");
     400               0 :   if (!mTypeOmitted) {
     401               0 :     if (mNegated) {
     402               0 :       aString.AppendLiteral("not ");
     403               0 :     } else if (mHasOnly) {
     404               0 :       aString.AppendLiteral("only ");
     405                 :     }
     406               0 :     aString.Append(nsDependentAtomString(mMediaType));
     407                 :   }
     408                 : 
     409               0 :   for (PRUint32 i = 0, i_end = mExpressions.Length(); i < i_end; ++i) {
     410               0 :     if (i > 0 || !mTypeOmitted)
     411               0 :       aString.AppendLiteral(" and ");
     412               0 :     aString.AppendLiteral("(");
     413                 : 
     414               0 :     const nsMediaExpression &expr = mExpressions[i];
     415               0 :     if (expr.mRange == nsMediaExpression::eMin) {
     416               0 :       aString.AppendLiteral("min-");
     417               0 :     } else if (expr.mRange == nsMediaExpression::eMax) {
     418               0 :       aString.AppendLiteral("max-");
     419                 :     }
     420                 : 
     421               0 :     const nsMediaFeature *feature = expr.mFeature;
     422               0 :     aString.Append(nsDependentAtomString(*feature->mName));
     423                 : 
     424               0 :     if (expr.mValue.GetUnit() != eCSSUnit_Null) {
     425               0 :       aString.AppendLiteral(": ");
     426               0 :       switch (feature->mValueType) {
     427                 :         case nsMediaFeature::eLength:
     428               0 :           NS_ASSERTION(expr.mValue.IsLengthUnit(), "bad unit");
     429                 :           // Use 'width' as a property that takes length values
     430                 :           // written in the normal way.
     431               0 :           expr.mValue.AppendToString(eCSSProperty_width, aString);
     432               0 :           break;
     433                 :         case nsMediaFeature::eInteger:
     434                 :         case nsMediaFeature::eBoolInteger:
     435               0 :           NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Integer,
     436                 :                        "bad unit");
     437                 :           // Use 'z-index' as a property that takes integer values
     438                 :           // written without anything extra.
     439               0 :           expr.mValue.AppendToString(eCSSProperty_z_index, aString);
     440               0 :           break;
     441                 :         case nsMediaFeature::eFloat:
     442                 :           {
     443               0 :             NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Number,
     444                 :                          "bad unit");
     445                 :             // Use 'line-height' as a property that takes float values
     446                 :             // written in the normal way.
     447               0 :             expr.mValue.AppendToString(eCSSProperty_line_height, aString);
     448                 :           }
     449               0 :           break;
     450                 :         case nsMediaFeature::eIntRatio:
     451                 :           {
     452               0 :             NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Array,
     453                 :                          "bad unit");
     454               0 :             nsCSSValue::Array *array = expr.mValue.GetArrayValue();
     455               0 :             NS_ASSERTION(array->Count() == 2, "unexpected length");
     456               0 :             NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
     457                 :                          "bad unit");
     458               0 :             NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Integer,
     459                 :                          "bad unit");
     460               0 :             array->Item(0).AppendToString(eCSSProperty_z_index, aString);
     461               0 :             aString.AppendLiteral("/");
     462               0 :             array->Item(1).AppendToString(eCSSProperty_z_index, aString);
     463                 :           }
     464               0 :           break;
     465                 :         case nsMediaFeature::eResolution:
     466                 :           {
     467               0 :             aString.AppendFloat(expr.mValue.GetFloatValue());
     468               0 :             if (expr.mValue.GetUnit() == eCSSUnit_Inch) {
     469               0 :               aString.AppendLiteral("dpi");
     470                 :             } else {
     471               0 :               NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Centimeter,
     472                 :                            "bad unit");
     473               0 :               aString.AppendLiteral("dpcm");
     474                 :             }
     475                 :           }
     476               0 :           break;
     477                 :         case nsMediaFeature::eEnumerated:
     478               0 :           NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Enumerated,
     479                 :                        "bad unit");
     480                 :           AppendASCIItoUTF16(
     481                 :               nsCSSProps::ValueToKeyword(expr.mValue.GetIntValue(),
     482               0 :                                          feature->mData.mKeywordTable),
     483               0 :               aString);
     484               0 :           break;
     485                 :         case nsMediaFeature::eIdent:
     486               0 :           NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Ident,
     487                 :                        "bad unit");
     488               0 :           aString.Append(expr.mValue.GetStringBufferValue());
     489               0 :           break;
     490                 :       }
     491                 :     }
     492                 : 
     493               0 :     aString.AppendLiteral(")");
     494                 :   }
     495                 : }
     496                 : 
     497                 : nsMediaQuery*
     498               0 : nsMediaQuery::Clone() const
     499                 : {
     500               0 :   nsAutoPtr<nsMediaQuery> result(new nsMediaQuery(*this));
     501               0 :   NS_ENSURE_TRUE(result &&
     502                 :                    result->mExpressions.Length() == mExpressions.Length(),
     503                 :                  nsnull);
     504               0 :   return result.forget();
     505                 : }
     506                 : 
     507                 : bool
     508               0 : nsMediaQuery::Matches(nsPresContext* aPresContext,
     509                 :                       nsMediaQueryResultCacheKey* aKey) const
     510                 : {
     511               0 :   if (mHadUnknownExpression)
     512               0 :     return false;
     513                 : 
     514                 :   bool match =
     515               0 :     mMediaType == aPresContext->Medium() || mMediaType == nsGkAtoms::all;
     516               0 :   for (PRUint32 i = 0, i_end = mExpressions.Length(); match && i < i_end; ++i) {
     517               0 :     const nsMediaExpression &expr = mExpressions[i];
     518               0 :     nsCSSValue actual;
     519                 :     nsresult rv =
     520               0 :       (expr.mFeature->mGetter)(aPresContext, expr.mFeature, actual);
     521               0 :     NS_ENSURE_SUCCESS(rv, false); // any better ideas?
     522                 : 
     523               0 :     match = expr.Matches(aPresContext, actual);
     524               0 :     if (aKey) {
     525               0 :       aKey->AddExpression(&expr, match);
     526                 :     }
     527                 :   }
     528                 : 
     529               0 :   return match == !mNegated;
     530                 : }
     531                 : 
     532                 : DOMCI_DATA(MediaList, nsMediaList)
     533                 : 
     534               0 : NS_INTERFACE_MAP_BEGIN(nsMediaList)
     535               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMMediaList)
     536               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     537               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MediaList)
     538               0 : NS_INTERFACE_MAP_END
     539                 : 
     540               0 : NS_IMPL_ADDREF(nsMediaList)
     541               0 : NS_IMPL_RELEASE(nsMediaList)
     542                 : 
     543                 : 
     544               0 : nsMediaList::nsMediaList()
     545               0 :   : mStyleSheet(nsnull)
     546                 : {
     547               0 : }
     548                 : 
     549               0 : nsMediaList::~nsMediaList()
     550                 : {
     551               0 : }
     552                 : 
     553                 : nsresult
     554               0 : nsMediaList::GetText(nsAString& aMediaText)
     555                 : {
     556               0 :   aMediaText.Truncate();
     557                 : 
     558               0 :   for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     559               0 :     nsMediaQuery* query = mArray[i];
     560               0 :     NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
     561                 : 
     562               0 :     query->AppendToString(aMediaText);
     563                 : 
     564               0 :     if (i + 1 < i_end) {
     565               0 :       aMediaText.AppendLiteral(", ");
     566                 :     }
     567                 :   }
     568                 : 
     569               0 :   return NS_OK;
     570                 : }
     571                 : 
     572                 : // XXXbz this is so ill-defined in the spec, it's not clear quite what
     573                 : // it should be doing....
     574                 : nsresult
     575               0 : nsMediaList::SetText(const nsAString& aMediaText)
     576                 : {
     577               0 :   nsCSSParser parser;
     578                 : 
     579               0 :   bool htmlMode = false;
     580               0 :   if (mStyleSheet) {
     581               0 :     nsCOMPtr<nsIDOMNode> node;
     582               0 :     mStyleSheet->GetOwnerNode(getter_AddRefs(node));
     583               0 :     htmlMode = !!node;
     584                 :   }
     585                 : 
     586                 :   return parser.ParseMediaList(aMediaText, nsnull, 0,
     587               0 :                                this, htmlMode);
     588                 : }
     589                 : 
     590                 : bool
     591               0 : nsMediaList::Matches(nsPresContext* aPresContext,
     592                 :                      nsMediaQueryResultCacheKey* aKey)
     593                 : {
     594               0 :   for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     595               0 :     if (mArray[i]->Matches(aPresContext, aKey)) {
     596               0 :       return true;
     597                 :     }
     598                 :   }
     599               0 :   return mArray.IsEmpty();
     600                 : }
     601                 : 
     602                 : nsresult
     603               0 : nsMediaList::SetStyleSheet(nsCSSStyleSheet *aSheet)
     604                 : {
     605               0 :   NS_ASSERTION(aSheet == mStyleSheet || !aSheet || !mStyleSheet,
     606                 :                "multiple style sheets competing for one media list");
     607               0 :   mStyleSheet = aSheet;
     608               0 :   return NS_OK;
     609                 : }
     610                 : 
     611                 : nsresult
     612               0 : nsMediaList::Clone(nsMediaList** aResult)
     613                 : {
     614               0 :   nsRefPtr<nsMediaList> result = new nsMediaList();
     615               0 :   if (!result || !result->mArray.AppendElements(mArray.Length()))
     616               0 :     return NS_ERROR_OUT_OF_MEMORY;
     617               0 :   for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     618               0 :     if (!(result->mArray[i] = mArray[i]->Clone())) {
     619               0 :       return NS_ERROR_OUT_OF_MEMORY;
     620                 :     }
     621                 :   }
     622               0 :   NS_ADDREF(*aResult = result);
     623               0 :   return NS_OK;
     624                 : }
     625                 : 
     626                 : NS_IMETHODIMP
     627               0 : nsMediaList::GetMediaText(nsAString& aMediaText)
     628                 : {
     629               0 :   return GetText(aMediaText);
     630                 : }
     631                 : 
     632                 : // "sheet" should be an nsCSSStyleSheet and "doc" should be an
     633                 : // nsCOMPtr<nsIDocument>
     634                 : #define BEGIN_MEDIA_CHANGE(sheet, doc)                         \
     635                 :   if (sheet) {                                                 \
     636                 :     doc = sheet->GetOwningDocument();                          \
     637                 :   }                                                            \
     638                 :   mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true);    \
     639                 :   if (sheet) {                                                 \
     640                 :     rv = sheet->WillDirty();                                   \
     641                 :     NS_ENSURE_SUCCESS(rv, rv);                                 \
     642                 :   }
     643                 : 
     644                 : #define END_MEDIA_CHANGE(sheet, doc)                           \
     645                 :   if (sheet) {                                                 \
     646                 :     sheet->DidDirty();                                         \
     647                 :   }                                                            \
     648                 :   /* XXXldb Pass something meaningful? */                      \
     649                 :   if (doc) {                                                   \
     650                 :     doc->StyleRuleChanged(sheet, nsnull, nsnull);              \
     651                 :   }
     652                 : 
     653                 : 
     654                 : NS_IMETHODIMP
     655               0 : nsMediaList::SetMediaText(const nsAString& aMediaText)
     656                 : {
     657               0 :   nsresult rv = NS_OK;
     658               0 :   nsCOMPtr<nsIDocument> doc;
     659                 : 
     660               0 :   BEGIN_MEDIA_CHANGE(mStyleSheet, doc)
     661                 : 
     662               0 :   rv = SetText(aMediaText);
     663               0 :   if (NS_FAILED(rv))
     664               0 :     return rv;
     665                 :   
     666               0 :   END_MEDIA_CHANGE(mStyleSheet, doc)
     667                 : 
     668               0 :   return rv;
     669                 : }
     670                 :                                
     671                 : NS_IMETHODIMP
     672               0 : nsMediaList::GetLength(PRUint32* aLength)
     673                 : {
     674               0 :   NS_ENSURE_ARG_POINTER(aLength);
     675                 : 
     676               0 :   *aLength = mArray.Length();
     677               0 :   return NS_OK;
     678                 : }
     679                 : 
     680                 : NS_IMETHODIMP
     681               0 : nsMediaList::Item(PRUint32 aIndex, nsAString& aReturn)
     682                 : {
     683               0 :   PRInt32 index = aIndex;
     684               0 :   if (0 <= index && index < Count()) {
     685               0 :     nsMediaQuery* query = mArray[index];
     686               0 :     NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
     687                 : 
     688               0 :     aReturn.Truncate();
     689               0 :     query->AppendToString(aReturn);
     690                 :   } else {
     691               0 :     SetDOMStringToNull(aReturn);
     692                 :   }
     693                 : 
     694               0 :   return NS_OK;
     695                 : }
     696                 : 
     697                 : NS_IMETHODIMP
     698               0 : nsMediaList::DeleteMedium(const nsAString& aOldMedium)
     699                 : {
     700               0 :   nsresult rv = NS_OK;
     701               0 :   nsCOMPtr<nsIDocument> doc;
     702                 : 
     703               0 :   BEGIN_MEDIA_CHANGE(mStyleSheet, doc)
     704                 :   
     705               0 :   rv = Delete(aOldMedium);
     706               0 :   if (NS_FAILED(rv))
     707               0 :     return rv;
     708                 : 
     709               0 :   END_MEDIA_CHANGE(mStyleSheet, doc)
     710                 :   
     711               0 :   return rv;
     712                 : }
     713                 : 
     714                 : NS_IMETHODIMP
     715               0 : nsMediaList::AppendMedium(const nsAString& aNewMedium)
     716                 : {
     717               0 :   nsresult rv = NS_OK;
     718               0 :   nsCOMPtr<nsIDocument> doc;
     719                 : 
     720               0 :   BEGIN_MEDIA_CHANGE(mStyleSheet, doc)
     721                 :   
     722               0 :   rv = Append(aNewMedium);
     723               0 :   if (NS_FAILED(rv))
     724               0 :     return rv;
     725                 : 
     726               0 :   END_MEDIA_CHANGE(mStyleSheet, doc)
     727                 :   
     728               0 :   return rv;
     729                 : }
     730                 : 
     731                 : nsresult
     732               0 : nsMediaList::Delete(const nsAString& aOldMedium)
     733                 : {
     734               0 :   if (aOldMedium.IsEmpty())
     735               0 :     return NS_ERROR_DOM_NOT_FOUND_ERR;
     736                 : 
     737               0 :   for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     738               0 :     nsMediaQuery* query = mArray[i];
     739               0 :     NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
     740                 : 
     741               0 :     nsAutoString buf;
     742               0 :     query->AppendToString(buf);
     743               0 :     if (buf == aOldMedium) {
     744               0 :       mArray.RemoveElementAt(i);
     745               0 :       return NS_OK;
     746                 :     }
     747                 :   }
     748                 : 
     749               0 :   return NS_ERROR_DOM_NOT_FOUND_ERR;
     750                 : }
     751                 : 
     752                 : nsresult
     753               0 : nsMediaList::Append(const nsAString& aNewMedium)
     754                 : {
     755               0 :   if (aNewMedium.IsEmpty())
     756               0 :     return NS_ERROR_DOM_NOT_FOUND_ERR;
     757                 : 
     758               0 :   Delete(aNewMedium);
     759                 : 
     760               0 :   nsresult rv = NS_OK;
     761               0 :   nsTArray<nsAutoPtr<nsMediaQuery> > buf;
     762                 : #ifdef DEBUG
     763                 :   bool ok = 
     764                 : #endif
     765               0 :     mArray.SwapElements(buf);
     766               0 :   NS_ASSERTION(ok, "SwapElements should never fail when neither array "
     767                 :                    "is an auto array");
     768               0 :   SetText(aNewMedium);
     769               0 :   if (mArray.Length() == 1) {
     770               0 :     nsMediaQuery *query = mArray[0].forget();
     771               0 :     if (!buf.AppendElement(query)) {
     772               0 :       delete query;
     773               0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     774                 :     }
     775                 :   }
     776                 : #ifdef DEBUG
     777                 :   ok = 
     778                 : #endif
     779               0 :     mArray.SwapElements(buf);
     780               0 :   NS_ASSERTION(ok, "SwapElements should never fail when neither array "
     781                 :                    "is an auto array");
     782               0 :   return rv;
     783                 : }
     784                 : 
     785                 : // -------------------------------
     786                 : // CSS Style Sheet Inner Data Container
     787                 : //
     788                 : 
     789                 : 
     790               0 : nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet)
     791                 :   : mSheets(),
     792                 :     mComplete(false)
     793                 : #ifdef DEBUG
     794               0 :     , mPrincipalSet(false)
     795                 : #endif
     796                 : {
     797               0 :   MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
     798               0 :   mSheets.AppendElement(aPrimarySheet);
     799                 : 
     800               0 :   mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1");
     801               0 : }
     802                 : 
     803               0 : static bool SetStyleSheetReference(css::Rule* aRule, void* aSheet)
     804                 : {
     805               0 :   if (aRule) {
     806               0 :     aRule->SetStyleSheet(static_cast<nsCSSStyleSheet*>(aSheet));
     807                 :   }
     808               0 :   return true;
     809                 : }
     810                 : 
     811                 : static bool
     812               0 : CloneRuleInto(css::Rule* aRule, void* aArray)
     813                 : {
     814               0 :   nsRefPtr<css::Rule> clone = aRule->Clone();
     815               0 :   static_cast<nsCOMArray<css::Rule>*>(aArray)->AppendObject(clone);
     816               0 :   return true;
     817                 : }
     818                 : 
     819                 : struct ChildSheetListBuilder {
     820                 :   nsRefPtr<nsCSSStyleSheet>* sheetSlot;
     821                 :   nsCSSStyleSheet* parent;
     822                 : 
     823               0 :   void SetParentLinks(nsCSSStyleSheet* aSheet) {
     824               0 :     aSheet->mParent = parent;
     825               0 :     aSheet->SetOwningDocument(parent->mDocument);
     826               0 :   }
     827                 : 
     828               0 :   static void ReparentChildList(nsCSSStyleSheet* aPrimarySheet,
     829                 :                                 nsCSSStyleSheet* aFirstChild)
     830                 :   {
     831               0 :     for (nsCSSStyleSheet *child = aFirstChild; child; child = child->mNext) {
     832               0 :       child->mParent = aPrimarySheet;
     833               0 :       child->SetOwningDocument(aPrimarySheet->mDocument);
     834                 :     }
     835               0 :   }
     836                 : };
     837                 :   
     838                 : bool
     839               0 : nsCSSStyleSheet::RebuildChildList(css::Rule* aRule, void* aBuilder)
     840                 : {
     841               0 :   PRInt32 type = aRule->GetType();
     842               0 :   if (type < css::Rule::IMPORT_RULE) {
     843                 :     // Keep going till we get to the import rules.
     844               0 :     return true;
     845                 :   }
     846                 : 
     847               0 :   if (type != css::Rule::IMPORT_RULE) {
     848                 :     // We're past all the import rules; stop the enumeration.
     849               0 :     return false;
     850                 :   }
     851                 : 
     852                 :   ChildSheetListBuilder* builder =
     853               0 :     static_cast<ChildSheetListBuilder*>(aBuilder);
     854                 : 
     855                 :   // XXXbz We really need to decomtaminate all this stuff.  Is there a reason
     856                 :   // that I can't just QI to ImportRule and get an nsCSSStyleSheet
     857                 :   // directly from it?
     858               0 :   nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(aRule));
     859               0 :   NS_ASSERTION(importRule, "GetType lied");
     860                 : 
     861               0 :   nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
     862               0 :   importRule->GetStyleSheet(getter_AddRefs(childSheet));
     863                 : 
     864                 :   // Have to do this QI to be safe, since XPConnect can fake
     865                 :   // nsIDOMCSSStyleSheets
     866               0 :   nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(childSheet);
     867               0 :   if (!cssSheet) {
     868               0 :     return true;
     869                 :   }
     870                 : 
     871               0 :   (*builder->sheetSlot) = cssSheet;
     872               0 :   builder->SetParentLinks(*builder->sheetSlot);
     873               0 :   builder->sheetSlot = &(*builder->sheetSlot)->mNext;
     874               0 :   return true;
     875                 : }
     876                 : 
     877                 : size_t
     878               0 : nsCSSStyleSheet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
     879                 : {
     880               0 :   size_t n = 0;
     881               0 :   const nsCSSStyleSheet* s = this;
     882               0 :   while (s) {
     883               0 :     n += aMallocSizeOf(s);
     884               0 :     n += s->mInner->SizeOfIncludingThis(aMallocSizeOf);
     885                 : 
     886                 :     // Measurement of the following members may be added later if DMD finds it is
     887                 :     // worthwhile:
     888                 :     // - s->mTitle
     889                 :     // - s->mMedia
     890                 :     // - s->mRuleCollection
     891                 :     // - s->mRuleProcessors
     892                 :     //
     893                 :     // The following members are not measured:
     894                 :     // - s->mOwnerRule, because it's non-owning
     895                 : 
     896               0 :     s = s->mNext;
     897                 :   }
     898               0 :   return n;
     899                 : }
     900                 : 
     901               0 : nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
     902                 :                                            nsCSSStyleSheet* aPrimarySheet)
     903                 :   : mSheets(),
     904                 :     mSheetURI(aCopy.mSheetURI),
     905                 :     mOriginalSheetURI(aCopy.mOriginalSheetURI),
     906                 :     mBaseURI(aCopy.mBaseURI),
     907                 :     mPrincipal(aCopy.mPrincipal),
     908                 :     mComplete(aCopy.mComplete)
     909                 : #ifdef DEBUG
     910               0 :     , mPrincipalSet(aCopy.mPrincipalSet)
     911                 : #endif
     912                 : {
     913               0 :   MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
     914               0 :   AddSheet(aPrimarySheet);
     915               0 :   aCopy.mOrderedRules.EnumerateForwards(CloneRuleInto, &mOrderedRules);
     916               0 :   mOrderedRules.EnumerateForwards(SetStyleSheetReference, aPrimarySheet);
     917                 : 
     918               0 :   ChildSheetListBuilder builder = { &mFirstChild, aPrimarySheet };
     919               0 :   mOrderedRules.EnumerateForwards(nsCSSStyleSheet::RebuildChildList, &builder);
     920                 : 
     921               0 :   RebuildNameSpaces();
     922               0 : }
     923                 : 
     924               0 : nsCSSStyleSheetInner::~nsCSSStyleSheetInner()
     925                 : {
     926               0 :   MOZ_COUNT_DTOR(nsCSSStyleSheetInner);
     927               0 :   mOrderedRules.EnumerateForwards(SetStyleSheetReference, nsnull);
     928               0 : }
     929                 : 
     930                 : nsCSSStyleSheetInner* 
     931               0 : nsCSSStyleSheetInner::CloneFor(nsCSSStyleSheet* aPrimarySheet)
     932                 : {
     933               0 :   return new nsCSSStyleSheetInner(*this, aPrimarySheet);
     934                 : }
     935                 : 
     936                 : void
     937               0 : nsCSSStyleSheetInner::AddSheet(nsCSSStyleSheet* aSheet)
     938                 : {
     939               0 :   mSheets.AppendElement(aSheet);
     940               0 : }
     941                 : 
     942                 : void
     943               0 : nsCSSStyleSheetInner::RemoveSheet(nsCSSStyleSheet* aSheet)
     944                 : {
     945               0 :   if (1 == mSheets.Length()) {
     946               0 :     NS_ASSERTION(aSheet == mSheets.ElementAt(0), "bad parent");
     947               0 :     delete this;
     948               0 :     return;
     949                 :   }
     950               0 :   if (aSheet == mSheets.ElementAt(0)) {
     951               0 :     mSheets.RemoveElementAt(0);
     952               0 :     NS_ASSERTION(mSheets.Length(), "no parents");
     953                 :     mOrderedRules.EnumerateForwards(SetStyleSheetReference,
     954               0 :                                     mSheets.ElementAt(0));
     955                 : 
     956               0 :     ChildSheetListBuilder::ReparentChildList(mSheets[0], mFirstChild);
     957                 :   }
     958                 :   else {
     959               0 :     mSheets.RemoveElement(aSheet);
     960                 :   }
     961                 : }
     962                 : 
     963                 : static void
     964               0 : AddNamespaceRuleToMap(css::Rule* aRule, nsXMLNameSpaceMap* aMap)
     965                 : {
     966               0 :   NS_ASSERTION(aRule->GetType() == css::Rule::NAMESPACE_RULE, "Bogus rule type");
     967                 : 
     968               0 :   nsRefPtr<css::NameSpaceRule> nameSpaceRule = do_QueryObject(aRule);
     969                 : 
     970               0 :   nsAutoString  urlSpec;
     971               0 :   nameSpaceRule->GetURLSpec(urlSpec);
     972                 : 
     973               0 :   aMap->AddPrefix(nameSpaceRule->GetPrefix(), urlSpec);
     974               0 : }
     975                 : 
     976                 : static bool
     977               0 : CreateNameSpace(css::Rule* aRule, void* aNameSpacePtr)
     978                 : {
     979               0 :   PRInt32 type = aRule->GetType();
     980               0 :   if (css::Rule::NAMESPACE_RULE == type) {
     981                 :     AddNamespaceRuleToMap(aRule,
     982               0 :                           static_cast<nsXMLNameSpaceMap*>(aNameSpacePtr));
     983               0 :     return true;
     984                 :   }
     985                 :   // stop if not namespace, import or charset because namespace can't follow
     986                 :   // anything else
     987               0 :   return (css::Rule::CHARSET_RULE == type || css::Rule::IMPORT_RULE == type);
     988                 : }
     989                 : 
     990                 : void 
     991               0 : nsCSSStyleSheetInner::RebuildNameSpaces()
     992                 : {
     993                 :   // Just nuke our existing namespace map, if any
     994               0 :   if (NS_SUCCEEDED(CreateNamespaceMap())) {
     995               0 :     mOrderedRules.EnumerateForwards(CreateNameSpace, mNameSpaceMap);
     996                 :   }
     997               0 : }
     998                 : 
     999                 : nsresult
    1000               0 : nsCSSStyleSheetInner::CreateNamespaceMap()
    1001                 : {
    1002               0 :   mNameSpaceMap = nsXMLNameSpaceMap::Create(false);
    1003               0 :   NS_ENSURE_TRUE(mNameSpaceMap, NS_ERROR_OUT_OF_MEMORY);
    1004                 :   // Override the default namespace map behavior for the null prefix to
    1005                 :   // return the wildcard namespace instead of the null namespace.
    1006               0 :   mNameSpaceMap->AddPrefix(nsnull, kNameSpaceID_Unknown);
    1007               0 :   return NS_OK;
    1008                 : }
    1009                 : 
    1010                 : size_t
    1011               0 : nsCSSStyleSheetInner::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
    1012                 : {
    1013               0 :   size_t n = aMallocSizeOf(this);
    1014                 :   n += mOrderedRules.SizeOfExcludingThis(css::Rule::SizeOfCOMArrayElementIncludingThis,
    1015               0 :                                          aMallocSizeOf);
    1016               0 :   n += mFirstChild ? mFirstChild->SizeOfIncludingThis(aMallocSizeOf) : 0;
    1017                 : 
    1018                 :   // Measurement of the following members may be added later if DMD finds it is
    1019                 :   // worthwhile:
    1020                 :   // - mSheetURI
    1021                 :   // - mOriginalSheetURI
    1022                 :   // - mBaseURI
    1023                 :   // - mPrincipal
    1024                 :   // - mNameSpaceMap
    1025                 :   //
    1026                 :   // The following members are not measured:
    1027                 :   // - mSheets, because it's non-owning
    1028                 : 
    1029               0 :   return n;
    1030                 : }
    1031                 : 
    1032                 : // -------------------------------
    1033                 : // CSS Style Sheet
    1034                 : //
    1035                 : 
    1036               0 : nsCSSStyleSheet::nsCSSStyleSheet()
    1037                 :   : mTitle(), 
    1038                 :     mParent(nsnull),
    1039                 :     mOwnerRule(nsnull),
    1040                 :     mRuleCollection(nsnull),
    1041                 :     mDocument(nsnull),
    1042                 :     mOwningNode(nsnull),
    1043                 :     mDisabled(false),
    1044                 :     mDirty(false),
    1045               0 :     mRuleProcessors(nsnull)
    1046                 : {
    1047                 : 
    1048               0 :   mInner = new nsCSSStyleSheetInner(this);
    1049               0 : }
    1050                 : 
    1051               0 : nsCSSStyleSheet::nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
    1052                 :                                  nsCSSStyleSheet* aParentToUse,
    1053                 :                                  css::ImportRule* aOwnerRuleToUse,
    1054                 :                                  nsIDocument* aDocumentToUse,
    1055                 :                                  nsIDOMNode* aOwningNodeToUse)
    1056                 :   : mTitle(aCopy.mTitle),
    1057                 :     mParent(aParentToUse),
    1058                 :     mOwnerRule(aOwnerRuleToUse),
    1059                 :     mRuleCollection(nsnull), // re-created lazily
    1060                 :     mDocument(aDocumentToUse),
    1061                 :     mOwningNode(aOwningNodeToUse),
    1062                 :     mDisabled(aCopy.mDisabled),
    1063                 :     mDirty(aCopy.mDirty),
    1064                 :     mInner(aCopy.mInner),
    1065               0 :     mRuleProcessors(nsnull)
    1066                 : {
    1067                 : 
    1068               0 :   mInner->AddSheet(this);
    1069                 : 
    1070               0 :   if (mDirty) { // CSSOM's been there, force full copy now
    1071               0 :     NS_ASSERTION(mInner->mComplete, "Why have rules been accessed on an incomplete sheet?");
    1072                 :     // FIXME: handle failure?
    1073               0 :     EnsureUniqueInner();
    1074                 :   }
    1075                 : 
    1076               0 :   if (aCopy.mMedia) {
    1077                 :     // XXX This is wrong; we should be keeping @import rules and
    1078                 :     // sheets in sync!
    1079               0 :     aCopy.mMedia->Clone(getter_AddRefs(mMedia));
    1080                 :   }
    1081               0 : }
    1082                 : 
    1083               0 : nsCSSStyleSheet::~nsCSSStyleSheet()
    1084                 : {
    1085               0 :   for (nsCSSStyleSheet* child = mInner->mFirstChild;
    1086                 :        child;
    1087               0 :        child = child->mNext) {
    1088                 :     // XXXbz this is a little bogus; see the XXX comment where we
    1089                 :     // declare mFirstChild.
    1090               0 :     if (child->mParent == this) {
    1091               0 :       child->mParent = nsnull;
    1092               0 :       child->mDocument = nsnull;
    1093                 :     }
    1094                 :   }
    1095               0 :   if (nsnull != mRuleCollection) {
    1096               0 :     mRuleCollection->DropReference();
    1097               0 :     NS_RELEASE(mRuleCollection);
    1098                 :   }
    1099               0 :   if (mMedia) {
    1100               0 :     mMedia->SetStyleSheet(nsnull);
    1101               0 :     mMedia = nsnull;
    1102                 :   }
    1103               0 :   mInner->RemoveSheet(this);
    1104                 :   // XXX The document reference is not reference counted and should
    1105                 :   // not be released. The document will let us know when it is going
    1106                 :   // away.
    1107               0 :   if (mRuleProcessors) {
    1108               0 :     NS_ASSERTION(mRuleProcessors->Length() == 0, "destructing sheet with rule processor reference");
    1109               0 :     delete mRuleProcessors; // weak refs, should be empty here anyway
    1110                 :   }
    1111               0 : }
    1112                 : 
    1113                 : 
    1114                 : DOMCI_DATA(CSSStyleSheet, nsCSSStyleSheet)
    1115                 : 
    1116                 : // QueryInterface implementation for nsCSSStyleSheet
    1117               0 : NS_INTERFACE_MAP_BEGIN(nsCSSStyleSheet)
    1118               0 :   NS_INTERFACE_MAP_ENTRY(nsIStyleSheet)
    1119               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStyleSheet)
    1120               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleSheet)
    1121               0 :   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
    1122               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleSheet)
    1123               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleSheet)
    1124               0 :   if (aIID.Equals(NS_GET_IID(nsCSSStyleSheet)))
    1125               0 :     foundInterface = reinterpret_cast<nsISupports*>(this);
    1126                 :   else
    1127               0 : NS_INTERFACE_MAP_END
    1128                 : 
    1129                 : 
    1130               0 : NS_IMPL_ADDREF(nsCSSStyleSheet)
    1131               0 : NS_IMPL_RELEASE(nsCSSStyleSheet)
    1132                 : 
    1133                 : 
    1134                 : nsresult
    1135               0 : nsCSSStyleSheet::AddRuleProcessor(nsCSSRuleProcessor* aProcessor)
    1136                 : {
    1137               0 :   if (! mRuleProcessors) {
    1138               0 :     mRuleProcessors = new nsAutoTArray<nsCSSRuleProcessor*, 8>();
    1139               0 :     if (!mRuleProcessors)
    1140               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1141                 :   }
    1142               0 :   NS_ASSERTION(mRuleProcessors->NoIndex == mRuleProcessors->IndexOf(aProcessor),
    1143                 :                "processor already registered");
    1144               0 :   mRuleProcessors->AppendElement(aProcessor); // weak ref
    1145               0 :   return NS_OK;
    1146                 : }
    1147                 : 
    1148                 : nsresult
    1149               0 : nsCSSStyleSheet::DropRuleProcessor(nsCSSRuleProcessor* aProcessor)
    1150                 : {
    1151               0 :   if (!mRuleProcessors)
    1152               0 :     return NS_ERROR_FAILURE;
    1153               0 :   return mRuleProcessors->RemoveElement(aProcessor)
    1154                 :            ? NS_OK
    1155               0 :            : NS_ERROR_FAILURE;
    1156                 : }
    1157                 : 
    1158                 : 
    1159                 : void
    1160               0 : nsCSSStyleSheet::SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
    1161                 :                          nsIURI* aBaseURI)
    1162                 : {
    1163               0 :   NS_PRECONDITION(aSheetURI && aBaseURI, "null ptr");
    1164                 : 
    1165               0 :   NS_ASSERTION(mInner->mOrderedRules.Count() == 0 && !mInner->mComplete,
    1166                 :                "Can't call SetURL on sheets that are complete or have rules");
    1167                 : 
    1168               0 :   mInner->mSheetURI = aSheetURI;
    1169               0 :   mInner->mOriginalSheetURI = aOriginalSheetURI;
    1170               0 :   mInner->mBaseURI = aBaseURI;
    1171               0 : }
    1172                 : 
    1173                 : void
    1174               0 : nsCSSStyleSheet::SetPrincipal(nsIPrincipal* aPrincipal)
    1175                 : {
    1176               0 :   NS_PRECONDITION(!mInner->mPrincipalSet,
    1177                 :                   "Should have an inner whose principal has not yet been set");
    1178               0 :   if (aPrincipal) {
    1179               0 :     mInner->mPrincipal = aPrincipal;
    1180                 : #ifdef DEBUG
    1181               0 :     mInner->mPrincipalSet = true;
    1182                 : #endif
    1183                 :   }
    1184               0 : }
    1185                 : 
    1186                 : /* virtual */ nsIURI*
    1187               0 : nsCSSStyleSheet::GetSheetURI() const
    1188                 : {
    1189               0 :   return mInner->mSheetURI;
    1190                 : }
    1191                 : 
    1192                 : /* virtual */ nsIURI*
    1193               0 : nsCSSStyleSheet::GetBaseURI() const
    1194                 : {
    1195               0 :   return mInner->mBaseURI;
    1196                 : }
    1197                 : 
    1198                 : /* virtual */ void
    1199               0 : nsCSSStyleSheet::GetType(nsString& aType) const
    1200                 : {
    1201               0 :   aType.AssignLiteral("text/css");
    1202               0 : }
    1203                 : 
    1204                 : bool
    1205               0 : nsCSSStyleSheet::UseForPresentation(nsPresContext* aPresContext,
    1206                 :                                     nsMediaQueryResultCacheKey& aKey) const
    1207                 : {
    1208               0 :   if (mMedia) {
    1209               0 :     return mMedia->Matches(aPresContext, &aKey);
    1210                 :   }
    1211               0 :   return true;
    1212                 : }
    1213                 : 
    1214                 : 
    1215                 : void
    1216               0 : nsCSSStyleSheet::SetMedia(nsMediaList* aMedia)
    1217                 : {
    1218               0 :   mMedia = aMedia;
    1219               0 : }
    1220                 : 
    1221                 : /* virtual */ bool
    1222               0 : nsCSSStyleSheet::HasRules() const
    1223                 : {
    1224               0 :   return StyleRuleCount() != 0;
    1225                 : }
    1226                 : 
    1227                 : /* virtual */ bool
    1228               0 : nsCSSStyleSheet::IsApplicable() const
    1229                 : {
    1230               0 :   return !mDisabled && mInner->mComplete;
    1231                 : }
    1232                 : 
    1233                 : /* virtual */ void
    1234               0 : nsCSSStyleSheet::SetEnabled(bool aEnabled)
    1235                 : {
    1236                 :   // Internal method, so callers must handle BeginUpdate/EndUpdate
    1237               0 :   bool oldDisabled = mDisabled;
    1238               0 :   mDisabled = !aEnabled;
    1239                 : 
    1240               0 :   if (mInner->mComplete && oldDisabled != mDisabled) {
    1241               0 :     ClearRuleCascades();
    1242                 : 
    1243               0 :     if (mDocument) {
    1244               0 :       mDocument->SetStyleSheetApplicableState(this, !mDisabled);
    1245                 :     }
    1246                 :   }
    1247               0 : }
    1248                 : 
    1249                 : /* virtual */ bool
    1250               0 : nsCSSStyleSheet::IsComplete() const
    1251                 : {
    1252               0 :   return mInner->mComplete;
    1253                 : }
    1254                 : 
    1255                 : /* virtual */ void
    1256               0 : nsCSSStyleSheet::SetComplete()
    1257                 : {
    1258               0 :   NS_ASSERTION(!mDirty, "Can't set a dirty sheet complete!");
    1259               0 :   mInner->mComplete = true;
    1260               0 :   if (mDocument && !mDisabled) {
    1261                 :     // Let the document know
    1262               0 :     mDocument->BeginUpdate(UPDATE_STYLE);
    1263               0 :     mDocument->SetStyleSheetApplicableState(this, true);
    1264               0 :     mDocument->EndUpdate(UPDATE_STYLE);
    1265                 :   }
    1266               0 : }
    1267                 : 
    1268                 : /* virtual */ nsIStyleSheet*
    1269               0 : nsCSSStyleSheet::GetParentSheet() const
    1270                 : {
    1271               0 :   return mParent;
    1272                 : }
    1273                 : 
    1274                 : /* virtual */ nsIDocument*
    1275               0 : nsCSSStyleSheet::GetOwningDocument() const
    1276                 : {
    1277               0 :   return mDocument;
    1278                 : }
    1279                 : 
    1280                 : /* virtual */ void
    1281               0 : nsCSSStyleSheet::SetOwningDocument(nsIDocument* aDocument)
    1282                 : { // not ref counted
    1283               0 :   mDocument = aDocument;
    1284                 :   // Now set the same document on all our child sheets....
    1285                 :   // XXXbz this is a little bogus; see the XXX comment where we
    1286                 :   // declare mFirstChild.
    1287               0 :   for (nsCSSStyleSheet* child = mInner->mFirstChild;
    1288               0 :        child; child = child->mNext) {
    1289               0 :     if (child->mParent == this) {
    1290               0 :       child->SetOwningDocument(aDocument);
    1291                 :     }
    1292                 :   }
    1293               0 : }
    1294                 : 
    1295                 : PRUint64
    1296               0 : nsCSSStyleSheet::FindOwningWindowInnerID() const
    1297                 : {
    1298               0 :   PRUint64 windowID = 0;
    1299               0 :   if (mDocument) {
    1300               0 :     windowID = mDocument->InnerWindowID();
    1301                 :   }
    1302                 : 
    1303               0 :   if (windowID == 0 && mOwningNode) {
    1304               0 :     nsCOMPtr<nsIContent> node = do_QueryInterface(mOwningNode);
    1305               0 :     if (node) {
    1306               0 :       windowID = node->OwnerDoc()->InnerWindowID();
    1307                 :     }
    1308                 :   }
    1309                 : 
    1310               0 :   if (windowID == 0 && mOwnerRule) {
    1311               0 :     nsCOMPtr<nsIStyleSheet> sheet = static_cast<css::Rule*>(mOwnerRule)->GetStyleSheet();
    1312               0 :     if (sheet) {
    1313               0 :       nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(sheet);
    1314               0 :       if (cssSheet) {
    1315               0 :         windowID = cssSheet->FindOwningWindowInnerID();
    1316                 :       }
    1317                 :     }
    1318                 :   }
    1319                 : 
    1320               0 :   if (windowID == 0 && mParent) {
    1321               0 :     windowID = mParent->FindOwningWindowInnerID();
    1322                 :   }
    1323                 : 
    1324               0 :   return windowID;
    1325                 : }
    1326                 : 
    1327                 : void
    1328               0 : nsCSSStyleSheet::AppendStyleSheet(nsCSSStyleSheet* aSheet)
    1329                 : {
    1330               0 :   NS_PRECONDITION(nsnull != aSheet, "null arg");
    1331                 : 
    1332               0 :   if (NS_SUCCEEDED(WillDirty())) {
    1333               0 :     nsRefPtr<nsCSSStyleSheet>* tail = &mInner->mFirstChild;
    1334               0 :     while (*tail) {
    1335               0 :       tail = &(*tail)->mNext;
    1336                 :     }
    1337               0 :     *tail = aSheet;
    1338                 :   
    1339                 :     // This is not reference counted. Our parent tells us when
    1340                 :     // it's going away.
    1341               0 :     aSheet->mParent = this;
    1342               0 :     aSheet->mDocument = mDocument;
    1343               0 :     DidDirty();
    1344                 :   }
    1345               0 : }
    1346                 : 
    1347                 : void
    1348               0 : nsCSSStyleSheet::InsertStyleSheetAt(nsCSSStyleSheet* aSheet, PRInt32 aIndex)
    1349                 : {
    1350               0 :   NS_PRECONDITION(nsnull != aSheet, "null arg");
    1351                 : 
    1352               0 :   if (NS_SUCCEEDED(WillDirty())) {
    1353               0 :     nsRefPtr<nsCSSStyleSheet>* tail = &mInner->mFirstChild;
    1354               0 :     while (*tail && aIndex) {
    1355               0 :       --aIndex;
    1356               0 :       tail = &(*tail)->mNext;
    1357                 :     }
    1358               0 :     aSheet->mNext = *tail;
    1359               0 :     *tail = aSheet;
    1360                 : 
    1361                 :     // This is not reference counted. Our parent tells us when
    1362                 :     // it's going away.
    1363               0 :     aSheet->mParent = this;
    1364               0 :     aSheet->mDocument = mDocument;
    1365               0 :     DidDirty();
    1366                 :   }
    1367               0 : }
    1368                 : 
    1369                 : void
    1370               0 : nsCSSStyleSheet::PrependStyleRule(css::Rule* aRule)
    1371                 : {
    1372               0 :   NS_PRECONDITION(nsnull != aRule, "null arg");
    1373                 : 
    1374               0 :   if (NS_SUCCEEDED(WillDirty())) {
    1375               0 :     mInner->mOrderedRules.InsertObjectAt(aRule, 0);
    1376               0 :     aRule->SetStyleSheet(this);
    1377               0 :     DidDirty();
    1378                 : 
    1379               0 :     if (css::Rule::NAMESPACE_RULE == aRule->GetType()) {
    1380                 :       // no api to prepend a namespace (ugh), release old ones and re-create them all
    1381               0 :       mInner->RebuildNameSpaces();
    1382                 :     }
    1383                 :   }
    1384               0 : }
    1385                 : 
    1386                 : void
    1387               0 : nsCSSStyleSheet::AppendStyleRule(css::Rule* aRule)
    1388                 : {
    1389               0 :   NS_PRECONDITION(nsnull != aRule, "null arg");
    1390                 : 
    1391               0 :   if (NS_SUCCEEDED(WillDirty())) {
    1392               0 :     mInner->mOrderedRules.AppendObject(aRule);
    1393               0 :     aRule->SetStyleSheet(this);
    1394               0 :     DidDirty();
    1395                 : 
    1396               0 :     if (css::Rule::NAMESPACE_RULE == aRule->GetType()) {
    1397                 : #ifdef DEBUG
    1398                 :       nsresult rv =
    1399                 : #endif
    1400               0 :         RegisterNamespaceRule(aRule);
    1401               0 :       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
    1402                 :                        "RegisterNamespaceRule returned error");
    1403                 :     }
    1404                 :   }
    1405               0 : }
    1406                 : 
    1407                 : void
    1408               0 : nsCSSStyleSheet::ReplaceStyleRule(css::Rule* aOld, css::Rule* aNew)
    1409                 : {
    1410               0 :   NS_PRECONDITION(mInner->mOrderedRules.Count() != 0, "can't have old rule");
    1411               0 :   NS_PRECONDITION(mInner->mComplete, "No replacing in an incomplete sheet!");
    1412                 : 
    1413               0 :   if (NS_SUCCEEDED(WillDirty())) {
    1414               0 :     PRInt32 index = mInner->mOrderedRules.IndexOf(aOld);
    1415               0 :     if (NS_UNLIKELY(index == -1)) {
    1416               0 :       NS_NOTREACHED("Couldn't find old rule");
    1417               0 :       return;
    1418                 :     }
    1419               0 :     mInner->mOrderedRules.ReplaceObjectAt(aNew, index);
    1420                 : 
    1421               0 :     aNew->SetStyleSheet(this);
    1422               0 :     aOld->SetStyleSheet(nsnull);
    1423               0 :     DidDirty();
    1424               0 :     NS_ASSERTION(css::Rule::NAMESPACE_RULE != aNew->GetType(), "not yet implemented");
    1425               0 :     NS_ASSERTION(css::Rule::NAMESPACE_RULE != aOld->GetType(), "not yet implemented");
    1426                 :   }
    1427                 : }
    1428                 : 
    1429                 : PRInt32
    1430               0 : nsCSSStyleSheet::StyleRuleCount() const
    1431                 : {
    1432               0 :   return mInner->mOrderedRules.Count();
    1433                 : }
    1434                 : 
    1435                 : nsresult
    1436               0 : nsCSSStyleSheet::GetStyleRuleAt(PRInt32 aIndex, css::Rule*& aRule) const
    1437                 : {
    1438                 :   // Important: If this function is ever made scriptable, we must add
    1439                 :   // a security check here. See GetCssRules below for an example.
    1440               0 :   aRule = mInner->mOrderedRules.SafeObjectAt(aIndex);
    1441               0 :   if (aRule) {
    1442               0 :     NS_ADDREF(aRule);
    1443               0 :     return NS_OK;
    1444                 :   }
    1445                 : 
    1446               0 :   return NS_ERROR_ILLEGAL_VALUE;
    1447                 : }
    1448                 : 
    1449                 : PRInt32
    1450               0 : nsCSSStyleSheet::StyleSheetCount() const
    1451                 : {
    1452                 :   // XXX Far from an ideal way to do this, but the hope is that
    1453                 :   // it won't be done too often. If it is, we might want to 
    1454                 :   // consider storing the children in an array.
    1455               0 :   PRInt32 count = 0;
    1456                 : 
    1457               0 :   const nsCSSStyleSheet* child = mInner->mFirstChild;
    1458               0 :   while (child) {
    1459               0 :     count++;
    1460               0 :     child = child->mNext;
    1461                 :   }
    1462                 : 
    1463               0 :   return count;
    1464                 : }
    1465                 : 
    1466                 : nsCSSStyleSheet::EnsureUniqueInnerResult
    1467               0 : nsCSSStyleSheet::EnsureUniqueInner()
    1468                 : {
    1469               0 :   mDirty = true;
    1470                 : 
    1471               0 :   NS_ABORT_IF_FALSE(mInner->mSheets.Length() != 0,
    1472                 :                     "unexpected number of outers");
    1473               0 :   if (mInner->mSheets.Length() == 1) {
    1474               0 :     return eUniqueInner_AlreadyUnique;
    1475                 :   }
    1476               0 :   nsCSSStyleSheetInner* clone = mInner->CloneFor(this);
    1477               0 :   if (!clone) {
    1478               0 :     return eUniqueInner_CloneFailed;
    1479                 :   }
    1480               0 :   mInner->RemoveSheet(this);
    1481               0 :   mInner = clone;
    1482                 : 
    1483                 :   // otherwise the rule processor has pointers to the old rules
    1484               0 :   ClearRuleCascades();
    1485                 : 
    1486               0 :   return eUniqueInner_ClonedInner;
    1487                 : }
    1488                 : 
    1489                 : bool
    1490               0 : nsCSSStyleSheet::AppendAllChildSheets(nsTArray<nsCSSStyleSheet*>& aArray)
    1491                 : {
    1492               0 :   for (nsCSSStyleSheet* child = mInner->mFirstChild; child;
    1493               0 :        child = child->mNext) {
    1494               0 :     if (!aArray.AppendElement(child)) {
    1495               0 :       return false;
    1496                 :     }
    1497                 :   }
    1498               0 :   return true;
    1499                 : }
    1500                 : 
    1501                 : already_AddRefed<nsCSSStyleSheet>
    1502               0 : nsCSSStyleSheet::Clone(nsCSSStyleSheet* aCloneParent,
    1503                 :                        css::ImportRule* aCloneOwnerRule,
    1504                 :                        nsIDocument* aCloneDocument,
    1505                 :                        nsIDOMNode* aCloneOwningNode) const
    1506                 : {
    1507                 :   nsCSSStyleSheet* clone = new nsCSSStyleSheet(*this,
    1508                 :                                                aCloneParent,
    1509                 :                                                aCloneOwnerRule,
    1510                 :                                                aCloneDocument,
    1511               0 :                                                aCloneOwningNode);
    1512               0 :   NS_IF_ADDREF(clone);
    1513               0 :   return clone;
    1514                 : }
    1515                 : 
    1516                 : #ifdef DEBUG
    1517                 : static void
    1518               0 : ListRules(const nsCOMArray<css::Rule>& aRules, FILE* aOut, PRInt32 aIndent)
    1519                 : {
    1520               0 :   for (PRInt32 index = aRules.Count() - 1; index >= 0; --index) {
    1521               0 :     aRules.ObjectAt(index)->List(aOut, aIndent);
    1522                 :   }
    1523               0 : }
    1524                 : 
    1525                 : struct ListEnumData {
    1526                 :   ListEnumData(FILE* aOut, PRInt32 aIndent)
    1527                 :     : mOut(aOut),
    1528                 :       mIndent(aIndent)
    1529                 :   {
    1530                 :   }
    1531                 :   FILE*   mOut;
    1532                 :   PRInt32 mIndent;
    1533                 : };
    1534                 : 
    1535                 : /* virtual */ void
    1536               0 : nsCSSStyleSheet::List(FILE* out, PRInt32 aIndent) const
    1537                 : {
    1538                 : 
    1539                 :   PRInt32 index;
    1540                 : 
    1541                 :   // Indent
    1542               0 :   for (index = aIndent; --index >= 0; ) fputs("  ", out);
    1543                 : 
    1544               0 :   fputs("CSS Style Sheet: ", out);
    1545               0 :   nsCAutoString urlSpec;
    1546               0 :   nsresult rv = mInner->mSheetURI->GetSpec(urlSpec);
    1547               0 :   if (NS_SUCCEEDED(rv) && !urlSpec.IsEmpty()) {
    1548               0 :     fputs(urlSpec.get(), out);
    1549                 :   }
    1550                 : 
    1551               0 :   if (mMedia) {
    1552               0 :     fputs(" media: ", out);
    1553               0 :     nsAutoString  buffer;
    1554               0 :     mMedia->GetText(buffer);
    1555               0 :     fputs(NS_ConvertUTF16toUTF8(buffer).get(), out);
    1556                 :   }
    1557               0 :   fputs("\n", out);
    1558                 : 
    1559               0 :   for (const nsCSSStyleSheet*  child = mInner->mFirstChild;
    1560                 :        child;
    1561               0 :        child = child->mNext) {
    1562               0 :     child->List(out, aIndent + 1);
    1563                 :   }
    1564                 : 
    1565               0 :   fputs("Rules in source order:\n", out);
    1566               0 :   ListRules(mInner->mOrderedRules, out, aIndent);
    1567               0 : }
    1568                 : #endif
    1569                 : 
    1570                 : void 
    1571               0 : nsCSSStyleSheet::ClearRuleCascades()
    1572                 : {
    1573               0 :   if (mRuleProcessors) {
    1574               0 :     nsCSSRuleProcessor **iter = mRuleProcessors->Elements(),
    1575               0 :                        **end = iter + mRuleProcessors->Length();
    1576               0 :     for(; iter != end; ++iter) {
    1577               0 :       (*iter)->ClearRuleCascades();
    1578                 :     }
    1579                 :   }
    1580               0 :   if (mParent) {
    1581               0 :     nsCSSStyleSheet* parent = (nsCSSStyleSheet*)mParent;
    1582               0 :     parent->ClearRuleCascades();
    1583                 :   }
    1584               0 : }
    1585                 : 
    1586                 : nsresult
    1587               0 : nsCSSStyleSheet::WillDirty()
    1588                 : {
    1589               0 :   if (!mInner->mComplete) {
    1590                 :     // Do nothing
    1591               0 :     return NS_OK;
    1592                 :   }
    1593                 : 
    1594               0 :   if (EnsureUniqueInner() == eUniqueInner_CloneFailed) {
    1595               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1596                 :   }
    1597               0 :   return NS_OK;
    1598                 : }
    1599                 : 
    1600                 : void
    1601               0 : nsCSSStyleSheet::DidDirty()
    1602                 : {
    1603               0 :   NS_ABORT_IF_FALSE(!mInner->mComplete || mDirty,
    1604                 :                     "caller must have called WillDirty()");
    1605               0 :   ClearRuleCascades();
    1606               0 : }
    1607                 : 
    1608                 : nsresult
    1609               0 : nsCSSStyleSheet::SubjectSubsumesInnerPrincipal() const
    1610                 : {
    1611                 :   // Get the security manager and do the subsumes check
    1612                 :   nsIScriptSecurityManager *securityManager =
    1613               0 :     nsContentUtils::GetSecurityManager();
    1614                 : 
    1615               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    1616               0 :   nsresult rv = securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    1617               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1618                 : 
    1619               0 :   if (!subjectPrincipal) {
    1620               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1621                 :   }
    1622                 : 
    1623                 :   bool subsumes;
    1624               0 :   rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
    1625               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1626                 : 
    1627               0 :   if (subsumes) {
    1628               0 :     return NS_OK;
    1629                 :   }
    1630                 :   
    1631               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    1632               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1633                 :   }
    1634                 : 
    1635               0 :   return NS_OK;
    1636                 : }
    1637                 : 
    1638                 : nsresult
    1639               0 : nsCSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
    1640                 : {
    1641               0 :   if (!mInner->mNameSpaceMap) {
    1642               0 :     nsresult rv = mInner->CreateNamespaceMap();
    1643               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1644                 :   }
    1645                 : 
    1646               0 :   AddNamespaceRuleToMap(aRule, mInner->mNameSpaceMap);
    1647               0 :   return NS_OK;
    1648                 : }
    1649                 : 
    1650                 :   // nsIDOMStyleSheet interface
    1651                 : NS_IMETHODIMP    
    1652               0 : nsCSSStyleSheet::GetType(nsAString& aType)
    1653                 : {
    1654               0 :   aType.AssignLiteral("text/css");
    1655               0 :   return NS_OK;
    1656                 : }
    1657                 : 
    1658                 : NS_IMETHODIMP    
    1659               0 : nsCSSStyleSheet::GetDisabled(bool* aDisabled)
    1660                 : {
    1661               0 :   *aDisabled = mDisabled;
    1662               0 :   return NS_OK;
    1663                 : }
    1664                 : 
    1665                 : NS_IMETHODIMP    
    1666               0 : nsCSSStyleSheet::SetDisabled(bool aDisabled)
    1667                 : {
    1668                 :   // DOM method, so handle BeginUpdate/EndUpdate
    1669               0 :   MOZ_AUTO_DOC_UPDATE(mDocument, UPDATE_STYLE, true);
    1670               0 :   nsCSSStyleSheet::SetEnabled(!aDisabled);
    1671               0 :   return NS_OK;
    1672                 : }
    1673                 : 
    1674                 : NS_IMETHODIMP
    1675               0 : nsCSSStyleSheet::GetOwnerNode(nsIDOMNode** aOwnerNode)
    1676                 : {
    1677               0 :   *aOwnerNode = mOwningNode;
    1678               0 :   NS_IF_ADDREF(*aOwnerNode);
    1679               0 :   return NS_OK;
    1680                 : }
    1681                 : 
    1682                 : NS_IMETHODIMP
    1683               0 : nsCSSStyleSheet::GetParentStyleSheet(nsIDOMStyleSheet** aParentStyleSheet)
    1684                 : {
    1685               0 :   NS_ENSURE_ARG_POINTER(aParentStyleSheet);
    1686                 : 
    1687               0 :   NS_IF_ADDREF(*aParentStyleSheet = mParent);
    1688                 : 
    1689               0 :   return NS_OK;
    1690                 : }
    1691                 : 
    1692                 : NS_IMETHODIMP
    1693               0 : nsCSSStyleSheet::GetHref(nsAString& aHref)
    1694                 : {
    1695               0 :   if (mInner->mOriginalSheetURI) {
    1696               0 :     nsCAutoString str;
    1697               0 :     mInner->mOriginalSheetURI->GetSpec(str);
    1698               0 :     CopyUTF8toUTF16(str, aHref);
    1699                 :   } else {
    1700               0 :     SetDOMStringToNull(aHref);
    1701                 :   }
    1702                 : 
    1703               0 :   return NS_OK;
    1704                 : }
    1705                 : 
    1706                 : /* virtual */ void
    1707               0 : nsCSSStyleSheet::GetTitle(nsString& aTitle) const
    1708                 : {
    1709               0 :   aTitle = mTitle;
    1710               0 : }
    1711                 : 
    1712                 : NS_IMETHODIMP
    1713               0 : nsCSSStyleSheet::GetTitle(nsAString& aTitle)
    1714                 : {
    1715               0 :   aTitle.Assign(mTitle);
    1716               0 :   return NS_OK;
    1717                 : }
    1718                 : 
    1719                 : NS_IMETHODIMP
    1720               0 : nsCSSStyleSheet::GetMedia(nsIDOMMediaList** aMedia)
    1721                 : {
    1722               0 :   NS_ENSURE_ARG_POINTER(aMedia);
    1723               0 :   *aMedia = nsnull;
    1724                 : 
    1725               0 :   if (!mMedia) {
    1726               0 :     mMedia = new nsMediaList();
    1727               0 :     NS_ENSURE_TRUE(mMedia, NS_ERROR_OUT_OF_MEMORY);
    1728               0 :     mMedia->SetStyleSheet(this);
    1729                 :   }
    1730                 : 
    1731               0 :   *aMedia = mMedia;
    1732               0 :   NS_ADDREF(*aMedia);
    1733                 : 
    1734               0 :   return NS_OK;
    1735                 : }
    1736                 : 
    1737                 : NS_IMETHODIMP    
    1738               0 : nsCSSStyleSheet::GetOwnerRule(nsIDOMCSSRule** aOwnerRule)
    1739                 : {
    1740               0 :   if (mOwnerRule) {
    1741               0 :     NS_IF_ADDREF(*aOwnerRule = mOwnerRule->GetDOMRule());
    1742                 :   } else {
    1743               0 :     *aOwnerRule = nsnull;
    1744                 :   }
    1745               0 :   return NS_OK;
    1746                 : }
    1747                 : 
    1748                 : NS_IMETHODIMP    
    1749               0 : nsCSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
    1750                 : {
    1751                 :   // No doing this on incomplete sheets!
    1752               0 :   if (!mInner->mComplete) {
    1753               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    1754                 :   }
    1755                 :   
    1756                 :   //-- Security check: Only scripts whose principal subsumes that of the
    1757                 :   //   style sheet can access rule collections.
    1758               0 :   nsresult rv = SubjectSubsumesInnerPrincipal();
    1759               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1760                 : 
    1761                 :   // OK, security check passed, so get the rule collection
    1762               0 :   if (nsnull == mRuleCollection) {
    1763               0 :     mRuleCollection = new CSSRuleListImpl(this);
    1764               0 :     if (nsnull == mRuleCollection) {
    1765               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1766                 :     }
    1767               0 :     NS_ADDREF(mRuleCollection);
    1768                 :   }
    1769                 : 
    1770               0 :   *aCssRules = mRuleCollection;
    1771               0 :   NS_ADDREF(mRuleCollection);
    1772                 : 
    1773               0 :   return NS_OK;
    1774                 : }
    1775                 : 
    1776                 : NS_IMETHODIMP    
    1777               0 : nsCSSStyleSheet::InsertRule(const nsAString& aRule, 
    1778                 :                             PRUint32 aIndex, 
    1779                 :                             PRUint32* aReturn)
    1780                 : {
    1781                 :   //-- Security check: Only scripts whose principal subsumes that of the
    1782                 :   //   style sheet can modify rule collections.
    1783               0 :   nsresult rv = SubjectSubsumesInnerPrincipal();
    1784               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1785                 : 
    1786               0 :   return InsertRuleInternal(aRule, aIndex, aReturn);
    1787                 : }
    1788                 : 
    1789                 : nsresult
    1790               0 : nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule, 
    1791                 :                                     PRUint32 aIndex, 
    1792                 :                                     PRUint32* aReturn)
    1793                 : {
    1794                 :   // No doing this if the sheet is not complete!
    1795               0 :   if (!mInner->mComplete) {
    1796               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    1797                 :   }
    1798                 : 
    1799               0 :   if (aRule.IsEmpty()) {
    1800                 :     // Nothing to do here
    1801               0 :     return NS_OK;
    1802                 :   }
    1803                 :   
    1804                 :   nsresult result;
    1805               0 :   result = WillDirty();
    1806               0 :   if (NS_FAILED(result))
    1807               0 :     return result;
    1808                 :   
    1809               0 :   if (aIndex > PRUint32(mInner->mOrderedRules.Count()))
    1810               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
    1811                 :   
    1812               0 :   NS_ASSERTION(PRUint32(mInner->mOrderedRules.Count()) <= PR_INT32_MAX,
    1813                 :                "Too many style rules!");
    1814                 : 
    1815                 :   // Hold strong ref to the CSSLoader in case the document update
    1816                 :   // kills the document
    1817               0 :   nsRefPtr<css::Loader> loader;
    1818               0 :   if (mDocument) {
    1819               0 :     loader = mDocument->CSSLoader();
    1820               0 :     NS_ASSERTION(loader, "Document with no CSS loader!");
    1821                 :   }
    1822                 : 
    1823               0 :   nsCSSParser css(loader, this);
    1824                 : 
    1825               0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
    1826                 : 
    1827               0 :   nsCOMArray<css::Rule> rules;
    1828                 :   result = css.ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
    1829               0 :                          mInner->mPrincipal, rules);
    1830               0 :   if (NS_FAILED(result))
    1831               0 :     return result;
    1832                 : 
    1833               0 :   PRInt32 rulecount = rules.Count();
    1834               0 :   if (rulecount == 0) {
    1835                 :     // Since we know aRule was not an empty string, just throw
    1836               0 :     return NS_ERROR_DOM_SYNTAX_ERR;
    1837                 :   }
    1838                 :   
    1839                 :   // Hierarchy checking.  Just check the first and last rule in the list.
    1840                 :   
    1841                 :   // check that we're not inserting before a charset rule
    1842               0 :   css::Rule* nextRule = mInner->mOrderedRules.SafeObjectAt(aIndex);
    1843               0 :   if (nextRule) {
    1844               0 :     PRInt32 nextType = nextRule->GetType();
    1845               0 :     if (nextType == css::Rule::CHARSET_RULE) {
    1846               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1847                 :     }
    1848                 : 
    1849                 :     // check last rule in list
    1850               0 :     css::Rule* lastRule = rules.ObjectAt(rulecount - 1);
    1851               0 :     PRInt32 lastType = lastRule->GetType();
    1852                 : 
    1853               0 :     if (nextType == css::Rule::IMPORT_RULE &&
    1854                 :         lastType != css::Rule::CHARSET_RULE &&
    1855                 :         lastType != css::Rule::IMPORT_RULE) {
    1856               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1857                 :     }
    1858                 :     
    1859               0 :     if (nextType == css::Rule::NAMESPACE_RULE &&
    1860                 :         lastType != css::Rule::CHARSET_RULE &&
    1861                 :         lastType != css::Rule::IMPORT_RULE &&
    1862                 :         lastType != css::Rule::NAMESPACE_RULE) {
    1863               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1864                 :     } 
    1865                 :   }
    1866                 :   
    1867                 :   // check first rule in list
    1868               0 :   css::Rule* firstRule = rules.ObjectAt(0);
    1869               0 :   PRInt32 firstType = firstRule->GetType();
    1870               0 :   if (aIndex != 0) {
    1871               0 :     if (firstType == css::Rule::CHARSET_RULE) { // no inserting charset at nonzero position
    1872               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1873                 :     }
    1874                 :   
    1875               0 :     css::Rule* prevRule = mInner->mOrderedRules.SafeObjectAt(aIndex - 1);
    1876               0 :     PRInt32 prevType = prevRule->GetType();
    1877                 : 
    1878               0 :     if (firstType == css::Rule::IMPORT_RULE &&
    1879                 :         prevType != css::Rule::CHARSET_RULE &&
    1880                 :         prevType != css::Rule::IMPORT_RULE) {
    1881               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1882                 :     }
    1883                 : 
    1884               0 :     if (firstType == css::Rule::NAMESPACE_RULE &&
    1885                 :         prevType != css::Rule::CHARSET_RULE &&
    1886                 :         prevType != css::Rule::IMPORT_RULE &&
    1887                 :         prevType != css::Rule::NAMESPACE_RULE) {
    1888               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1889                 :     }
    1890                 :   }
    1891                 :   
    1892               0 :   bool insertResult = mInner->mOrderedRules.InsertObjectsAt(rules, aIndex);
    1893               0 :   NS_ENSURE_TRUE(insertResult, NS_ERROR_OUT_OF_MEMORY);
    1894               0 :   DidDirty();
    1895                 : 
    1896               0 :   for (PRInt32 counter = 0; counter < rulecount; counter++) {
    1897               0 :     css::Rule* cssRule = rules.ObjectAt(counter);
    1898               0 :     cssRule->SetStyleSheet(this);
    1899                 : 
    1900               0 :     PRInt32 type = cssRule->GetType();
    1901               0 :     if (type == css::Rule::NAMESPACE_RULE) {
    1902                 :       // XXXbz does this screw up when inserting a namespace rule before
    1903                 :       // another namespace rule that binds the same prefix to a different
    1904                 :       // namespace?
    1905               0 :       result = RegisterNamespaceRule(cssRule);
    1906               0 :       NS_ENSURE_SUCCESS(result, result);
    1907                 :     }
    1908                 : 
    1909                 :     // We don't notify immediately for @import rules, but rather when
    1910                 :     // the sheet the rule is importing is loaded
    1911               0 :     bool notify = true;
    1912               0 :     if (type == css::Rule::IMPORT_RULE) {
    1913               0 :       nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(cssRule));
    1914               0 :       NS_ASSERTION(importRule, "Rule which has type IMPORT_RULE and does not implement nsIDOMCSSImportRule!");
    1915               0 :       nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
    1916               0 :       importRule->GetStyleSheet(getter_AddRefs(childSheet));
    1917               0 :       if (!childSheet) {
    1918               0 :         notify = false;
    1919                 :       }
    1920                 :     }
    1921               0 :     if (mDocument && notify) {
    1922               0 :       mDocument->StyleRuleAdded(this, cssRule);
    1923                 :     }
    1924                 :   }
    1925                 :   
    1926               0 :   *aReturn = aIndex;
    1927               0 :   return NS_OK;
    1928                 : }
    1929                 : 
    1930                 : NS_IMETHODIMP    
    1931               0 : nsCSSStyleSheet::DeleteRule(PRUint32 aIndex)
    1932                 : {
    1933               0 :   nsresult result = NS_ERROR_DOM_INDEX_SIZE_ERR;
    1934                 :   // No doing this if the sheet is not complete!
    1935               0 :   if (!mInner->mComplete) {
    1936               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    1937                 :   }
    1938                 : 
    1939                 :   //-- Security check: Only scripts whose principal subsumes that of the
    1940                 :   //   style sheet can modify rule collections.
    1941               0 :   nsresult rv = SubjectSubsumesInnerPrincipal();
    1942               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1943                 : 
    1944                 :   // XXX TBI: handle @rule types
    1945               0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
    1946                 :     
    1947               0 :   result = WillDirty();
    1948                 : 
    1949               0 :   if (NS_SUCCEEDED(result)) {
    1950               0 :     if (aIndex >= PRUint32(mInner->mOrderedRules.Count()))
    1951               0 :       return NS_ERROR_DOM_INDEX_SIZE_ERR;
    1952                 : 
    1953               0 :     NS_ASSERTION(PRUint32(mInner->mOrderedRules.Count()) <= PR_INT32_MAX,
    1954                 :                  "Too many style rules!");
    1955                 : 
    1956                 :     // Hold a strong ref to the rule so it doesn't die when we RemoveObjectAt
    1957               0 :     nsRefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(aIndex);
    1958               0 :     if (rule) {
    1959               0 :       mInner->mOrderedRules.RemoveObjectAt(aIndex);
    1960               0 :       rule->SetStyleSheet(nsnull);
    1961               0 :       DidDirty();
    1962                 : 
    1963               0 :       if (mDocument) {
    1964               0 :         mDocument->StyleRuleRemoved(this, rule);
    1965                 :       }
    1966                 :     }
    1967                 :   }
    1968                 : 
    1969               0 :   return result;
    1970                 : }
    1971                 : 
    1972                 : nsresult
    1973               0 : nsCSSStyleSheet::DeleteRuleFromGroup(css::GroupRule* aGroup, PRUint32 aIndex)
    1974                 : {
    1975               0 :   NS_ENSURE_ARG_POINTER(aGroup);
    1976               0 :   NS_ASSERTION(mInner->mComplete, "No deleting from an incomplete sheet!");
    1977                 :   nsresult result;
    1978               0 :   nsRefPtr<css::Rule> rule = aGroup->GetStyleRuleAt(aIndex);
    1979               0 :   NS_ENSURE_TRUE(rule, NS_ERROR_ILLEGAL_VALUE);
    1980                 : 
    1981                 :   // check that the rule actually belongs to this sheet!
    1982               0 :   if (this != rule->GetStyleSheet()) {
    1983               0 :     return NS_ERROR_INVALID_ARG;
    1984                 :   }
    1985                 : 
    1986               0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
    1987                 :   
    1988               0 :   result = WillDirty();
    1989               0 :   NS_ENSURE_SUCCESS(result, result);
    1990                 : 
    1991               0 :   result = aGroup->DeleteStyleRuleAt(aIndex);
    1992               0 :   NS_ENSURE_SUCCESS(result, result);
    1993                 :   
    1994               0 :   rule->SetStyleSheet(nsnull);
    1995                 :   
    1996               0 :   DidDirty();
    1997                 : 
    1998               0 :   if (mDocument) {
    1999               0 :     mDocument->StyleRuleRemoved(this, rule);
    2000                 :   }
    2001                 : 
    2002               0 :   return NS_OK;
    2003                 : }
    2004                 : 
    2005                 : nsresult
    2006               0 : nsCSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule,
    2007                 :                                      css::GroupRule* aGroup,
    2008                 :                                      PRUint32 aIndex,
    2009                 :                                      PRUint32* _retval)
    2010                 : {
    2011                 :   nsresult result;
    2012               0 :   NS_ASSERTION(mInner->mComplete, "No inserting into an incomplete sheet!");
    2013                 :   // check that the group actually belongs to this sheet!
    2014               0 :   if (this != aGroup->GetStyleSheet()) {
    2015               0 :     return NS_ERROR_INVALID_ARG;
    2016                 :   }
    2017                 : 
    2018               0 :   if (aRule.IsEmpty()) {
    2019                 :     // Nothing to do here
    2020               0 :     return NS_OK;
    2021                 :   }
    2022                 : 
    2023                 :   // Hold strong ref to the CSSLoader in case the document update
    2024                 :   // kills the document
    2025               0 :   nsRefPtr<css::Loader> loader;
    2026               0 :   if (mDocument) {
    2027               0 :     loader = mDocument->CSSLoader();
    2028               0 :     NS_ASSERTION(loader, "Document with no CSS loader!");
    2029                 :   }
    2030                 : 
    2031               0 :   nsCSSParser css(loader, this);
    2032                 : 
    2033                 :   // parse and grab the rule
    2034               0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
    2035                 : 
    2036               0 :   result = WillDirty();
    2037               0 :   NS_ENSURE_SUCCESS(result, result);
    2038                 : 
    2039               0 :   nsCOMArray<css::Rule> rules;
    2040                 :   result = css.ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
    2041               0 :                          mInner->mPrincipal, rules);
    2042               0 :   NS_ENSURE_SUCCESS(result, result);
    2043                 : 
    2044               0 :   PRInt32 rulecount = rules.Count();
    2045               0 :   if (rulecount == 0) {
    2046                 :     // Since we know aRule was not an empty string, just throw
    2047               0 :     return NS_ERROR_DOM_SYNTAX_ERR;
    2048                 :   }
    2049                 : 
    2050                 :   PRInt32 counter;
    2051                 :   css::Rule* rule;
    2052               0 :   for (counter = 0; counter < rulecount; counter++) {
    2053                 :     // Only rulesets are allowed in a group as of CSS2
    2054               0 :     rule = rules.ObjectAt(counter);
    2055               0 :     if (rule->GetType() != css::Rule::STYLE_RULE) {
    2056               0 :       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    2057                 :     }
    2058                 :   }
    2059                 :   
    2060               0 :   result = aGroup->InsertStyleRulesAt(aIndex, rules);
    2061               0 :   NS_ENSURE_SUCCESS(result, result);
    2062               0 :   DidDirty();
    2063               0 :   for (counter = 0; counter < rulecount; counter++) {
    2064               0 :     rule = rules.ObjectAt(counter);
    2065                 :   
    2066               0 :     if (mDocument) {
    2067               0 :       mDocument->StyleRuleAdded(this, rule);
    2068                 :     }
    2069                 :   }
    2070                 : 
    2071               0 :   *_retval = aIndex;
    2072               0 :   return NS_OK;
    2073                 : }
    2074                 : 
    2075                 : nsresult
    2076               0 : nsCSSStyleSheet::ReplaceRuleInGroup(css::GroupRule* aGroup,
    2077                 :                                     css::Rule* aOld, css::Rule* aNew)
    2078                 : {
    2079                 :   nsresult result;
    2080               0 :   NS_PRECONDITION(mInner->mComplete, "No replacing in an incomplete sheet!");
    2081               0 :   NS_ASSERTION(this == aGroup->GetStyleSheet(), "group doesn't belong to this sheet");
    2082               0 :   result = WillDirty();
    2083               0 :   NS_ENSURE_SUCCESS(result, result);
    2084                 : 
    2085               0 :   result = aGroup->ReplaceStyleRule(aOld, aNew);
    2086               0 :   DidDirty();
    2087               0 :   return result;
    2088                 : }
    2089                 : 
    2090                 : // nsICSSLoaderObserver implementation
    2091                 : NS_IMETHODIMP
    2092               0 : nsCSSStyleSheet::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
    2093                 :                                   bool aWasAlternate,
    2094                 :                                   nsresult aStatus)
    2095                 : {
    2096               0 :   NS_ASSERTION(this == aSheet->GetParentSheet(),
    2097                 :                "We are being notified of a sheet load for a sheet that is not our child!");
    2098                 : 
    2099               0 :   if (mDocument && NS_SUCCEEDED(aStatus)) {
    2100               0 :     mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
    2101                 : 
    2102                 :     // XXXldb @import rules shouldn't even implement nsIStyleRule (but
    2103                 :     // they do)!
    2104               0 :     mDocument->StyleRuleAdded(this, aSheet->GetOwnerRule());
    2105                 :   }
    2106                 : 
    2107               0 :   return NS_OK;
    2108                 : }
    2109                 : 
    2110                 : /* virtual */ nsIURI*
    2111               0 : nsCSSStyleSheet::GetOriginalURI() const
    2112                 : {
    2113               0 :   return mInner->mOriginalSheetURI;
    2114                 : }
    2115                 : 
    2116                 : nsresult
    2117               0 : NS_NewCSSStyleSheet(nsCSSStyleSheet** aInstancePtrResult)
    2118                 : {
    2119               0 :   *aInstancePtrResult = nsnull;
    2120               0 :   nsCSSStyleSheet  *it = new nsCSSStyleSheet();
    2121                 : 
    2122               0 :   if (!it) {
    2123               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2124                 :   }
    2125                 : 
    2126               0 :   NS_ADDREF(it);
    2127                 : 
    2128               0 :   if (!it->mInner || !it->mInner->mPrincipal) {
    2129               0 :     NS_RELEASE(it);
    2130               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2131                 :   }
    2132                 :   
    2133               0 :   *aInstancePtrResult = it;
    2134               0 :   return NS_OK;
    2135                 : }

Generated by: LCOV version 1.7