LCOV - code coverage report
Current view: top level - dom/xul - nsXULPrototypeCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 129 316 40.8 %
Date: 2017-07-14 16:53:18 Functions: 17 32 53.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 "nsXULPrototypeCache.h"
       8             : 
       9             : #include "plstr.h"
      10             : #include "nsXULPrototypeDocument.h"
      11             : #include "nsIServiceManager.h"
      12             : #include "nsIURI.h"
      13             : 
      14             : #include "nsIFile.h"
      15             : #include "nsIObjectInputStream.h"
      16             : #include "nsIObjectOutputStream.h"
      17             : #include "nsIObserverService.h"
      18             : #include "nsIStringStream.h"
      19             : #include "nsIStorageStream.h"
      20             : 
      21             : #include "nsAppDirectoryServiceDefs.h"
      22             : 
      23             : #include "js/TracingAPI.h"
      24             : 
      25             : #include "mozilla/StyleSheetInlines.h"
      26             : #include "mozilla/Preferences.h"
      27             : #include "mozilla/scache/StartupCache.h"
      28             : #include "mozilla/scache/StartupCacheUtils.h"
      29             : #include "mozilla/Telemetry.h"
      30             : #include "mozilla/intl/LocaleService.h"
      31             : 
      32             : using namespace mozilla;
      33             : using namespace mozilla::scache;
      34             : using mozilla::intl::LocaleService;
      35             : 
      36             : static bool gDisableXULCache = false; // enabled by default
      37             : static const char kDisableXULCachePref[] = "nglayout.debug.disable_xul_cache";
      38             : static const char kXULCacheInfoKey[] = "nsXULPrototypeCache.startupCache";
      39             : static const char kXULCachePrefix[] = "xulcache";
      40             : 
      41             : //----------------------------------------------------------------------
      42             : 
      43             : static void
      44           3 : UpdategDisableXULCache()
      45             : {
      46             :     // Get the value of "nglayout.debug.disable_xul_cache" preference
      47           3 :     gDisableXULCache =
      48           3 :         Preferences::GetBool(kDisableXULCachePref, gDisableXULCache);
      49             : 
      50             :     // Sets the flag if the XUL cache is disabled
      51           3 :     if (gDisableXULCache) {
      52           0 :         Telemetry::Accumulate(Telemetry::XUL_CACHE_DISABLED, true);
      53             :     }
      54             : 
      55           3 : }
      56             : 
      57             : static void
      58           0 : DisableXULCacheChangedCallback(const char* aPref, void* aClosure)
      59             : {
      60           0 :     bool wasEnabled = !gDisableXULCache;
      61           0 :     UpdategDisableXULCache();
      62             : 
      63           0 :     if (wasEnabled && gDisableXULCache) {
      64           0 :         nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
      65           0 :         if (cache) {
      66             :             // AbortCaching() calls Flush() for us.
      67           0 :             cache->AbortCaching();
      68             :         }
      69             :     }
      70           0 : }
      71             : 
      72             : //----------------------------------------------------------------------
      73             : 
      74             : nsXULPrototypeCache*  nsXULPrototypeCache::sInstance = nullptr;
      75             : 
      76             : 
      77           3 : nsXULPrototypeCache::nsXULPrototypeCache()
      78             : {
      79           3 : }
      80             : 
      81             : 
      82           0 : nsXULPrototypeCache::~nsXULPrototypeCache()
      83             : {
      84           0 :     FlushScripts();
      85           0 : }
      86             : 
      87             : 
      88          15 : NS_IMPL_ISUPPORTS(nsXULPrototypeCache, nsIObserver)
      89             : 
      90             : /* static */ nsXULPrototypeCache*
      91         772 : nsXULPrototypeCache::GetInstance()
      92             : {
      93         772 :     if (!sInstance) {
      94           3 :         NS_ADDREF(sInstance = new nsXULPrototypeCache());
      95             : 
      96           3 :         UpdategDisableXULCache();
      97             : 
      98             :         Preferences::RegisterCallback(DisableXULCacheChangedCallback,
      99           3 :                                       kDisableXULCachePref);
     100             : 
     101             :         nsCOMPtr<nsIObserverService> obsSvc =
     102           6 :             mozilla::services::GetObserverService();
     103           3 :         if (obsSvc) {
     104           3 :             nsXULPrototypeCache *p = sInstance;
     105           3 :             obsSvc->AddObserver(p, "chrome-flush-skin-caches", false);
     106           3 :             obsSvc->AddObserver(p, "chrome-flush-caches", false);
     107           3 :             obsSvc->AddObserver(p, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
     108           3 :             obsSvc->AddObserver(p, "startupcache-invalidate", false);
     109             :         }
     110             : 
     111             :     }
     112         772 :     return sInstance;
     113             : }
     114             : 
     115             : //----------------------------------------------------------------------
     116             : 
     117             : NS_IMETHODIMP
     118           0 : nsXULPrototypeCache::Observe(nsISupports* aSubject,
     119             :                              const char *aTopic,
     120             :                              const char16_t *aData)
     121             : {
     122           0 :     if (!strcmp(aTopic, "chrome-flush-skin-caches")) {
     123           0 :         FlushSkinFiles();
     124             :     }
     125           0 :     else if (!strcmp(aTopic, "chrome-flush-caches") ||
     126           0 :              !strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     127           0 :         Flush();
     128             :     }
     129           0 :     else if (!strcmp(aTopic, "startupcache-invalidate")) {
     130           0 :         AbortCaching();
     131             :     }
     132             :     else {
     133           0 :         NS_WARNING("Unexpected observer topic.");
     134             :     }
     135           0 :     return NS_OK;
     136             : }
     137             : 
     138             : nsXULPrototypeDocument*
     139           6 : nsXULPrototypeCache::GetPrototype(nsIURI* aURI)
     140             : {
     141           6 :     if (!aURI)
     142           0 :         return nullptr;
     143             : 
     144          12 :     nsCOMPtr<nsIURI> uriWithoutRef;
     145           6 :     aURI->CloneIgnoringRef(getter_AddRefs(uriWithoutRef));
     146             : 
     147           6 :     nsXULPrototypeDocument* protoDoc = mPrototypeTable.GetWeak(uriWithoutRef);
     148           6 :     if (protoDoc)
     149           0 :         return protoDoc;
     150             : 
     151           6 :     nsresult rv = BeginCaching(aURI);
     152           6 :     if (NS_FAILED(rv))
     153           0 :         return nullptr;
     154             : 
     155             :     // No prototype in XUL memory cache. Spin up the cache Service.
     156          12 :     nsCOMPtr<nsIObjectInputStream> ois;
     157           6 :     rv = GetInputStream(aURI, getter_AddRefs(ois));
     158           6 :     if (NS_FAILED(rv))
     159           0 :         return nullptr;
     160             : 
     161          12 :     RefPtr<nsXULPrototypeDocument> newProto;
     162           6 :     rv = NS_NewXULPrototypeDocument(getter_AddRefs(newProto));
     163           6 :     if (NS_FAILED(rv))
     164           0 :         return nullptr;
     165             : 
     166           6 :     rv = newProto->Read(ois);
     167           6 :     if (NS_SUCCEEDED(rv)) {
     168           6 :         rv = PutPrototype(newProto);
     169             :     } else {
     170           0 :         newProto = nullptr;
     171             :     }
     172             : 
     173           6 :     mInputStreamTable.Remove(aURI);
     174           6 :     return newProto;
     175             : }
     176             : 
     177             : nsresult
     178           6 : nsXULPrototypeCache::PutPrototype(nsXULPrototypeDocument* aDocument)
     179             : {
     180           6 :     if (!aDocument->GetURI()) {
     181           0 :         return NS_ERROR_FAILURE;
     182             :     }
     183             : 
     184          12 :     nsCOMPtr<nsIURI> uri;
     185           6 :     aDocument->GetURI()->CloneIgnoringRef(getter_AddRefs(uri));
     186             : 
     187             :     // Put() releases any old value and addrefs the new one
     188           6 :     mPrototypeTable.Put(uri, aDocument);
     189             : 
     190           6 :     return NS_OK;
     191             : }
     192             : 
     193             : mozilla::StyleSheet*
     194          89 : nsXULPrototypeCache::GetStyleSheet(nsIURI* aURI,
     195             :                                    StyleBackendType aType)
     196             : {
     197          89 :     StyleSheetTable& table = StyleSheetTableFor(aType);
     198          89 :     return table.GetWeak(aURI);
     199             : }
     200             : 
     201             : nsresult
     202          37 : nsXULPrototypeCache::PutStyleSheet(StyleSheet* aStyleSheet,
     203             :                                    StyleBackendType aType)
     204             : {
     205          37 :     nsIURI* uri = aStyleSheet->GetSheetURI();
     206             : 
     207          37 :     StyleSheetTable& table = StyleSheetTableFor(aType);
     208          37 :     table.Put(uri, aStyleSheet);
     209             : 
     210          37 :     return NS_OK;
     211             : }
     212             : 
     213             : JSScript*
     214          38 : nsXULPrototypeCache::GetScript(nsIURI* aURI)
     215             : {
     216          38 :     return mScriptTable.Get(aURI);
     217             : }
     218             : 
     219             : nsresult
     220          37 : nsXULPrototypeCache::PutScript(nsIURI* aURI,
     221             :                                JS::Handle<JSScript*> aScriptObject)
     222             : {
     223          37 :     MOZ_ASSERT(aScriptObject, "Need a non-NULL script");
     224             : 
     225             : #ifdef DEBUG_BUG_392650
     226             :     if (mScriptTable.Get(aURI)) {
     227             :         nsAutoCString scriptName;
     228             :         aURI->GetSpec(scriptName);
     229             :         nsAutoCString message("Loaded script ");
     230             :         message += scriptName;
     231             :         message += " twice (bug 392650)";
     232             :         NS_WARNING(message.get());
     233             :     }
     234             : #endif
     235             : 
     236          37 :     mScriptTable.Put(aURI, aScriptObject);
     237             : 
     238          37 :     return NS_OK;
     239             : }
     240             : 
     241             : nsXBLDocumentInfo*
     242          26 : nsXULPrototypeCache::GetXBLDocumentInfo(nsIURI* aURL,
     243             :                                         StyleBackendType aType)
     244             : {
     245          26 :   MOZ_ASSERT(aType != StyleBackendType::None,
     246             :              "Please use either gecko or servo when looking up for the cache!");
     247          26 :   return XBLDocTableFor(aType).GetWeak(aURL);
     248             : }
     249             : 
     250             : nsresult
     251          26 : nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo)
     252             : {
     253          26 :   nsIURI* uri = aDocumentInfo->DocumentURI();
     254             :   XBLDocTable& table =
     255          26 :     XBLDocTableFor(aDocumentInfo->GetDocument()->GetStyleBackendType());
     256             : 
     257          26 :   nsXBLDocumentInfo* info = table.GetWeak(uri);
     258          26 :   if (!info) {
     259          26 :     table.Put(uri, aDocumentInfo);
     260             :   }
     261          26 :   return NS_OK;
     262             : }
     263             : 
     264             : void
     265           0 : nsXULPrototypeCache::FlushSkinFiles()
     266             : {
     267             :   StyleBackendType tableTypes[] = { StyleBackendType::Gecko,
     268           0 :                                     StyleBackendType::Servo };
     269             : 
     270           0 :   for (auto tableType : tableTypes) {
     271             :     // Flush out skin XBL files from the cache.
     272           0 :     XBLDocTable& xblDocTable = XBLDocTableFor(tableType);
     273           0 :     for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
     274           0 :       nsAutoCString str;
     275           0 :       iter.Key()->GetPath(str);
     276           0 :       if (strncmp(str.get(), "/skin", 5) == 0) {
     277           0 :         iter.Remove();
     278             :       }
     279             :     }
     280             : 
     281             :     // Now flush out our skin stylesheets from the cache.
     282           0 :     StyleSheetTable& table = StyleSheetTableFor(tableType);
     283           0 :     for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
     284           0 :       nsAutoCString str;
     285           0 :       iter.Data()->GetSheetURI()->GetPath(str);
     286           0 :       if (strncmp(str.get(), "/skin", 5) == 0) {
     287           0 :         iter.Remove();
     288             :       }
     289             :     }
     290             : 
     291             :     // Iterate over all the remaining XBL and make sure cached
     292             :     // scoped skin stylesheets are flushed and refetched by the
     293             :     // prototype bindings.
     294           0 :     for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
     295           0 :       iter.Data()->FlushSkinStylesheets();
     296             :     }
     297             :   }
     298           0 : }
     299             : 
     300             : void
     301           0 : nsXULPrototypeCache::FlushScripts()
     302             : {
     303           0 :     mScriptTable.Clear();
     304           0 : }
     305             : 
     306             : void
     307           0 : nsXULPrototypeCache::Flush()
     308             : {
     309           0 :     mPrototypeTable.Clear();
     310           0 :     mScriptTable.Clear();
     311           0 :     mGeckoStyleSheetTable.Clear();
     312           0 :     mServoStyleSheetTable.Clear();
     313           0 :     mGeckoXBLDocTable.Clear();
     314           0 :     mServoXBLDocTable.Clear();
     315           0 : }
     316             : 
     317             : 
     318             : bool
     319         765 : nsXULPrototypeCache::IsEnabled()
     320             : {
     321         765 :     return !gDisableXULCache;
     322             : }
     323             : 
     324             : void
     325           0 : nsXULPrototypeCache::AbortCaching()
     326             : {
     327             : #ifdef DEBUG_brendan
     328             :     NS_BREAK();
     329             : #endif
     330             : 
     331             :     // Flush the XUL cache for good measure, in case we cached a bogus/downrev
     332             :     // script, somehow.
     333           0 :     Flush();
     334             : 
     335             :     // Clear the cache set
     336           0 :     mStartupCacheURITable.Clear();
     337           0 : }
     338             : 
     339             : 
     340             : nsresult
     341           0 : nsXULPrototypeCache::WritePrototype(nsXULPrototypeDocument* aPrototypeDocument)
     342             : {
     343           0 :     nsresult rv = NS_OK, rv2 = NS_OK;
     344             : 
     345           0 :     if (!StartupCache::GetSingleton())
     346           0 :         return NS_OK;
     347             : 
     348           0 :     nsCOMPtr<nsIURI> protoURI = aPrototypeDocument->GetURI();
     349             : 
     350           0 :     nsCOMPtr<nsIObjectOutputStream> oos;
     351           0 :     rv = GetOutputStream(protoURI, getter_AddRefs(oos));
     352           0 :     NS_ENSURE_SUCCESS(rv, rv);
     353             : 
     354           0 :     rv = aPrototypeDocument->Write(oos);
     355           0 :     NS_ENSURE_SUCCESS(rv, rv);
     356           0 :     FinishOutputStream(protoURI);
     357           0 :     return NS_FAILED(rv) ? rv : rv2;
     358             : }
     359             : 
     360             : nsresult
     361          43 : nsXULPrototypeCache::GetInputStream(nsIURI* uri, nsIObjectInputStream** stream)
     362             : {
     363          86 :     nsAutoCString spec(kXULCachePrefix);
     364          43 :     nsresult rv = PathifyURI(uri, spec);
     365          43 :     if (NS_FAILED(rv))
     366           0 :         return NS_ERROR_NOT_AVAILABLE;
     367             : 
     368          86 :     UniquePtr<char[]> buf;
     369             :     uint32_t len;
     370          86 :     nsCOMPtr<nsIObjectInputStream> ois;
     371          43 :     StartupCache* sc = StartupCache::GetSingleton();
     372          43 :     if (!sc)
     373           0 :         return NS_ERROR_NOT_AVAILABLE;
     374             : 
     375          43 :     rv = sc->GetBuffer(spec.get(), &buf, &len);
     376          43 :     if (NS_FAILED(rv))
     377           0 :         return NS_ERROR_NOT_AVAILABLE;
     378             : 
     379          43 :     rv = NewObjectInputStreamFromBuffer(Move(buf), len, getter_AddRefs(ois));
     380          43 :     NS_ENSURE_SUCCESS(rv, rv);
     381             : 
     382          43 :     mInputStreamTable.Put(uri, ois);
     383             : 
     384          43 :     ois.forget(stream);
     385          43 :     return NS_OK;
     386             : }
     387             : 
     388             : nsresult
     389          37 : nsXULPrototypeCache::FinishInputStream(nsIURI* uri) {
     390          37 :     mInputStreamTable.Remove(uri);
     391          37 :     return NS_OK;
     392             : }
     393             : 
     394             : nsresult
     395           0 : nsXULPrototypeCache::GetOutputStream(nsIURI* uri, nsIObjectOutputStream** stream)
     396             : {
     397             :     nsresult rv;
     398           0 :     nsCOMPtr<nsIObjectOutputStream> objectOutput;
     399           0 :     nsCOMPtr<nsIStorageStream> storageStream;
     400           0 :     bool found = mOutputStreamTable.Get(uri, getter_AddRefs(storageStream));
     401           0 :     if (found) {
     402           0 :         objectOutput = do_CreateInstance("mozilla.org/binaryoutputstream;1");
     403           0 :         if (!objectOutput) return NS_ERROR_OUT_OF_MEMORY;
     404             :         nsCOMPtr<nsIOutputStream> outputStream
     405           0 :             = do_QueryInterface(storageStream);
     406           0 :         objectOutput->SetOutputStream(outputStream);
     407             :     } else {
     408           0 :         rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput),
     409           0 :                                                  getter_AddRefs(storageStream),
     410           0 :                                                  false);
     411           0 :         NS_ENSURE_SUCCESS(rv, rv);
     412           0 :         mOutputStreamTable.Put(uri, storageStream);
     413             :     }
     414           0 :     objectOutput.forget(stream);
     415           0 :     return NS_OK;
     416             : }
     417             : 
     418             : nsresult
     419           0 : nsXULPrototypeCache::FinishOutputStream(nsIURI* uri)
     420             : {
     421             :     nsresult rv;
     422           0 :     StartupCache* sc = StartupCache::GetSingleton();
     423           0 :     if (!sc)
     424           0 :         return NS_ERROR_NOT_AVAILABLE;
     425             : 
     426           0 :     nsCOMPtr<nsIStorageStream> storageStream;
     427           0 :     bool found = mOutputStreamTable.Get(uri, getter_AddRefs(storageStream));
     428           0 :     if (!found)
     429           0 :         return NS_ERROR_UNEXPECTED;
     430             :     nsCOMPtr<nsIOutputStream> outputStream
     431           0 :         = do_QueryInterface(storageStream);
     432           0 :     outputStream->Close();
     433             : 
     434           0 :     UniquePtr<char[]> buf;
     435             :     uint32_t len;
     436           0 :     rv = NewBufferFromStorageStream(storageStream, &buf, &len);
     437           0 :     NS_ENSURE_SUCCESS(rv, rv);
     438             : 
     439           0 :     if (!mStartupCacheURITable.GetEntry(uri)) {
     440           0 :         nsAutoCString spec(kXULCachePrefix);
     441           0 :         rv = PathifyURI(uri, spec);
     442           0 :         if (NS_FAILED(rv))
     443           0 :             return NS_ERROR_NOT_AVAILABLE;
     444           0 :         rv = sc->PutBuffer(spec.get(), buf.get(), len);
     445           0 :         if (NS_SUCCEEDED(rv)) {
     446           0 :             mOutputStreamTable.Remove(uri);
     447           0 :             mStartupCacheURITable.PutEntry(uri);
     448             :         }
     449             :     }
     450             : 
     451           0 :     return rv;
     452             : }
     453             : 
     454             : // We have data if we're in the middle of writing it or we already
     455             : // have it in the cache.
     456             : nsresult
     457           0 : nsXULPrototypeCache::HasData(nsIURI* uri, bool* exists)
     458             : {
     459           0 :     if (mOutputStreamTable.Get(uri, nullptr)) {
     460           0 :         *exists = true;
     461           0 :         return NS_OK;
     462             :     }
     463           0 :     nsAutoCString spec(kXULCachePrefix);
     464           0 :     nsresult rv = PathifyURI(uri, spec);
     465           0 :     if (NS_FAILED(rv)) {
     466           0 :         *exists = false;
     467           0 :         return NS_OK;
     468             :     }
     469           0 :     UniquePtr<char[]> buf;
     470             :     uint32_t len;
     471           0 :     StartupCache* sc = StartupCache::GetSingleton();
     472           0 :     if (sc) {
     473           0 :         rv = sc->GetBuffer(spec.get(), &buf, &len);
     474             :     } else {
     475           0 :         *exists = false;
     476           0 :         return NS_OK;
     477             :     }
     478           0 :     *exists = NS_SUCCEEDED(rv);
     479           0 :     return NS_OK;
     480             : }
     481             : 
     482             : nsresult
     483           6 : nsXULPrototypeCache::BeginCaching(nsIURI* aURI)
     484             : {
     485             :     nsresult rv, tmp;
     486             : 
     487          12 :     nsAutoCString path;
     488           6 :     aURI->GetPath(path);
     489           6 :     if (!StringEndsWith(path, NS_LITERAL_CSTRING(".xul")))
     490           0 :         return NS_ERROR_NOT_AVAILABLE;
     491             : 
     492           6 :     StartupCache* startupCache = StartupCache::GetSingleton();
     493           6 :     if (!startupCache)
     494           0 :         return NS_ERROR_FAILURE;
     495             : 
     496           6 :     if (gDisableXULCache)
     497           0 :         return NS_ERROR_NOT_AVAILABLE;
     498             : 
     499             :     // Get the chrome directory to validate against the one stored in the
     500             :     // cache file, or to store there if we're generating a new file.
     501          12 :     nsCOMPtr<nsIFile> chromeDir;
     502           6 :     rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR, getter_AddRefs(chromeDir));
     503           6 :     if (NS_FAILED(rv))
     504           0 :         return rv;
     505          12 :     nsAutoCString chromePath;
     506           6 :     rv = chromeDir->GetNativePath(chromePath);
     507           6 :     if (NS_FAILED(rv))
     508           0 :         return rv;
     509             : 
     510             :     // XXXbe we assume the first package's locale is the same as the locale of
     511             :     // all subsequent packages of cached chrome URIs....
     512          12 :     nsAutoCString package;
     513           6 :     rv = aURI->GetHost(package);
     514           6 :     if (NS_FAILED(rv))
     515           0 :         return rv;
     516          12 :     nsAutoCString locale;
     517           6 :     LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale);
     518             : 
     519          12 :     nsAutoCString fileChromePath, fileLocale;
     520             : 
     521          12 :     UniquePtr<char[]> buf;
     522             :     uint32_t len, amtRead;
     523          12 :     nsCOMPtr<nsIObjectInputStream> objectInput;
     524             : 
     525           6 :     rv = startupCache->GetBuffer(kXULCacheInfoKey, &buf, &len);
     526           6 :     if (NS_SUCCEEDED(rv))
     527          12 :         rv = NewObjectInputStreamFromBuffer(Move(buf), len,
     528          18 :                                             getter_AddRefs(objectInput));
     529             : 
     530           6 :     if (NS_SUCCEEDED(rv)) {
     531           6 :         rv = objectInput->ReadCString(fileLocale);
     532           6 :         tmp = objectInput->ReadCString(fileChromePath);
     533           6 :         if (NS_FAILED(tmp)) {
     534           0 :           rv = tmp;
     535             :         }
     536          12 :         if (NS_FAILED(rv) ||
     537          12 :             (!fileChromePath.Equals(chromePath) ||
     538           6 :              !fileLocale.Equals(locale))) {
     539             :             // Our cache won't be valid in this case, we'll need to rewrite.
     540             :             // XXX This blows away work that other consumers (like
     541             :             // mozJSComponentLoader) have done, need more fine-grained control.
     542           0 :             startupCache->InvalidateCache();
     543           0 :             mStartupCacheURITable.Clear();
     544           0 :             rv = NS_ERROR_UNEXPECTED;
     545             :         }
     546           0 :     } else if (rv != NS_ERROR_NOT_AVAILABLE)
     547             :         // NS_ERROR_NOT_AVAILABLE is normal, usually if there's no cachefile.
     548           0 :         return rv;
     549             : 
     550           6 :     if (NS_FAILED(rv)) {
     551             :         // Either the cache entry was invalid or it didn't exist, so write it now.
     552           0 :         nsCOMPtr<nsIObjectOutputStream> objectOutput;
     553           0 :         nsCOMPtr<nsIInputStream> inputStream;
     554           0 :         nsCOMPtr<nsIStorageStream> storageStream;
     555           0 :         rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput),
     556           0 :                                                  getter_AddRefs(storageStream),
     557           0 :                                                  false);
     558           0 :         if (NS_SUCCEEDED(rv)) {
     559           0 :             rv = objectOutput->WriteStringZ(locale.get());
     560           0 :             tmp = objectOutput->WriteStringZ(chromePath.get());
     561           0 :             if (NS_FAILED(tmp)) {
     562           0 :               rv = tmp;
     563             :             }
     564           0 :             tmp = objectOutput->Close();
     565           0 :             if (NS_FAILED(tmp)) {
     566           0 :               rv = tmp;
     567             :             }
     568           0 :             tmp = storageStream->NewInputStream(0, getter_AddRefs(inputStream));
     569           0 :             if (NS_FAILED(tmp)) {
     570           0 :               rv = tmp;
     571             :             }
     572             :         }
     573             : 
     574           0 :         if (NS_SUCCEEDED(rv)) {
     575             :             uint64_t len64;
     576           0 :             rv = inputStream->Available(&len64);
     577           0 :             if (NS_SUCCEEDED(rv)) {
     578           0 :               if (len64 <= UINT32_MAX)
     579           0 :                 len = (uint32_t)len64;
     580             :               else
     581           0 :                 rv = NS_ERROR_FILE_TOO_BIG;
     582             :             }
     583             :         }
     584             : 
     585           0 :         if (NS_SUCCEEDED(rv)) {
     586           0 :             buf = MakeUnique<char[]>(len);
     587           0 :             rv = inputStream->Read(buf.get(), len, &amtRead);
     588           0 :             if (NS_SUCCEEDED(rv) && len == amtRead)
     589           0 :               rv = startupCache->PutBuffer(kXULCacheInfoKey, buf.get(), len);
     590             :             else {
     591           0 :                 rv = NS_ERROR_UNEXPECTED;
     592             :             }
     593             :         }
     594             : 
     595             :         // Failed again, just bail.
     596           0 :         if (NS_FAILED(rv)) {
     597           0 :             startupCache->InvalidateCache();
     598           0 :             mStartupCacheURITable.Clear();
     599           0 :             return NS_ERROR_FAILURE;
     600             :         }
     601             :     }
     602             : 
     603           6 :     return NS_OK;
     604             : }
     605             : 
     606             : void
     607           0 : nsXULPrototypeCache::MarkInCCGeneration(uint32_t aGeneration)
     608             : {
     609             :     StyleBackendType tableTypes[] = { StyleBackendType::Gecko,
     610           0 :                                       StyleBackendType::Servo };
     611             : 
     612           0 :     for (auto tableType : tableTypes) {
     613           0 :         XBLDocTable& xblDocTable = XBLDocTableFor(tableType);
     614           0 :         for (auto iter = xblDocTable.Iter(); !iter.Done(); iter.Next()) {
     615           0 :             iter.Data()->MarkInCCGeneration(aGeneration);
     616             :         }
     617             :     }
     618           0 :     for (auto iter = mPrototypeTable.Iter(); !iter.Done(); iter.Next()) {
     619           0 :         iter.Data()->MarkInCCGeneration(aGeneration);
     620             :     }
     621           0 : }
     622             : 
     623             : void
     624           1 : nsXULPrototypeCache::MarkInGC(JSTracer* aTrc)
     625             : {
     626          38 :     for (auto iter = mScriptTable.Iter(); !iter.Done(); iter.Next()) {
     627          37 :         JS::Heap<JSScript*>& script = iter.Data();
     628          37 :         JS::TraceEdge(aTrc, &script, "nsXULPrototypeCache script");
     629             :     }
     630           1 : }

Generated by: LCOV version 1.13