LCOV - code coverage report
Current view: top level - dom/xbl - nsXBLResourceLoader.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 67 134 50.0 %
Date: 2017-07-14 16:53:18 Functions: 8 17 47.1 %
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 "nsTArray.h"
       8             : #include "nsString.h"
       9             : #include "nsIStyleRuleProcessor.h"
      10             : #include "nsIDocument.h"
      11             : #include "nsIContent.h"
      12             : #include "nsIPresShell.h"
      13             : #include "nsXBLService.h"
      14             : #include "nsIServiceManager.h"
      15             : #include "nsXBLResourceLoader.h"
      16             : #include "nsXBLPrototypeResources.h"
      17             : #include "nsIDocumentObserver.h"
      18             : #include "imgILoader.h"
      19             : #include "imgRequestProxy.h"
      20             : #include "mozilla/StyleSheet.h"
      21             : #include "mozilla/StyleSheetInlines.h"
      22             : #include "mozilla/css/Loader.h"
      23             : #include "nsIURI.h"
      24             : #include "nsNetUtil.h"
      25             : #include "nsGkAtoms.h"
      26             : #include "nsFrameManager.h"
      27             : #include "nsStyleContext.h"
      28             : #include "nsXBLPrototypeBinding.h"
      29             : #include "nsCSSRuleProcessor.h"
      30             : #include "nsContentUtils.h"
      31             : #include "nsStyleSet.h"
      32             : #include "nsIScriptSecurityManager.h"
      33             : 
      34             : using namespace mozilla;
      35             : 
      36           0 : NS_IMPL_CYCLE_COLLECTION(nsXBLResourceLoader, mBoundElements)
      37             : 
      38          30 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLResourceLoader)
      39           0 :   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
      40           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      41           0 : NS_INTERFACE_MAP_END
      42             : 
      43          30 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLResourceLoader)
      44           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLResourceLoader)
      45             : 
      46             : struct nsXBLResource
      47             : {
      48             :   nsXBLResource* mNext;
      49             :   nsIAtom* mType;
      50             :   nsString mSrc;
      51             : 
      52          39 :   nsXBLResource(nsIAtom* aType, const nsAString& aSrc)
      53          39 :   {
      54          39 :     MOZ_COUNT_CTOR(nsXBLResource);
      55          39 :     mNext = nullptr;
      56          39 :     mType = aType;
      57          39 :     mSrc = aSrc;
      58          39 :   }
      59             : 
      60          32 :   ~nsXBLResource()
      61          32 :   {
      62          32 :     MOZ_COUNT_DTOR(nsXBLResource);
      63          41 :     NS_CONTENT_DELETE_LIST_MEMBER(nsXBLResource, this, mNext);
      64          32 :   }
      65             : };
      66             : 
      67          30 : nsXBLResourceLoader::nsXBLResourceLoader(nsXBLPrototypeBinding* aBinding,
      68          30 :                                          nsXBLPrototypeResources* aResources)
      69             : :mBinding(aBinding),
      70             :  mResources(aResources),
      71             :  mResourceList(nullptr),
      72             :  mLastResource(nullptr),
      73             :  mLoadingResources(false),
      74             :  mInLoadResourcesFunc(false),
      75          30 :  mPendingSheets(0)
      76             : {
      77          30 : }
      78             : 
      79           0 : nsXBLResourceLoader::~nsXBLResourceLoader()
      80             : {
      81           0 :   delete mResourceList;
      82           0 : }
      83             : 
      84             : bool
      85         164 : nsXBLResourceLoader::LoadResources(nsIContent* aBoundElement)
      86             : {
      87         164 :   mInLoadResourcesFunc = true;
      88             : 
      89         164 :   if (mLoadingResources) {
      90         141 :     mInLoadResourcesFunc = false;
      91         141 :     return mPendingSheets == 0;
      92             :   }
      93             : 
      94          23 :   mLoadingResources = true;
      95             : 
      96             :   // Declare our loaders.
      97          46 :   nsCOMPtr<nsIDocument> doc = mBinding->XBLDocumentInfo()->GetDocument();
      98          23 :   mBoundDocument = aBoundElement->OwnerDoc();
      99             : 
     100          23 :   mozilla::css::Loader* cssLoader = doc->CSSLoader();
     101          23 :   MOZ_ASSERT(cssLoader->GetDocument() &&
     102             :              cssLoader->GetDocument()->GetStyleBackendType()
     103             :                == mBoundDocument->GetStyleBackendType(),
     104             :              "The style backends of the loader and bound document are mismatched!");
     105             : 
     106          23 :   nsIURI *docURL = doc->GetDocumentURI();
     107          23 :   nsIPrincipal* docPrincipal = doc->NodePrincipal();
     108             : 
     109          46 :   nsCOMPtr<nsIURI> url;
     110             : 
     111          55 :   for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
     112          32 :     if (curr->mSrc.IsEmpty())
     113           0 :       continue;
     114             : 
     115          32 :     if (NS_FAILED(NS_NewURI(getter_AddRefs(url), curr->mSrc,
     116             :                             doc->GetDocumentCharacterSet(), docURL)))
     117           0 :       continue;
     118             : 
     119          32 :     if (curr->mType == nsGkAtoms::image) {
     120             :       // Now kick off the image load...
     121             :       // Passing nullptr for pretty much everything -- cause we don't care!
     122             :       // XXX: initialDocumentURI is nullptr!
     123           0 :       RefPtr<imgRequestProxy> req;
     124           0 :       nsContentUtils::LoadImage(url, doc, doc, docPrincipal, docURL,
     125             :                                 doc->GetReferrerPolicy(), nullptr,
     126           0 :                                 nsIRequest::LOAD_BACKGROUND, EmptyString(),
     127           0 :                                 getter_AddRefs(req));
     128             :     }
     129          32 :     else if (curr->mType == nsGkAtoms::stylesheet) {
     130             :       // Kick off the load of the stylesheet.
     131             : 
     132             :       // Always load chrome synchronously
     133             :       // XXXbz should that still do a content policy check?
     134             :       bool chrome;
     135             :       nsresult rv;
     136          32 :       if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
     137             :       {
     138          32 :         rv = nsContentUtils::GetSecurityManager()->
     139          32 :           CheckLoadURIWithPrincipal(docPrincipal, url,
     140          64 :                                     nsIScriptSecurityManager::ALLOW_CHROME);
     141          32 :         if (NS_SUCCEEDED(rv)) {
     142          64 :           RefPtr<StyleSheet> sheet;
     143          32 :           rv = cssLoader->LoadSheetSync(url, &sheet);
     144          32 :           NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
     145          32 :           if (NS_SUCCEEDED(rv))
     146             :           {
     147          32 :             rv = StyleSheetLoaded(sheet, false, NS_OK);
     148          32 :             NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
     149             :           }
     150             :         }
     151             :       }
     152             :       else
     153             :       {
     154           0 :         rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this);
     155           0 :         if (NS_SUCCEEDED(rv))
     156           0 :           ++mPendingSheets;
     157             :       }
     158             :     }
     159             :   }
     160             : 
     161          23 :   mInLoadResourcesFunc = false;
     162             : 
     163             :   // Destroy our resource list.
     164          23 :   delete mResourceList;
     165          23 :   mResourceList = nullptr;
     166             : 
     167          23 :   return mPendingSheets == 0;
     168             : }
     169             : 
     170             : // nsICSSLoaderObserver
     171             : NS_IMETHODIMP
     172          32 : nsXBLResourceLoader::StyleSheetLoaded(StyleSheet* aSheet,
     173             :                                       bool aWasAlternate,
     174             :                                       nsresult aStatus)
     175             : {
     176          32 :   if (!mResources) {
     177             :     // Our resources got destroyed -- just bail out
     178           0 :     return NS_OK;
     179             :   }
     180             : 
     181          32 :   mResources->AppendStyleSheet(aSheet);
     182             : 
     183          32 :   if (!mInLoadResourcesFunc)
     184           0 :     mPendingSheets--;
     185             : 
     186          32 :   if (mPendingSheets == 0) {
     187             :     // All stylesheets are loaded.
     188          32 :     if (aSheet->IsGecko()) {
     189          32 :       mResources->GatherRuleProcessor();
     190             :     } else {
     191           0 :       mResources->ComputeServoStyleSet(
     192           0 :         mBoundDocument->GetShell()->GetPresContext());
     193             :     }
     194             : 
     195             :     // XXX Check for mPendingScripts when scripts also come online.
     196          32 :     if (!mInLoadResourcesFunc)
     197           0 :       NotifyBoundElements();
     198             :   }
     199          32 :   return NS_OK;
     200             : }
     201             : 
     202             : void
     203          39 : nsXBLResourceLoader::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
     204             : {
     205          39 :   nsXBLResource* res = new nsXBLResource(aResourceType, aSrc);
     206          39 :   if (!mResourceList)
     207          30 :     mResourceList = res;
     208             :   else
     209           9 :     mLastResource->mNext = res;
     210             : 
     211          39 :   mLastResource = res;
     212          39 : }
     213             : 
     214             : void
     215           0 : nsXBLResourceLoader::AddResourceListener(nsIContent* aBoundElement)
     216             : {
     217           0 :   if (aBoundElement) {
     218           0 :     mBoundElements.AppendObject(aBoundElement);
     219             :   }
     220           0 : }
     221             : 
     222             : void
     223           0 : nsXBLResourceLoader::NotifyBoundElements()
     224             : {
     225           0 :   nsXBLService* xblService = nsXBLService::GetInstance();
     226           0 :   if (!xblService)
     227           0 :     return;
     228             : 
     229           0 :   nsIURI* bindingURI = mBinding->BindingURI();
     230             : 
     231           0 :   uint32_t eltCount = mBoundElements.Count();
     232           0 :   for (uint32_t j = 0; j < eltCount; j++) {
     233           0 :     nsCOMPtr<nsIContent> content = mBoundElements.ObjectAt(j);
     234           0 :     MOZ_ASSERT(content->IsElement());
     235             : 
     236           0 :     bool ready = false;
     237           0 :     xblService->BindingReady(content, bindingURI, &ready);
     238             : 
     239           0 :     if (ready) {
     240             :       // We need the document to flush out frame construction and
     241             :       // such, so we want to use the current document.
     242           0 :       nsIDocument* doc = content->GetUncomposedDoc();
     243             : 
     244           0 :       if (doc) {
     245             :         // Flush first to make sure we can get the frame for content
     246           0 :         doc->FlushPendingNotifications(FlushType::Frames);
     247             : 
     248             :         // If |content| is (in addition to having binding |mBinding|)
     249             :         // also a descendant of another element with binding |mBinding|,
     250             :         // then we might have just constructed it due to the
     251             :         // notification of its parent.  (We can know about both if the
     252             :         // binding loads were triggered from the DOM rather than frame
     253             :         // construction.)  So we have to check both whether the element
     254             :         // has a primary frame and whether it's in the undisplayed map
     255             :         // before sending a ContentInserted notification, or bad things
     256             :         // will happen.
     257           0 :         nsIPresShell *shell = doc->GetShell();
     258           0 :         if (shell) {
     259           0 :           nsIFrame* childFrame = content->GetPrimaryFrame();
     260           0 :           if (!childFrame) {
     261             :             // Check to see if it's in the undisplayed content map, or the
     262             :             // display: contents map.
     263             :             nsStyleContext* sc =
     264           0 :               shell->FrameManager()->GetUndisplayedContent(content);
     265             : 
     266           0 :             if (!sc) {
     267           0 :               sc = shell->FrameManager()->GetDisplayContentsStyleFor(content);
     268             :             }
     269             : 
     270           0 :             if (!sc) {
     271           0 :               if (shell->StyleSet()->IsServo()) {
     272             :                 // Ensure the element has servo data so that
     273             :                 // nsChangeHint_ReconstructFrame posted by
     274             :                 // PostRecreateFramesFor() is recognized.
     275           0 :                 shell->StyleSet()->GetAsServo()->StyleNewlyBoundElement(
     276           0 :                   content->AsElement());
     277             :               }
     278           0 :               shell->PostRecreateFramesFor(content->AsElement());
     279             :             }
     280             :           }
     281             :         }
     282             : 
     283             :         // Flush again
     284             :         // XXXbz why is this needed?
     285           0 :         doc->FlushPendingNotifications(FlushType::ContentAndNotify);
     286             :       }
     287             :     }
     288             :   }
     289             : 
     290             :   // Clear out the whole array.
     291           0 :   mBoundElements.Clear();
     292             : 
     293             :   // Delete ourselves.
     294           0 :   mResources->ClearLoader();
     295             : }
     296             : 
     297             : nsresult
     298           0 : nsXBLResourceLoader::Write(nsIObjectOutputStream* aStream)
     299             : {
     300             :   nsresult rv;
     301             : 
     302           0 :   for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
     303           0 :     if (curr->mType == nsGkAtoms::image)
     304           0 :       rv = aStream->Write8(XBLBinding_Serialize_Image);
     305           0 :     else if (curr->mType == nsGkAtoms::stylesheet)
     306           0 :       rv = aStream->Write8(XBLBinding_Serialize_Stylesheet);
     307             :     else
     308           0 :       continue;
     309             : 
     310           0 :     NS_ENSURE_SUCCESS(rv, rv);
     311             : 
     312           0 :     rv = aStream->WriteWStringZ(curr->mSrc.get());
     313           0 :     NS_ENSURE_SUCCESS(rv, rv);
     314             :   }
     315             : 
     316           0 :   return NS_OK;
     317             : }

Generated by: LCOV version 1.13