LCOV - code coverage report
Current view: top level - layout/style - StyleSheet.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 93 382 24.3 %
Date: 2017-07-14 16:53:18 Functions: 20 68 29.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/StyleSheet.h"
       8             : 
       9             : #include "mozilla/dom/CSSImportRule.h"
      10             : #include "mozilla/dom/CSSRuleList.h"
      11             : #include "mozilla/dom/MediaList.h"
      12             : #include "mozilla/dom/ShadowRoot.h"
      13             : #include "mozilla/ServoCSSRuleList.h"
      14             : #include "mozilla/ServoStyleSheet.h"
      15             : #include "mozilla/StyleSheetInlines.h"
      16             : #include "mozilla/CSSStyleSheet.h"
      17             : 
      18             : #include "mozAutoDocUpdate.h"
      19             : #include "NullPrincipal.h"
      20             : 
      21             : namespace mozilla {
      22             : 
      23          60 : StyleSheet::StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode)
      24             :   : mParent(nullptr)
      25             :   , mDocument(nullptr)
      26             :   , mOwningNode(nullptr)
      27             :   , mOwnerRule(nullptr)
      28             :   , mParsingMode(aParsingMode)
      29             :   , mType(aType)
      30             :   , mDisabled(false)
      31             :   , mDirty(false)
      32             :   , mDocumentAssociationMode(NotOwnedByDocument)
      33          60 :   , mInner(nullptr)
      34             : {
      35          60 : }
      36             : 
      37          15 : StyleSheet::StyleSheet(const StyleSheet& aCopy,
      38             :                        StyleSheet* aParentToUse,
      39             :                        dom::CSSImportRule* aOwnerRuleToUse,
      40             :                        nsIDocument* aDocumentToUse,
      41          15 :                        nsINode* aOwningNodeToUse)
      42             :   : mParent(aParentToUse)
      43             :   , mTitle(aCopy.mTitle)
      44             :   , mDocument(aDocumentToUse)
      45             :   , mOwningNode(aOwningNodeToUse)
      46             :   , mOwnerRule(aOwnerRuleToUse)
      47          15 :   , mParsingMode(aCopy.mParsingMode)
      48          15 :   , mType(aCopy.mType)
      49          15 :   , mDisabled(aCopy.mDisabled)
      50          15 :   , mDirty(aCopy.mDirty)
      51             :   // We only use this constructor during cloning.  It's the cloner's
      52             :   // responsibility to notify us if we end up being owned by a document.
      53             :   , mDocumentAssociationMode(NotOwnedByDocument)
      54          75 :   , mInner(aCopy.mInner) // Shallow copy, but concrete subclasses will fix up.
      55             : {
      56          15 :   MOZ_ASSERT(mInner, "Should only copy StyleSheets with an mInner.");
      57          15 :   mInner->AddSheet(this);
      58             : 
      59          15 :   if (aCopy.mMedia) {
      60             :     // XXX This is wrong; we should be keeping @import rules and
      61             :     // sheets in sync!
      62           0 :     mMedia = aCopy.mMedia->Clone();
      63             :   }
      64          15 : }
      65             : 
      66           0 : StyleSheet::~StyleSheet()
      67             : {
      68           0 :   MOZ_ASSERT(!mInner, "Inner should have been dropped in LastRelease");
      69           0 : }
      70             : 
      71             : void
      72           0 : StyleSheet::LastRelease()
      73             : {
      74           0 :   MOZ_ASSERT(mInner, "Should have an mInner at time of destruction.");
      75           0 :   MOZ_ASSERT(mInner->mSheets.Contains(this), "Our mInner should include us.");
      76             : 
      77           0 :   UnparentChildren();
      78           0 :   if (IsGecko()) {
      79           0 :     AsGecko()->LastRelease();
      80             :   } else {
      81           0 :     AsServo()->LastRelease();
      82             :   }
      83             : 
      84           0 :   mInner->RemoveSheet(this);
      85           0 :   mInner = nullptr;
      86             : 
      87           0 :   DropMedia();
      88           0 : }
      89             : 
      90             : void
      91           0 : StyleSheet::UnlinkInner()
      92             : {
      93             :   // We can only have a cycle through our inner if we have a unique inner,
      94             :   // because otherwise there are no JS wrappers for anything in the inner.
      95           0 :   if (mInner->mSheets.Length() != 1) {
      96           0 :     return;
      97             :   }
      98             : 
      99             :   // Have to be a bit careful with child sheets, because we want to
     100             :   // drop their mNext pointers and null out their mParent and
     101             :   // mDocument, but don't want to work with deleted objects.  And we
     102             :   // don't want to do any addrefing in the process, just to make sure
     103             :   // we don't confuse the cycle collector (though on the face of it,
     104             :   // addref/release pairs during unlink should probably be ok).
     105           0 :   RefPtr<StyleSheet> child;
     106           0 :   child.swap(SheetInfo().mFirstChild);
     107           0 :   while (child) {
     108           0 :     MOZ_ASSERT(child->mParent == this, "We have a unique inner!");
     109           0 :     child->mParent = nullptr;
     110             :     // We (and child) might still think we're owned by a document, because
     111             :     // unlink order is non-deterministic, so the document's unlink, which would
     112             :     // tell us it does't own us anymore, may not have happened yet.  But if
     113             :     // we're being unlinked, clearly we're not owned by a document anymore
     114             :     // conceptually!
     115           0 :     child->SetAssociatedDocument(nullptr, NotOwnedByDocument);
     116             : 
     117           0 :     RefPtr<StyleSheet> next;
     118             :     // Null out child->mNext, but don't let it die yet
     119           0 :     next.swap(child->mNext);
     120             :     // Switch to looking at the old value of child->mNext next iteration
     121           0 :     child.swap(next);
     122             :     // "next" is now our previous value of child; it'll get released
     123             :     // as we loop around.
     124             :   }
     125             : }
     126             : 
     127             : void
     128           0 : StyleSheet::TraverseInner(nsCycleCollectionTraversalCallback &cb)
     129             : {
     130             :   // We can only have a cycle through our inner if we have a unique inner,
     131             :   // because otherwise there are no JS wrappers for anything in the inner.
     132           0 :   if (mInner->mSheets.Length() != 1) {
     133           0 :     return;
     134             :   }
     135             : 
     136           0 :   StyleSheet* childSheet = GetFirstChild();
     137           0 :   while (childSheet) {
     138           0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "child sheet");
     139           0 :     cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, childSheet));
     140           0 :     childSheet = childSheet->mNext;
     141             :   }
     142             : }
     143             : 
     144             : // QueryInterface implementation for StyleSheet
     145           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StyleSheet)
     146           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     147           0 :   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
     148           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStyleSheet)
     149           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleSheet)
     150           0 : NS_INTERFACE_MAP_END
     151             : 
     152         776 : NS_IMPL_CYCLE_COLLECTING_ADDREF(StyleSheet)
     153             : // We want to disconnect from our inner as soon as our refcount drops to zero,
     154             : // without waiting for async deletion by the cycle collector.  Otherwise we
     155             : // might end up cloning the inner if someone mutates another sheet that shares
     156             : // it with us, even though there is only one such sheet and we're about to go
     157             : // away.  This situation arises easily with sheet preloading.
     158         410 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(StyleSheet, LastRelease())
     159             : 
     160             : NS_IMPL_CYCLE_COLLECTION_CLASS(StyleSheet)
     161             : 
     162           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(StyleSheet)
     163           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia)
     164           0 :   tmp->TraverseInner(cb);
     165           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     166             : 
     167           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(StyleSheet)
     168           0 :   tmp->DropMedia();
     169           0 :   tmp->UnlinkInner();
     170           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     171           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     172             : 
     173           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(StyleSheet)
     174             : 
     175             : mozilla::dom::CSSStyleSheetParsingMode
     176           0 : StyleSheet::ParsingModeDOM()
     177             : {
     178             : #define CHECK(X, Y) \
     179             :   static_assert(static_cast<int>(X) == static_cast<int>(Y),             \
     180             :                 "mozilla::dom::CSSStyleSheetParsingMode and mozilla::css::SheetParsingMode should have identical values");
     181             : 
     182             :   CHECK(mozilla::dom::CSSStyleSheetParsingMode::Agent, css::eAgentSheetFeatures);
     183             :   CHECK(mozilla::dom::CSSStyleSheetParsingMode::User, css::eUserSheetFeatures);
     184             :   CHECK(mozilla::dom::CSSStyleSheetParsingMode::Author, css::eAuthorSheetFeatures);
     185             : 
     186             : #undef CHECK
     187             : 
     188           0 :   return static_cast<mozilla::dom::CSSStyleSheetParsingMode>(mParsingMode);
     189             : }
     190             : 
     191             : bool
     192         161 : StyleSheet::IsComplete() const
     193             : {
     194         161 :   return SheetInfo().mComplete;
     195             : }
     196             : 
     197             : void
     198          60 : StyleSheet::SetComplete()
     199             : {
     200          60 :   NS_ASSERTION(!mDirty, "Can't set a dirty sheet complete!");
     201          60 :   SheetInfo().mComplete = true;
     202          60 :   if (mDocument && !mDisabled) {
     203             :     // Let the document know
     204          13 :     mDocument->BeginUpdate(UPDATE_STYLE);
     205          13 :     mDocument->SetStyleSheetApplicableState(this, true);
     206          13 :     mDocument->EndUpdate(UPDATE_STYLE);
     207             :   }
     208             : 
     209         142 :   if (mOwningNode && !mDisabled &&
     210          71 :       mOwningNode->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
     211           0 :       mOwningNode->IsContent()) {
     212           0 :     dom::ShadowRoot* shadowRoot = mOwningNode->AsContent()->GetContainingShadow();
     213           0 :     shadowRoot->StyleSheetChanged();
     214             :   }
     215          60 : }
     216             : 
     217             : void
     218          76 : StyleSheet::SetEnabled(bool aEnabled)
     219             : {
     220             :   // Internal method, so callers must handle BeginUpdate/EndUpdate
     221          76 :   bool oldDisabled = mDisabled;
     222          76 :   mDisabled = !aEnabled;
     223             : 
     224          76 :   if (IsComplete() && oldDisabled != mDisabled) {
     225           0 :     EnabledStateChanged();
     226             : 
     227           0 :     if (mDocument) {
     228           0 :       mDocument->SetStyleSheetApplicableState(this, !mDisabled);
     229             :     }
     230             :   }
     231          76 : }
     232             : 
     233          60 : StyleSheetInfo::StyleSheetInfo(CORSMode aCORSMode,
     234             :                                ReferrerPolicy aReferrerPolicy,
     235          60 :                                const dom::SRIMetadata& aIntegrity)
     236         120 :   : mPrincipal(NullPrincipal::Create())
     237             :   , mCORSMode(aCORSMode)
     238             :   , mReferrerPolicy(aReferrerPolicy)
     239             :   , mIntegrity(aIntegrity)
     240             :   , mComplete(false)
     241             : #ifdef DEBUG
     242         180 :   , mPrincipalSet(false)
     243             : #endif
     244             : {
     245          60 :   if (!mPrincipal) {
     246           0 :     NS_RUNTIMEABORT("NullPrincipal::Init failed");
     247             :   }
     248          60 : }
     249             : 
     250           0 : StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy,
     251           0 :                                StyleSheet* aPrimarySheet)
     252             :   : mSheetURI(aCopy.mSheetURI)
     253             :   , mOriginalSheetURI(aCopy.mOriginalSheetURI)
     254             :   , mBaseURI(aCopy.mBaseURI)
     255             :   , mPrincipal(aCopy.mPrincipal)
     256           0 :   , mCORSMode(aCopy.mCORSMode)
     257           0 :   , mReferrerPolicy(aCopy.mReferrerPolicy)
     258             :   , mIntegrity(aCopy.mIntegrity)
     259           0 :   , mComplete(aCopy.mComplete)
     260             :   , mFirstChild()  // We don't rebuild the child because we're making a copy
     261             :                    // without children.
     262             :   , mSourceMapURL(aCopy.mSourceMapURL)
     263             : #ifdef DEBUG
     264           0 :   , mPrincipalSet(aCopy.mPrincipalSet)
     265             : #endif
     266             : {
     267           0 :   AddSheet(aPrimarySheet);
     268           0 : }
     269             : 
     270           0 : StyleSheetInfo::~StyleSheetInfo()
     271             : {
     272           0 : }
     273             : 
     274             : void
     275          75 : StyleSheetInfo::AddSheet(StyleSheet* aSheet)
     276             : {
     277          75 :   mSheets.AppendElement(aSheet);
     278          75 : }
     279             : 
     280             : void
     281           0 : StyleSheetInfo::RemoveSheet(StyleSheet* aSheet)
     282             : {
     283           0 :   if ((aSheet == mSheets.ElementAt(0)) && (mSheets.Length() > 1)) {
     284           0 :     StyleSheet::ChildSheetListBuilder::ReparentChildList(mSheets[1], mFirstChild);
     285             :   }
     286             : 
     287           0 :   if (1 == mSheets.Length()) {
     288           0 :     NS_ASSERTION(aSheet == mSheets.ElementAt(0), "bad parent");
     289           0 :     delete this;
     290           0 :     return;
     291             :   }
     292             : 
     293           0 :   mSheets.RemoveElement(aSheet);
     294             : }
     295             : 
     296             : void
     297           0 : StyleSheet::ChildSheetListBuilder::SetParentLinks(StyleSheet* aSheet)
     298             : {
     299           0 :   aSheet->mParent = parent;
     300           0 :   aSheet->SetAssociatedDocument(parent->mDocument,
     301           0 :                                 parent->mDocumentAssociationMode);
     302           0 : }
     303             : 
     304             : void
     305           0 : StyleSheet::ChildSheetListBuilder::ReparentChildList(StyleSheet* aPrimarySheet,
     306             :                                                      StyleSheet* aFirstChild)
     307             : {
     308           0 :   for (StyleSheet *child = aFirstChild; child; child = child->mNext) {
     309           0 :     child->mParent = aPrimarySheet;
     310           0 :     child->SetAssociatedDocument(aPrimarySheet->mDocument,
     311           0 :                                  aPrimarySheet->mDocumentAssociationMode);
     312             :   }
     313           0 : }
     314             : 
     315             : // nsIDOMStyleSheet interface
     316             : 
     317             : NS_IMETHODIMP
     318           0 : StyleSheet::GetType(nsAString& aType)
     319             : {
     320           0 :   aType.AssignLiteral("text/css");
     321           0 :   return NS_OK;
     322             : }
     323             : 
     324             : NS_IMETHODIMP
     325           0 : StyleSheet::GetDisabled(bool* aDisabled)
     326             : {
     327           0 :   *aDisabled = Disabled();
     328           0 :   return NS_OK;
     329             : }
     330             : 
     331             : NS_IMETHODIMP
     332           0 : StyleSheet::SetDisabled(bool aDisabled)
     333             : {
     334             :   // DOM method, so handle BeginUpdate/EndUpdate
     335           0 :   MOZ_AUTO_DOC_UPDATE(mDocument, UPDATE_STYLE, true);
     336           0 :   SetEnabled(!aDisabled);
     337           0 :   return NS_OK;
     338             : }
     339             : 
     340             : NS_IMETHODIMP
     341           0 : StyleSheet::GetOwnerNode(nsIDOMNode** aOwnerNode)
     342             : {
     343           0 :   nsCOMPtr<nsIDOMNode> ownerNode = do_QueryInterface(GetOwnerNode());
     344           0 :   ownerNode.forget(aOwnerNode);
     345           0 :   return NS_OK;
     346             : }
     347             : 
     348             : NS_IMETHODIMP
     349           0 : StyleSheet::GetHref(nsAString& aHref)
     350             : {
     351           0 :   if (nsIURI* sheetURI = SheetInfo().mOriginalSheetURI) {
     352           0 :     nsAutoCString str;
     353           0 :     nsresult rv = sheetURI->GetSpec(str);
     354           0 :     NS_ENSURE_SUCCESS(rv, rv);
     355           0 :     CopyUTF8toUTF16(str, aHref);
     356             :   } else {
     357           0 :     SetDOMStringToNull(aHref);
     358             :   }
     359           0 :   return NS_OK;
     360             : }
     361             : 
     362             : NS_IMETHODIMP
     363           0 : StyleSheet::GetTitle(nsAString& aTitle)
     364             : {
     365           0 :   aTitle.Assign(mTitle);
     366           0 :   return NS_OK;
     367             : }
     368             : 
     369             : // nsIDOMStyleSheet interface
     370             : 
     371             : NS_IMETHODIMP
     372           0 : StyleSheet::GetParentStyleSheet(nsIDOMStyleSheet** aParentStyleSheet)
     373             : {
     374           0 :   NS_ENSURE_ARG_POINTER(aParentStyleSheet);
     375           0 :   NS_IF_ADDREF(*aParentStyleSheet = GetParentStyleSheet());
     376           0 :   return NS_OK;
     377             : }
     378             : 
     379             : NS_IMETHODIMP
     380           0 : StyleSheet::GetMedia(nsIDOMMediaList** aMedia)
     381             : {
     382           0 :   NS_ADDREF(*aMedia = Media());
     383           0 :   return NS_OK;
     384             : }
     385             : 
     386             : NS_IMETHODIMP
     387           0 : StyleSheet::GetOwnerRule(nsIDOMCSSRule** aOwnerRule)
     388             : {
     389           0 :   NS_IF_ADDREF(*aOwnerRule = GetDOMOwnerRule());
     390           0 :   return NS_OK;
     391             : }
     392             : 
     393             : NS_IMETHODIMP
     394           0 : StyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
     395             : {
     396           0 :   ErrorResult rv;
     397             :   nsCOMPtr<nsIDOMCSSRuleList> rules =
     398           0 :     GetCssRules(*nsContentUtils::SubjectPrincipal(), rv);
     399           0 :   rules.forget(aCssRules);
     400           0 :   return rv.StealNSResult();
     401             : }
     402             : 
     403             : NS_IMETHODIMP
     404           0 : StyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
     405             :                        uint32_t* aReturn)
     406             : {
     407           0 :   ErrorResult rv;
     408           0 :   *aReturn =
     409           0 :     InsertRule(aRule, aIndex, *nsContentUtils::SubjectPrincipal(), rv);
     410           0 :   return rv.StealNSResult();
     411             : }
     412             : 
     413             : NS_IMETHODIMP
     414           0 : StyleSheet::DeleteRule(uint32_t aIndex)
     415             : {
     416           0 :   ErrorResult rv;
     417           0 :   DeleteRule(aIndex, *nsContentUtils::SubjectPrincipal(), rv);
     418           0 :   return rv.StealNSResult();
     419             : }
     420             : 
     421             : void
     422        3079 : StyleSheet::WillDirty()
     423             : {
     424        3079 :   if (mInner->mComplete) {
     425          14 :     EnsureUniqueInner();
     426             :   }
     427        3079 : }
     428             : 
     429             : void
     430         121 : StyleSheet::AddStyleSet(const StyleSetHandle& aStyleSet)
     431             : {
     432         121 :   NS_ASSERTION(!mStyleSets.Contains(aStyleSet),
     433             :                "style set already registered");
     434         121 :   mStyleSets.AppendElement(aStyleSet);
     435         121 : }
     436             : 
     437             : void
     438          44 : StyleSheet::DropStyleSet(const StyleSetHandle& aStyleSet)
     439             : {
     440          88 :   DebugOnly<bool> found = mStyleSets.RemoveElement(aStyleSet);
     441          44 :   NS_ASSERTION(found, "didn't find style set");
     442          44 : }
     443             : 
     444             : void
     445          14 : StyleSheet::EnsureUniqueInner()
     446             : {
     447          14 :   MOZ_ASSERT(mInner->mSheets.Length() != 0,
     448             :              "unexpected number of outers");
     449          14 :   mDirty = true;
     450             : 
     451          14 :   if (mInner->mSheets.Length() == 1) {
     452             :     // already unique
     453          14 :     return;
     454             :   }
     455             : 
     456           0 :   StyleSheetInfo* clone = mInner->CloneFor(this);
     457           0 :   MOZ_ASSERT(clone);
     458           0 :   mInner->RemoveSheet(this);
     459           0 :   mInner = clone;
     460             : 
     461           0 :   if (CSSStyleSheet* geckoSheet = GetAsGecko()) {
     462             :     // Ensure we're using the new rules.
     463             :     //
     464             :     // NOTE: In Servo, all kind of changes that change the set of selectors or
     465             :     // rules we match are covered by the PresShell notifications. In Gecko
     466             :     // that's true too, but this is probably needed because selectors are not
     467             :     // refcounted and can become stale.
     468           0 :     geckoSheet->ClearRuleCascades();
     469             :   } else {
     470             :     // Fixup the child lists and parent links in the Servo sheet. This is done
     471             :     // here instead of in StyleSheetInner::CloneFor, because it's just more
     472             :     // convenient to do so instead.
     473           0 :     AsServo()->BuildChildListAfterInnerClone();
     474             :   }
     475             : 
     476             :   // let our containing style sets know that if we call
     477             :   // nsPresContext::EnsureSafeToHandOutCSSRules we will need to restyle the
     478             :   // document
     479           0 :   for (StyleSetHandle& setHandle : mStyleSets) {
     480           0 :     setHandle->SetNeedsRestyleAfterEnsureUniqueInner();
     481             :   }
     482             : }
     483             : 
     484             : void
     485           0 : StyleSheet::AppendAllChildSheets(nsTArray<StyleSheet*>& aArray)
     486             : {
     487           0 :   for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
     488           0 :     aArray.AppendElement(child);
     489             :   }
     490           0 : }
     491             : 
     492             : // WebIDL CSSStyleSheet API
     493             : 
     494             : #define FORWARD_INTERNAL(method_, args_) \
     495             :   if (IsServo()) { \
     496             :     return AsServo()->method_ args_; \
     497             :   } \
     498             :   return AsGecko()->method_ args_;
     499             : 
     500             : dom::CSSRuleList*
     501           0 : StyleSheet::GetCssRules(nsIPrincipal& aSubjectPrincipal,
     502             :                         ErrorResult& aRv)
     503             : {
     504           0 :   if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
     505           0 :     return nullptr;
     506             :   }
     507           0 :   FORWARD_INTERNAL(GetCssRulesInternal, ())
     508             : }
     509             : 
     510             : void
     511           0 : StyleSheet::GetSourceMapURL(nsAString& aSourceMapURL)
     512             : {
     513           0 :   aSourceMapURL = mInner->mSourceMapURL;
     514           0 : }
     515             : 
     516             : void
     517           0 : StyleSheet::SetSourceMapURL(const nsAString& aSourceMapURL)
     518             : {
     519           0 :   mInner->mSourceMapURL = aSourceMapURL;
     520           0 : }
     521             : 
     522             : css::Rule*
     523           0 : StyleSheet::GetDOMOwnerRule() const
     524             : {
     525           0 :   return mOwnerRule;
     526             : }
     527             : 
     528             : uint32_t
     529           0 : StyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
     530             :                        nsIPrincipal& aSubjectPrincipal,
     531             :                        ErrorResult& aRv)
     532             : {
     533           0 :   if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
     534           0 :     return 0;
     535             :   }
     536           0 :   FORWARD_INTERNAL(InsertRuleInternal, (aRule, aIndex, aRv))
     537             : }
     538             : 
     539             : void
     540           0 : StyleSheet::DeleteRule(uint32_t aIndex,
     541             :                        nsIPrincipal& aSubjectPrincipal,
     542             :                        ErrorResult& aRv)
     543             : {
     544           0 :   if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
     545           0 :     return;
     546             :   }
     547           0 :   FORWARD_INTERNAL(DeleteRuleInternal, (aIndex, aRv))
     548             : }
     549             : 
     550             : nsresult
     551           0 : StyleSheet::DeleteRuleFromGroup(css::GroupRule* aGroup, uint32_t aIndex)
     552             : {
     553           0 :   NS_ENSURE_ARG_POINTER(aGroup);
     554           0 :   NS_ASSERTION(IsComplete(), "No deleting from an incomplete sheet!");
     555           0 :   RefPtr<css::Rule> rule = aGroup->GetStyleRuleAt(aIndex);
     556           0 :   NS_ENSURE_TRUE(rule, NS_ERROR_ILLEGAL_VALUE);
     557             : 
     558             :   // check that the rule actually belongs to this sheet!
     559           0 :   if (this != rule->GetStyleSheet()) {
     560           0 :     return NS_ERROR_INVALID_ARG;
     561             :   }
     562             : 
     563           0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     564             : 
     565           0 :   WillDirty();
     566             : 
     567           0 :   nsresult result = aGroup->DeleteStyleRuleAt(aIndex);
     568           0 :   NS_ENSURE_SUCCESS(result, result);
     569             : 
     570           0 :   rule->SetStyleSheet(nullptr);
     571             : 
     572           0 :   DidDirty();
     573             : 
     574           0 :   if (mDocument) {
     575           0 :     mDocument->StyleRuleRemoved(this, rule);
     576             :   }
     577             : 
     578           0 :   return NS_OK;
     579             : }
     580             : 
     581             : nsresult
     582           0 : StyleSheet::InsertRuleIntoGroup(const nsAString& aRule,
     583             :                                 css::GroupRule* aGroup,
     584             :                                 uint32_t aIndex)
     585             : {
     586           0 :   NS_ASSERTION(IsComplete(), "No inserting into an incomplete sheet!");
     587             :   // check that the group actually belongs to this sheet!
     588           0 :   if (this != aGroup->GetStyleSheet()) {
     589           0 :     return NS_ERROR_INVALID_ARG;
     590             :   }
     591             : 
     592             :   // parse and grab the rule
     593           0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     594             : 
     595           0 :   WillDirty();
     596             : 
     597             :   nsresult result;
     598           0 :   if (IsGecko()) {
     599           0 :     result = AsGecko()->InsertRuleIntoGroupInternal(aRule, aGroup, aIndex);
     600             :   } else {
     601           0 :     result = AsServo()->InsertRuleIntoGroupInternal(aRule, aGroup, aIndex);
     602             :   }
     603           0 :   NS_ENSURE_SUCCESS(result, result);
     604             : 
     605           0 :   DidDirty();
     606             : 
     607           0 :   if (mDocument) {
     608           0 :     mDocument->StyleRuleAdded(this, aGroup->GetStyleRuleAt(aIndex));
     609             :   }
     610             : 
     611           0 :   return NS_OK;
     612             : }
     613             : 
     614             : uint64_t
     615           0 : StyleSheet::FindOwningWindowInnerID() const
     616             : {
     617           0 :   uint64_t windowID = 0;
     618           0 :   if (mDocument) {
     619           0 :     windowID = mDocument->InnerWindowID();
     620             :   }
     621             : 
     622           0 :   if (windowID == 0 && mOwningNode) {
     623           0 :     windowID = mOwningNode->OwnerDoc()->InnerWindowID();
     624             :   }
     625             : 
     626           0 :   RefPtr<css::Rule> ownerRule;
     627           0 :   if (windowID == 0 && (ownerRule = GetDOMOwnerRule())) {
     628           0 :     RefPtr<StyleSheet> sheet = ownerRule->GetStyleSheet();
     629           0 :     if (sheet) {
     630           0 :       windowID = sheet->FindOwningWindowInnerID();
     631             :     }
     632             :   }
     633             : 
     634           0 :   if (windowID == 0 && mParent) {
     635           0 :     windowID = mParent->FindOwningWindowInnerID();
     636             :   }
     637             : 
     638           0 :   return windowID;
     639             : }
     640             : 
     641             : void
     642           0 : StyleSheet::EnabledStateChanged()
     643             : {
     644           0 :   FORWARD_INTERNAL(EnabledStateChangedInternal, ())
     645             : }
     646             : 
     647             : #undef FORWARD_INTERNAL
     648             : 
     649             : void
     650           0 : StyleSheet::UnparentChildren()
     651             : {
     652             :   // XXXbz this is a little bogus; see the XXX comment where we
     653             :   // declare mFirstChild in StyleSheetInfo.
     654           0 :   for (StyleSheet* child = GetFirstChild();
     655           0 :        child;
     656           0 :        child = child->mNext) {
     657           0 :     if (child->mParent == this) {
     658           0 :       child->mParent = nullptr;
     659           0 :       MOZ_ASSERT(child->mDocumentAssociationMode == NotOwnedByDocument,
     660             :                  "How did we get to the destructor, exactly, if we're owned "
     661             :                  "by a document?");
     662           0 :       child->mDocument = nullptr;
     663             :     }
     664             :   }
     665           0 : }
     666             : 
     667             : void
     668           0 : StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
     669             :                                           ErrorResult& aRv)
     670             : {
     671           0 :   StyleSheetInfo& info = SheetInfo();
     672             : 
     673           0 :   if (aSubjectPrincipal.Subsumes(info.mPrincipal)) {
     674           0 :     return;
     675             :   }
     676             : 
     677             :   // Allow access only if CORS mode is not NONE and the security flag
     678             :   // is not turned off.
     679           0 :   if (GetCORSMode() == CORS_NONE &&
     680           0 :       !nsContentUtils::BypassCSSOMOriginCheck()) {
     681           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     682           0 :     return;
     683             :   }
     684             : 
     685             :   // Now make sure we set the principal of our inner to the subjectPrincipal.
     686             :   // We do this because we're in a situation where the caller would not normally
     687             :   // be able to access the sheet, but the sheet has opted in to being read.
     688             :   // Unfortunately, that means it's also opted in to being _edited_, and if the
     689             :   // caller now makes edits to the sheet we want the resulting resource loads,
     690             :   // if any, to look as if they are coming from the caller's principal, not the
     691             :   // original sheet principal.
     692             :   //
     693             :   // That means we need a unique inner, of course.  But we don't want to do that
     694             :   // if we're not complete yet.  Luckily, all the callers of this method throw
     695             :   // anyway if not complete, so we can just do that here too.
     696           0 :   if (!info.mComplete) {
     697           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     698           0 :     return;
     699             :   }
     700             : 
     701           0 :   WillDirty();
     702             : 
     703           0 :   info.mPrincipal = &aSubjectPrincipal;
     704             : 
     705           0 :   DidDirty();
     706             : }
     707             : 
     708             : bool
     709           0 : StyleSheet::AreRulesAvailable(nsIPrincipal& aSubjectPrincipal,
     710             :                               ErrorResult& aRv)
     711             : {
     712             :   // Rules are not available on incomplete sheets.
     713           0 :   if (!SheetInfo().mComplete) {
     714           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     715           0 :     return false;
     716             :   }
     717             :   //-- Security check: Only scripts whose principal subsumes that of the
     718             :   //   style sheet can access rule collections.
     719           0 :   SubjectSubsumesInnerPrincipal(aSubjectPrincipal, aRv);
     720           0 :   if (NS_WARN_IF(aRv.Failed())) {
     721           0 :     return false;
     722             :   }
     723           0 :   return true;
     724             : }
     725             : 
     726             : StyleSheet*
     727          16 : StyleSheet::GetFirstChild() const
     728             : {
     729          16 :   return SheetInfo().mFirstChild;
     730             : }
     731             : 
     732             : void
     733          14 : StyleSheet::SetAssociatedDocument(nsIDocument* aDocument,
     734             :                                   DocumentAssociationMode aAssociationMode)
     735             : {
     736          14 :   MOZ_ASSERT(aDocument || aAssociationMode == NotOwnedByDocument);
     737             : 
     738             :   // not ref counted
     739          14 :   mDocument = aDocument;
     740          14 :   mDocumentAssociationMode = aAssociationMode;
     741             : 
     742             :   // Now set the same document on all our child sheets....
     743             :   // XXXbz this is a little bogus; see the XXX comment where we
     744             :   // declare mFirstChild.
     745          14 :   for (StyleSheet* child = GetFirstChild();
     746          14 :        child; child = child->mNext) {
     747           0 :     if (child->mParent == this) {
     748           0 :       child->SetAssociatedDocument(aDocument, aAssociationMode);
     749             :     }
     750             :   }
     751          14 : }
     752             : 
     753             : void
     754           0 : StyleSheet::ClearAssociatedDocument()
     755             : {
     756           0 :   SetAssociatedDocument(nullptr, NotOwnedByDocument);
     757           0 : }
     758             : 
     759             : void
     760           3 : StyleSheet::PrependStyleSheet(StyleSheet* aSheet)
     761             : {
     762           3 :   WillDirty();
     763           3 :   PrependStyleSheetSilently(aSheet);
     764           3 :   DidDirty();
     765           3 : }
     766             : 
     767             : void
     768           3 : StyleSheet::PrependStyleSheetSilently(StyleSheet* aSheet)
     769             : {
     770           3 :   MOZ_ASSERT(aSheet);
     771             : 
     772           3 :   aSheet->mNext = SheetInfo().mFirstChild;
     773           3 :   SheetInfo().mFirstChild = aSheet;
     774             : 
     775             :   // This is not reference counted. Our parent tells us when
     776             :   // it's going away.
     777           3 :   aSheet->mParent = this;
     778           3 :   aSheet->SetAssociatedDocument(mDocument, mDocumentAssociationMode);
     779           3 : }
     780             : 
     781             : size_t
     782           5 : StyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     783             : {
     784           5 :   size_t n = 0;
     785           5 :   const StyleSheet* s = this;
     786          15 :   while (s) {
     787           5 :     n += aMallocSizeOf(s);
     788             : 
     789             :     // Measurement of the following members may be added later if DMD finds it
     790             :     // is worthwhile:
     791             :     // - s->mTitle
     792             :     // - s->mMedia
     793             :     // - s->mStyleSets
     794             : 
     795           5 :     s = s->mNext;
     796             :   }
     797           5 :   return n;
     798             : }
     799             : 
     800             : #ifdef DEBUG
     801             : void
     802           0 : StyleSheet::List(FILE* out, int32_t aIndent) const
     803             : {
     804             :   int32_t index;
     805             : 
     806             :   // Indent
     807           0 :   nsAutoCString str;
     808           0 :   for (index = aIndent; --index >= 0; ) {
     809           0 :     str.AppendLiteral("  ");
     810             :   }
     811             : 
     812           0 :   str.AppendLiteral("CSS Style Sheet: ");
     813           0 :   nsAutoCString urlSpec;
     814           0 :   nsresult rv = GetSheetURI()->GetSpec(urlSpec);
     815           0 :   if (NS_SUCCEEDED(rv) && !urlSpec.IsEmpty()) {
     816           0 :     str.Append(urlSpec);
     817             :   }
     818             : 
     819           0 :   if (mMedia) {
     820           0 :     str.AppendLiteral(" media: ");
     821           0 :     nsAutoString  buffer;
     822           0 :     mMedia->GetText(buffer);
     823           0 :     AppendUTF16toUTF8(buffer, str);
     824             :   }
     825           0 :   str.Append('\n');
     826           0 :   fprintf_stderr(out, "%s", str.get());
     827             : 
     828           0 :   for (const StyleSheet* child = GetFirstChild();
     829           0 :        child;
     830           0 :        child = child->mNext) {
     831           0 :     child->List(out, aIndent + 1);
     832             :   }
     833           0 : }
     834             : #endif
     835             : 
     836             : void
     837          73 : StyleSheet::SetMedia(dom::MediaList* aMedia)
     838             : {
     839          73 :   mMedia = aMedia;
     840          73 : }
     841             : 
     842             : void
     843           0 : StyleSheet::DropMedia()
     844             : {
     845           0 :   if (mMedia) {
     846           0 :     mMedia->SetStyleSheet(nullptr);
     847           0 :     mMedia = nullptr;
     848             :   }
     849           0 : }
     850             : 
     851             : dom::MediaList*
     852           3 : StyleSheet::Media()
     853             : {
     854           3 :   if (!mMedia) {
     855           0 :     mMedia = dom::MediaList::Create(mType, nsString());
     856           0 :     mMedia->SetStyleSheet(this);
     857             :   }
     858             : 
     859           3 :   return mMedia;
     860             : }
     861             : 
     862             : // nsWrapperCache
     863             : 
     864             : JSObject*
     865           0 : StyleSheet::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     866             : {
     867           0 :   return dom::CSSStyleSheetBinding::Wrap(aCx, this, aGivenProto);
     868             : }
     869             : 
     870             : /* static */ bool
     871           0 : StyleSheet::RuleHasPendingChildSheet(css::Rule* aRule)
     872             : {
     873           0 :   MOZ_ASSERT(aRule->GetType() == css::Rule::IMPORT_RULE);
     874           0 :   auto rule = static_cast<dom::CSSImportRule*>(aRule);
     875           0 :   if (StyleSheet* childSheet = rule->GetStyleSheet()) {
     876           0 :     return !childSheet->IsComplete();
     877             :   }
     878           0 :   return false;
     879             : }
     880             : 
     881             : } // namespace mozilla

Generated by: LCOV version 1.13