LCOV - code coverage report
Current view: top level - layout/style - ServoStyleSheet.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 208 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 0.0 %
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/ServoStyleSheet.h"
       8             : 
       9             : #include "mozilla/css/Rule.h"
      10             : #include "mozilla/StyleBackendType.h"
      11             : #include "mozilla/ServoBindings.h"
      12             : #include "mozilla/ServoImportRule.h"
      13             : #include "mozilla/ServoMediaList.h"
      14             : #include "mozilla/ServoCSSRuleList.h"
      15             : #include "mozilla/css/GroupRule.h"
      16             : #include "mozilla/dom/CSSRuleList.h"
      17             : #include "mozilla/dom/MediaList.h"
      18             : #include "nsIStyleSheetLinkingElement.h"
      19             : #include "Loader.h"
      20             : 
      21             : 
      22             : #include "mozAutoDocUpdate.h"
      23             : #include "nsIDOMCSSStyleSheet.h"
      24             : 
      25             : using namespace mozilla::dom;
      26             : 
      27             : namespace mozilla {
      28             : 
      29             : // -------------------------------
      30             : // CSS Style Sheet Inner Data Container
      31             : //
      32             : 
      33           0 : ServoStyleSheetInner::ServoStyleSheetInner(CORSMode aCORSMode,
      34             :                                            ReferrerPolicy aReferrerPolicy,
      35             :                                            const SRIMetadata& aIntegrity,
      36           0 :                                            css::SheetParsingMode aParsingMode)
      37           0 :   : StyleSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
      38             : {
      39           0 :   mContents = Servo_StyleSheet_Empty(aParsingMode).Consume();
      40           0 :   mURLData = URLExtraData::Dummy();
      41           0 :   MOZ_COUNT_CTOR(ServoStyleSheetInner);
      42           0 : }
      43             : 
      44           0 : ServoStyleSheetInner::ServoStyleSheetInner(ServoStyleSheetInner& aCopy,
      45           0 :                                            ServoStyleSheet* aPrimarySheet)
      46             :   : StyleSheetInfo(aCopy, aPrimarySheet)
      47           0 :   , mURLData(aCopy.mURLData)
      48             : {
      49           0 :   MOZ_COUNT_CTOR(ServoStyleSheetInner);
      50             : 
      51             :   // Actually clone aCopy's mContents and use that as ours.
      52           0 :   mContents = Servo_StyleSheet_Clone(
      53           0 :     aCopy.mContents.get(), aPrimarySheet).Consume();
      54             : 
      55             :   // Our child list is fixed up by our parent.
      56           0 : }
      57             : 
      58             : void
      59           0 : ServoStyleSheet::BuildChildListAfterInnerClone()
      60             : {
      61           0 :   MOZ_ASSERT(Inner()->mSheets.Length() == 1, "Should've just cloned");
      62           0 :   MOZ_ASSERT(Inner()->mSheets[0] == this);
      63           0 :   MOZ_ASSERT(!Inner()->mFirstChild);
      64             : 
      65           0 :   auto* contents = Inner()->mContents.get();
      66             :   RefPtr<ServoCssRules> rules =
      67           0 :     Servo_StyleSheet_GetRules(contents).Consume();
      68             : 
      69           0 :   uint32_t index = 0;
      70             :   while (true) {
      71             :     uint32_t line, column; // Actually unused.
      72             :     RefPtr<RawServoImportRule> import =
      73           0 :       Servo_CssRules_GetImportRuleAt(rules, index, &line, &column).Consume();
      74           0 :     if (!import) {
      75             :       // Note that only @charset rules come before @import rules, and @charset
      76             :       // rules are parsed but skipped, so we can stop iterating as soon as we
      77             :       // find something that isn't an @import rule.
      78           0 :       break;
      79             :     }
      80             :     auto* sheet =
      81           0 :       const_cast<ServoStyleSheet*>(Servo_ImportRule_GetSheet(import));
      82           0 :     MOZ_ASSERT(sheet);
      83           0 :     PrependStyleSheetSilently(sheet);
      84           0 :     index++;
      85           0 :   }
      86           0 : }
      87             : 
      88             : already_AddRefed<ServoStyleSheet>
      89           0 : ServoStyleSheet::CreateEmptyChildSheet(
      90             :     already_AddRefed<dom::MediaList> aMediaList) const
      91             : {
      92             :   RefPtr<ServoStyleSheet> child =
      93             :     new ServoStyleSheet(
      94           0 :         ParsingMode(),
      95             :         CORSMode::CORS_NONE,
      96           0 :         GetReferrerPolicy(),
      97           0 :         SRIMetadata());
      98             : 
      99           0 :   child->mMedia = aMediaList;
     100           0 :   return child.forget();
     101             : }
     102             : 
     103             : 
     104           0 : ServoStyleSheetInner::~ServoStyleSheetInner()
     105             : {
     106           0 :   MOZ_COUNT_DTOR(ServoStyleSheetInner);
     107           0 : }
     108             : 
     109             : StyleSheetInfo*
     110           0 : ServoStyleSheetInner::CloneFor(StyleSheet* aPrimarySheet)
     111             : {
     112             :   return new ServoStyleSheetInner(*this,
     113           0 :                                   static_cast<ServoStyleSheet*>(aPrimarySheet));
     114             : }
     115             : 
     116           0 : MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleSheetMallocSizeOf)
     117             : 
     118             : size_t
     119           0 : ServoStyleSheetInner::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     120             : {
     121           0 :   size_t n = aMallocSizeOf(this);
     122           0 :   n += Servo_StyleSheet_SizeOfIncludingThis(
     123             :       ServoStyleSheetMallocSizeOf, mContents);
     124           0 :   return n;
     125             : }
     126             : 
     127           0 : ServoStyleSheet::ServoStyleSheet(css::SheetParsingMode aParsingMode,
     128             :                                  CORSMode aCORSMode,
     129             :                                  net::ReferrerPolicy aReferrerPolicy,
     130           0 :                                  const dom::SRIMetadata& aIntegrity)
     131           0 :   : StyleSheet(StyleBackendType::Servo, aParsingMode)
     132             : {
     133           0 :   mInner = new ServoStyleSheetInner(
     134           0 :     aCORSMode, aReferrerPolicy, aIntegrity, aParsingMode);
     135           0 :   mInner->AddSheet(this);
     136           0 : }
     137             : 
     138           0 : ServoStyleSheet::ServoStyleSheet(const ServoStyleSheet& aCopy,
     139             :                                  ServoStyleSheet* aParentToUse,
     140             :                                  dom::CSSImportRule* aOwnerRuleToUse,
     141             :                                  nsIDocument* aDocumentToUse,
     142           0 :                                  nsINode* aOwningNodeToUse)
     143             :   : StyleSheet(aCopy,
     144             :                aParentToUse,
     145             :                aOwnerRuleToUse,
     146             :                aDocumentToUse,
     147           0 :                aOwningNodeToUse)
     148             : {
     149           0 :   if (mDirty) { // CSSOM's been there, force full copy now
     150           0 :     NS_ASSERTION(mInner->mComplete,
     151             :                  "Why have rules been accessed on an incomplete sheet?");
     152             :     // FIXME: handle failure?
     153             :     //
     154             :     // NOTE: It's important to call this from the subclass, since this could
     155             :     // access uninitialized members otherwise.
     156           0 :     EnsureUniqueInner();
     157             :   }
     158           0 : }
     159             : 
     160           0 : ServoStyleSheet::~ServoStyleSheet()
     161             : {
     162           0 : }
     163             : 
     164             : void
     165           0 : ServoStyleSheet::LastRelease()
     166             : {
     167           0 :   DropRuleList();
     168           0 : }
     169             : 
     170             : // QueryInterface implementation for ServoStyleSheet
     171           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoStyleSheet)
     172           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCSSStyleSheet)
     173           0 :   if (aIID.Equals(NS_GET_IID(ServoStyleSheet)))
     174           0 :     foundInterface = reinterpret_cast<nsISupports*>(this);
     175             :   else
     176           0 : NS_INTERFACE_MAP_END_INHERITING(StyleSheet)
     177             : 
     178           0 : NS_IMPL_ADDREF_INHERITED(ServoStyleSheet, StyleSheet)
     179           0 : NS_IMPL_RELEASE_INHERITED(ServoStyleSheet, StyleSheet)
     180             : 
     181             : NS_IMPL_CYCLE_COLLECTION_CLASS(ServoStyleSheet)
     182             : 
     183           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoStyleSheet)
     184           0 :   tmp->DropRuleList();
     185           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(StyleSheet)
     186           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoStyleSheet, StyleSheet)
     187           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleList)
     188           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     189             : 
     190             : bool
     191           0 : ServoStyleSheet::HasRules() const
     192             : {
     193           0 :   return Servo_StyleSheet_HasRules(Inner()->mContents);
     194             : }
     195             : 
     196             : nsresult
     197           0 : ServoStyleSheet::ParseSheet(css::Loader* aLoader,
     198             :                             const nsAString& aInput,
     199             :                             nsIURI* aSheetURI,
     200             :                             nsIURI* aBaseURI,
     201             :                             nsIPrincipal* aSheetPrincipal,
     202             :                             uint32_t aLineNumber,
     203             :                             nsCompatibility aCompatMode,
     204             :                             css::LoaderReusableStyleSheets* aReusableSheets)
     205             : {
     206           0 :   MOZ_ASSERT(!mMedia || mMedia->IsServo());
     207             :   RefPtr<URLExtraData> extraData =
     208           0 :     new URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal);
     209             : 
     210           0 :   NS_ConvertUTF16toUTF8 input(aInput);
     211           0 :   Inner()->mContents =
     212           0 :     Servo_StyleSheet_FromUTF8Bytes(
     213           0 :         aLoader, this, &input, mParsingMode, extraData,
     214             :         aLineNumber, aCompatMode
     215           0 :     ).Consume();
     216             : 
     217           0 :   Inner()->mURLData = extraData.forget();
     218           0 :   return NS_OK;
     219             : }
     220             : 
     221             : nsresult
     222           0 : ServoStyleSheet::ReparseSheet(const nsAString& aInput)
     223             : {
     224           0 :   if (!mInner->mComplete) {
     225           0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
     226             :   }
     227             : 
     228             :   // Hold strong ref to the CSSLoader in case the document update
     229             :   // kills the document
     230           0 :   RefPtr<css::Loader> loader;
     231           0 :   if (mDocument) {
     232           0 :     loader = mDocument->CSSLoader();
     233           0 :     NS_ASSERTION(loader, "Document with no CSS loader!");
     234             :   } else {
     235           0 :     loader = new css::Loader(StyleBackendType::Servo, nullptr);
     236             :   }
     237             : 
     238           0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     239             : 
     240           0 :   WillDirty();
     241             : 
     242             :   // cache child sheets to reuse
     243           0 :   css::LoaderReusableStyleSheets reusableSheets;
     244           0 :   for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
     245           0 :     if (child->GetOriginalURI()) {
     246           0 :       reusableSheets.AddReusableSheet(child);
     247             :     }
     248             :   }
     249             : 
     250             :   // clean up child sheets list
     251           0 :   for (StyleSheet* child = GetFirstChild(); child; ) {
     252           0 :     StyleSheet* next = child->mNext;
     253           0 :     child->mParent = nullptr;
     254           0 :     child->SetAssociatedDocument(nullptr, NotOwnedByDocument);
     255           0 :     child->mNext = nullptr;
     256           0 :     child = next;
     257             :   }
     258           0 :   Inner()->mFirstChild = nullptr;
     259             : 
     260           0 :   uint32_t lineNumber = 1;
     261           0 :   if (mOwningNode) {
     262           0 :     nsCOMPtr<nsIStyleSheetLinkingElement> link = do_QueryInterface(mOwningNode);
     263           0 :     if (link) {
     264           0 :       lineNumber = link->GetLineNumber();
     265             :     }
     266             :   }
     267             : 
     268             :   // Notify mDocument that all our rules are removed.
     269           0 :   if (mDocument) {
     270             :     // Get the rule list.
     271           0 :     ServoCSSRuleList* ruleList = GetCssRulesInternal();
     272           0 :     MOZ_ASSERT(ruleList);
     273             : 
     274           0 :     uint32_t ruleCount = ruleList->Length();
     275           0 :     for (uint32_t i = 0; i < ruleCount; ++i) {
     276           0 :       css::Rule* rule = ruleList->GetRule(i);
     277           0 :       MOZ_ASSERT(rule);
     278           0 :       if (rule->GetType() == css::Rule::IMPORT_RULE &&
     279           0 :           RuleHasPendingChildSheet(rule)) {
     280           0 :         continue; // notify when loaded (see StyleSheetLoaded)
     281             :       }
     282           0 :       mDocument->StyleRuleRemoved(this, rule);
     283             : 
     284             :       // Document observers could possibly detach document from this sheet.
     285           0 :       if (!mDocument) {
     286             :         // If detached, don't process any more rules.
     287           0 :         break;
     288             :       }
     289             :     }
     290             :   }
     291             : 
     292           0 :   DropRuleList();
     293             : 
     294           0 :   nsresult rv = ParseSheet(loader, aInput, mInner->mSheetURI, mInner->mBaseURI,
     295           0 :                            mInner->mPrincipal, lineNumber,
     296           0 :                            eCompatibility_FullStandards, &reusableSheets);
     297           0 :   DidDirty();
     298           0 :   NS_ENSURE_SUCCESS(rv, rv);
     299             : 
     300             :   // Notify mDocument that all our new rules are added.
     301           0 :   if (mDocument) {
     302             :     // Get the rule list (which will need to be regenerated after ParseSheet).
     303           0 :     ServoCSSRuleList* ruleList = GetCssRulesInternal();
     304           0 :     MOZ_ASSERT(ruleList);
     305             : 
     306           0 :     uint32_t ruleCount = ruleList->Length();
     307           0 :     for (uint32_t i = 0; i < ruleCount; ++i) {
     308           0 :       css::Rule* rule = ruleList->GetRule(i);
     309           0 :       MOZ_ASSERT(rule);
     310           0 :       if (rule->GetType() == css::Rule::IMPORT_RULE &&
     311           0 :           RuleHasPendingChildSheet(rule)) {
     312           0 :         continue; // notify when loaded (see StyleSheetLoaded)
     313             :       }
     314             : 
     315           0 :       mDocument->StyleRuleAdded(this, rule);
     316             : 
     317             :       // Document observers could possibly detach document from this sheet.
     318           0 :       if (!mDocument) {
     319             :         // If detached, don't process any more rules.
     320           0 :         break;
     321             :       }
     322             :     }
     323             :   }
     324             : 
     325           0 :   return NS_OK;
     326             : }
     327             : 
     328             : // nsICSSLoaderObserver implementation
     329             : NS_IMETHODIMP
     330           0 : ServoStyleSheet::StyleSheetLoaded(StyleSheet* aSheet,
     331             :                                   bool aWasAlternate,
     332             :                                   nsresult aStatus)
     333             : {
     334           0 :   MOZ_ASSERT(aSheet->IsServo(),
     335             :              "why we were called back with a CSSStyleSheet?");
     336             : 
     337           0 :   ServoStyleSheet* sheet = aSheet->AsServo();
     338           0 :   if (sheet->GetParentSheet() == nullptr) {
     339           0 :     return NS_OK; // ignore if sheet has been detached already
     340             :   }
     341           0 :   NS_ASSERTION(this == sheet->GetParentSheet(),
     342             :                "We are being notified of a sheet load for a sheet that is not our child!");
     343             : 
     344           0 :   if (mDocument && NS_SUCCEEDED(aStatus)) {
     345           0 :     mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     346           0 :     mDocument->StyleRuleAdded(this, sheet->GetOwnerRule());
     347             :   }
     348             : 
     349           0 :   return NS_OK;
     350             : }
     351             : 
     352             : void
     353           0 : ServoStyleSheet::DropRuleList()
     354             : {
     355           0 :   if (mRuleList) {
     356           0 :     mRuleList->DropReference();
     357           0 :     mRuleList = nullptr;
     358             :   }
     359           0 : }
     360             : 
     361             : already_AddRefed<StyleSheet>
     362           0 : ServoStyleSheet::Clone(StyleSheet* aCloneParent,
     363             :                        dom::CSSImportRule* aCloneOwnerRule,
     364             :                        nsIDocument* aCloneDocument,
     365             :                        nsINode* aCloneOwningNode) const
     366             : {
     367             :   RefPtr<StyleSheet> clone = new ServoStyleSheet(*this,
     368             :     static_cast<ServoStyleSheet*>(aCloneParent),
     369             :     aCloneOwnerRule,
     370             :     aCloneDocument,
     371           0 :     aCloneOwningNode);
     372           0 :   return clone.forget();
     373             : }
     374             : 
     375             : ServoCSSRuleList*
     376           0 : ServoStyleSheet::GetCssRulesInternal()
     377             : {
     378           0 :   if (!mRuleList) {
     379           0 :     EnsureUniqueInner();
     380             : 
     381             :     RefPtr<ServoCssRules> rawRules =
     382           0 :       Servo_StyleSheet_GetRules(Inner()->mContents).Consume();
     383           0 :     MOZ_ASSERT(rawRules);
     384           0 :     mRuleList = new ServoCSSRuleList(rawRules.forget(), this);
     385             :   }
     386           0 :   return mRuleList;
     387             : }
     388             : 
     389             : uint32_t
     390           0 : ServoStyleSheet::InsertRuleInternal(const nsAString& aRule,
     391             :                                     uint32_t aIndex, ErrorResult& aRv)
     392             : {
     393             :   // Ensure mRuleList is constructed.
     394           0 :   GetCssRulesInternal();
     395             : 
     396           0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     397           0 :   aRv = mRuleList->InsertRule(aRule, aIndex);
     398           0 :   if (aRv.Failed()) {
     399           0 :     return 0;
     400             :   }
     401           0 :   if (mDocument) {
     402           0 :     if (mRuleList->GetRuleType(aIndex) != css::Rule::IMPORT_RULE ||
     403           0 :         !RuleHasPendingChildSheet(mRuleList->GetRule(aIndex))) {
     404             :       // XXX We may not want to get the rule when stylesheet change event
     405             :       // is not enabled.
     406           0 :       mDocument->StyleRuleAdded(this, mRuleList->GetRule(aIndex));
     407             :     }
     408             :   }
     409           0 :   return aIndex;
     410             : }
     411             : 
     412             : void
     413           0 : ServoStyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv)
     414             : {
     415             :   // Ensure mRuleList is constructed.
     416           0 :   GetCssRulesInternal();
     417           0 :   if (aIndex > mRuleList->Length()) {
     418           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     419           0 :     return;
     420             :   }
     421             : 
     422           0 :   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
     423             :   // Hold a strong ref to the rule so it doesn't die when we remove it
     424             :   // from the list. XXX We may not want to hold it if stylesheet change
     425             :   // event is not enabled.
     426           0 :   RefPtr<css::Rule> rule = mRuleList->GetRule(aIndex);
     427           0 :   aRv = mRuleList->DeleteRule(aIndex);
     428           0 :   MOZ_ASSERT(!aRv.ErrorCodeIs(NS_ERROR_DOM_INDEX_SIZE_ERR),
     429             :              "IndexSizeError should have been handled earlier");
     430           0 :   if (!aRv.Failed() && mDocument) {
     431           0 :     mDocument->StyleRuleRemoved(this, rule);
     432             :   }
     433             : }
     434             : 
     435             : nsresult
     436           0 : ServoStyleSheet::InsertRuleIntoGroupInternal(const nsAString& aRule,
     437             :                                              css::GroupRule* aGroup,
     438             :                                              uint32_t aIndex)
     439             : {
     440           0 :   auto rules = static_cast<ServoCSSRuleList*>(aGroup->CssRules());
     441           0 :   MOZ_ASSERT(rules->GetParentRule() == aGroup);
     442           0 :   return rules->InsertRule(aRule, aIndex);
     443             : }
     444             : 
     445             : size_t
     446           0 : ServoStyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     447             : {
     448           0 :   size_t n = StyleSheet::SizeOfIncludingThis(aMallocSizeOf);
     449           0 :   const ServoStyleSheet* s = this;
     450           0 :   while (s) {
     451             :     // See the comment in CSSStyleSheet::SizeOfIncludingThis() for an
     452             :     // explanation of this.
     453           0 :     if (s->Inner()->mSheets.LastElement() == s) {
     454           0 :       n += s->Inner()->SizeOfIncludingThis(aMallocSizeOf);
     455             :     }
     456             : 
     457             :     // Measurement of the following members may be added later if DMD finds it
     458             :     // is worthwhile:
     459             :     // - s->mRuleList
     460             : 
     461           0 :     s = s->mNext ? s->mNext->AsServo() : nullptr;
     462             :   }
     463           0 :   return n;
     464             : }
     465             : 
     466             : } // namespace mozilla

Generated by: LCOV version 1.13