LCOV - code coverage report
Current view: top level - dom/xbl - nsXBLDocumentInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 83 156 53.2 %
Date: 2017-07-14 16:53:18 Functions: 11 20 55.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/DebugOnly.h"
       8             : 
       9             : #include "nsXBLDocumentInfo.h"
      10             : #include "nsIDocument.h"
      11             : #include "nsXBLPrototypeBinding.h"
      12             : #include "nsIScriptObjectPrincipal.h"
      13             : #include "nsIScriptContext.h"
      14             : #include "nsIDOMDocument.h"
      15             : #include "jsapi.h"
      16             : #include "jsfriendapi.h"
      17             : #include "nsIURI.h"
      18             : #include "nsIConsoleService.h"
      19             : #include "nsIScriptError.h"
      20             : #include "nsIChromeRegistry.h"
      21             : #include "nsIPrincipal.h"
      22             : #include "nsJSPrincipals.h"
      23             : #include "nsIScriptSecurityManager.h"
      24             : #include "nsContentUtils.h"
      25             : #include "nsDOMJSUtils.h"
      26             : #include "mozilla/Services.h"
      27             : #include "xpcpublic.h"
      28             : #include "mozilla/scache/StartupCache.h"
      29             : #include "mozilla/scache/StartupCacheUtils.h"
      30             : #include "nsCCUncollectableMarker.h"
      31             : #include "mozilla/dom/BindingUtils.h"
      32             : #include "mozilla/dom/URL.h"
      33             : 
      34             : using namespace mozilla;
      35             : using namespace mozilla::scache;
      36             : using namespace mozilla::dom;
      37             : 
      38             : static const char kXBLCachePrefix[] = "xblcache";
      39             : 
      40             : /* Implementation file */
      41             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
      42             : 
      43           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
      44           0 :   if (tmp->mBindingTable) {
      45           0 :     for (auto iter = tmp->mBindingTable->ConstIter();
      46           0 :          !iter.Done(); iter.Next()) {
      47           0 :       iter.UserData()->Unlink();
      48             :     }
      49             :   }
      50           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
      51           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      52           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
      53           0 :   if (tmp->mDocument &&
      54           0 :       nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) {
      55           0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
      56             :   }
      57           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
      58           0 :   if (tmp->mBindingTable) {
      59           0 :     for (auto iter = tmp->mBindingTable->ConstIter();
      60           0 :          !iter.Done(); iter.Next()) {
      61           0 :       iter.UserData()->Traverse(cb);
      62             :     }
      63             :   }
      64           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      65          25 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
      66          25 :   if (tmp->mBindingTable) {
      67         334 :     for (auto iter = tmp->mBindingTable->ConstIter();
      68         309 :          !iter.Done(); iter.Next()) {
      69         142 :       iter.UserData()->Trace(aCallbacks, aClosure);
      70             :     }
      71             :   }
      72          25 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      73             : 
      74             : static void
      75           0 : UnmarkXBLJSObject(JS::GCCellPtr aPtr, const char* aName, void* aClosure)
      76             : {
      77           0 :   JS::ExposeObjectToActiveJS(&aPtr.as<JSObject>());
      78           0 : }
      79             : 
      80             : void
      81           0 : nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration)
      82             : {
      83           0 :   if (mDocument) {
      84           0 :     mDocument->MarkUncollectableForCCGeneration(aGeneration);
      85             :   }
      86             :   // Unmark any JS we hold
      87           0 :   if (mBindingTable) {
      88           0 :     for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
      89           0 :       iter.UserData()->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr);
      90             :     }
      91             :   }
      92           0 : }
      93             : 
      94         128 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
      95           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      96           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      97           0 : NS_INTERFACE_MAP_END
      98             : 
      99        2012 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
     100        1279 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocumentInfo)
     101             : 
     102          26 : nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
     103             :   : mDocument(aDocument),
     104             :     mScriptAccess(true),
     105             :     mIsChrome(false),
     106          26 :     mFirstBinding(nullptr)
     107             : {
     108          26 :   nsIURI* uri = aDocument->GetDocumentURI();
     109          26 :   if (IsChromeURI(uri)) {
     110             :     // Cache whether or not this chrome XBL can execute scripts.
     111             :     nsCOMPtr<nsIXULChromeRegistry> reg =
     112          52 :       mozilla::services::GetXULChromeRegistryService();
     113          26 :     if (reg) {
     114          26 :       bool allow = true;
     115          26 :       reg->AllowScriptsForPackage(uri, &allow);
     116          26 :       mScriptAccess = allow;
     117             :     }
     118          26 :     mIsChrome = true;
     119             :   } else {
     120             :     // If this binding isn't running with system principal, then it's running
     121             :     // from a remote-XUL whitelisted domain. This is already a not-really-
     122             :     // supported configuration (among other things, we don't use XBL scopes in
     123             :     // that configuration for compatibility reasons). But we should still at
     124             :     // least make an effort to prevent binding code from running if content
     125             :     // script is disabled or if the source domain is blacklisted (since the
     126             :     // source domain for remote XBL must always be the same as the source domain
     127             :     // of the bound content).
     128             :     //
     129             :     // If we just ask the binding document if script is enabled, it will
     130             :     // discover that it has no inner window, and return false. So instead, we
     131             :     // short-circuit the normal compartment-managed script-disabling machinery,
     132             :     // and query the policy for the URI directly.
     133             :     bool allow;
     134           0 :     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
     135           0 :     nsresult rv = ssm->PolicyAllowsScript(uri, &allow);
     136           0 :     mScriptAccess = NS_SUCCEEDED(rv) && allow;
     137             :   }
     138          26 : }
     139             : 
     140           0 : nsXBLDocumentInfo::~nsXBLDocumentInfo()
     141             : {
     142           0 :   mozilla::DropJSObjects(this);
     143           0 : }
     144             : 
     145             : nsXBLPrototypeBinding*
     146         633 : nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef)
     147             : {
     148         633 :   if (!mBindingTable)
     149           0 :     return nullptr;
     150             : 
     151         633 :   if (aRef.IsEmpty()) {
     152             :     // Return our first binding
     153           0 :     return mFirstBinding;
     154             :   }
     155             : 
     156         633 :   return mBindingTable->Get(aRef);
     157             : }
     158             : 
     159             : nsresult
     160         145 : nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
     161             : {
     162         145 :   if (!mBindingTable) {
     163          26 :     mBindingTable = new nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>();
     164          26 :     mozilla::HoldJSObjects(this);
     165             :   }
     166             : 
     167         145 :   NS_ENSURE_STATE(!mBindingTable->Get(aRef));
     168         145 :   mBindingTable->Put(aRef, aBinding);
     169             : 
     170         145 :   return NS_OK;
     171             : }
     172             : 
     173             : void
     174           0 : nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef)
     175             : {
     176           0 :   if (mBindingTable) {
     177           0 :     nsAutoPtr<nsXBLPrototypeBinding> bindingToRemove;
     178           0 :     mBindingTable->Remove(aRef, &bindingToRemove);
     179             : 
     180             :     // We do not want to destroy the binding, so just forget it.
     181           0 :     bindingToRemove.forget();
     182             :   }
     183           0 : }
     184             : 
     185             : // static
     186             : nsresult
     187          26 : nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo,
     188             :                                          nsIDocument* aBoundDocument)
     189             : {
     190          26 :   *aDocInfo = nullptr;
     191             : 
     192          52 :   nsAutoCString spec(kXBLCachePrefix);
     193          26 :   nsresult rv = PathifyURI(aURI, spec);
     194          26 :   NS_ENSURE_SUCCESS(rv, rv);
     195             : 
     196          26 :   StartupCache* startupCache = StartupCache::GetSingleton();
     197          26 :   if (!startupCache) {
     198           1 :     return NS_ERROR_FAILURE;
     199             :   }
     200             : 
     201          50 :   UniquePtr<char[]> buf;
     202             :   uint32_t len;
     203          25 :   rv = startupCache->GetBuffer(spec.get(), &buf, &len);
     204             :   // GetBuffer will fail if the binding is not in the cache.
     205          25 :   if (NS_FAILED(rv))
     206           0 :     return rv;
     207             : 
     208          50 :   nsCOMPtr<nsIObjectInputStream> stream;
     209          25 :   rv = NewObjectInputStreamFromBuffer(Move(buf), len, getter_AddRefs(stream));
     210          25 :   NS_ENSURE_SUCCESS(rv, rv);
     211             : 
     212             :   // The file compatibility.ini stores the build id. This is checked in
     213             :   // nsAppRunner.cpp and will delete the cache if a different build is
     214             :   // present. However, we check that the version matches here to be safe.
     215             :   uint32_t version;
     216          25 :   rv = stream->Read32(&version);
     217          25 :   NS_ENSURE_SUCCESS(rv, rv);
     218          25 :   if (version != XBLBinding_Serialize_Version) {
     219             :     // The version that exists is different than expected, likely created with a
     220             :     // different build, so invalidate the cache.
     221           0 :     startupCache->InvalidateCache();
     222           0 :     return NS_ERROR_NOT_AVAILABLE;
     223             :   }
     224             : 
     225          50 :   nsCOMPtr<nsIPrincipal> principal;
     226          25 :   nsContentUtils::GetSecurityManager()->
     227          25 :     GetSystemPrincipal(getter_AddRefs(principal));
     228             : 
     229          50 :   nsCOMPtr<nsIDOMDocument> domdoc;
     230          25 :   rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nullptr, principal);
     231          25 :   NS_ENSURE_SUCCESS(rv, rv);
     232             : 
     233          50 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
     234          25 :   NS_ASSERTION(doc, "Must have a document!");
     235             : 
     236             :   // Set the style backend type immediately after creating the XBL document.
     237             :   // Assume gecko if there's no bound document.
     238          25 :   doc->SetStyleBackendType(aBoundDocument ? aBoundDocument->GetStyleBackendType()
     239          25 :                                           : StyleBackendType::Gecko);
     240             : 
     241          75 :   RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(doc);
     242             : 
     243             :   while (1) {
     244             :     uint8_t flags;
     245         167 :     nsresult rv = stream->Read8(&flags);
     246         167 :     NS_ENSURE_SUCCESS(rv, rv);
     247         167 :     if (flags == XBLBinding_Serialize_NoMoreBindings)
     248          25 :       break;
     249             : 
     250         142 :     rv = nsXBLPrototypeBinding::ReadNewBinding(stream, docInfo, doc, flags);
     251         142 :     if (NS_FAILED(rv)) {
     252           0 :       return rv;
     253             :     }
     254         142 :   }
     255             : 
     256          25 :   docInfo.forget(aDocInfo);
     257          25 :   return NS_OK;
     258             : }
     259             : 
     260             : nsresult
     261           1 : nsXBLDocumentInfo::WritePrototypeBindings()
     262             : {
     263             :   // Only write out bindings with the system principal
     264           1 :   if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal()))
     265           0 :     return NS_OK;
     266             : 
     267           2 :   nsAutoCString spec(kXBLCachePrefix);
     268           1 :   nsresult rv = PathifyURI(DocumentURI(), spec);
     269           1 :   NS_ENSURE_SUCCESS(rv, rv);
     270             : 
     271           1 :   StartupCache* startupCache = StartupCache::GetSingleton();
     272           1 :   if (!startupCache) {
     273           1 :     return rv;
     274             :   }
     275             : 
     276           0 :   nsCOMPtr<nsIObjectOutputStream> stream;
     277           0 :   nsCOMPtr<nsIStorageStream> storageStream;
     278           0 :   rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(stream),
     279           0 :                                            getter_AddRefs(storageStream),
     280           0 :                                            true);
     281           0 :   NS_ENSURE_SUCCESS(rv, rv);
     282             : 
     283           0 :   rv = stream->Write32(XBLBinding_Serialize_Version);
     284           0 :   NS_ENSURE_SUCCESS(rv, rv);
     285             : 
     286           0 :   if (mBindingTable) {
     287           0 :     for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
     288           0 :       iter.UserData()->Write(stream);
     289             :     }
     290             :   }
     291             : 
     292             :   // write a end marker at the end
     293           0 :   rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings);
     294           0 :   NS_ENSURE_SUCCESS(rv, rv);
     295             : 
     296           0 :   stream->Close();
     297           0 :   NS_ENSURE_SUCCESS(rv, rv);
     298             : 
     299             :   uint32_t len;
     300           0 :   UniquePtr<char[]> buf;
     301           0 :   rv = NewBufferFromStorageStream(storageStream, &buf, &len);
     302           0 :   NS_ENSURE_SUCCESS(rv, rv);
     303             : 
     304           0 :   return startupCache->PutBuffer(spec.get(), buf.get(), len);
     305             : }
     306             : 
     307             : void
     308          26 : nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
     309             : {
     310          26 :   mFirstBinding = aBinding;
     311          26 : }
     312             : 
     313             : void
     314           0 : nsXBLDocumentInfo::FlushSkinStylesheets()
     315             : {
     316           0 :   if (mBindingTable) {
     317           0 :     for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
     318           0 :       iter.UserData()->FlushSkinSheets();
     319             :     }
     320             :   }
     321           0 : }
     322             : 
     323             : #ifdef DEBUG
     324             : void
     325        2388 : AssertInCompilationScope()
     326             : {
     327        4776 :   AutoJSContext cx;
     328        2388 :   MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx));
     329        2388 : }
     330             : #endif

Generated by: LCOV version 1.13