nsXULPrototypeCache.h (5214B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsXULPrototypeCache_h__ 7 #define nsXULPrototypeCache_h__ 8 9 #include "js/experimental/JSStencil.h" 10 #include "mozilla/RefPtr.h" 11 #include "mozilla/scache/StartupCache.h" 12 #include "nsBaseHashtable.h" 13 #include "nsCOMPtr.h" 14 #include "nsIObserver.h" 15 #include "nsIStorageStream.h" 16 #include "nsInterfaceHashtable.h" 17 #include "nsRefPtrHashtable.h" 18 #include "nsURIHashKey.h" 19 #include "nsXULPrototypeDocument.h" 20 21 class nsIHandleReportCallback; 22 namespace mozilla { 23 class StyleSheet; 24 } // namespace mozilla 25 26 /** 27 * The XUL prototype cache can be used to store and retrieve shared data for 28 * XUL documents, style sheets, XBL, and scripts. 29 * 30 * The cache has two levels: 31 * 1. In-memory hashtables 32 * 2. The on-disk cache file. 33 */ 34 class nsXULPrototypeCache : public nsIObserver { 35 public: 36 enum class CacheType { Prototype, Script }; 37 38 // nsISupports 39 NS_DECL_THREADSAFE_ISUPPORTS 40 NS_DECL_NSIOBSERVER 41 42 bool IsCached(nsIURI* aURI) { return GetPrototype(aURI) != nullptr; } 43 void AbortCaching(); 44 45 /** 46 * Whether the prototype cache is enabled. 47 */ 48 bool IsEnabled(); 49 50 /** 51 * Flush the cache; remove all XUL prototype documents, style 52 * sheets, and scripts. 53 */ 54 void Flush(); 55 56 // The following methods are used to put and retrive various items into and 57 // from the cache. 58 59 nsXULPrototypeDocument* GetPrototype(nsIURI* aURI); 60 nsresult PutPrototype(nsXULPrototypeDocument* aDocument); 61 void RemovePrototype(nsIURI* aURI) { mPrototypeTable.Remove(aURI); } 62 63 JS::Stencil* GetStencil(nsIURI* aURI); 64 nsresult PutStencil(nsIURI* aURI, JS::Stencil* aStencil); 65 66 /** 67 * Write the XUL prototype document to a cache file. The proto must be 68 * fully loaded. 69 */ 70 nsresult WritePrototype(nsXULPrototypeDocument* aPrototypeDocument); 71 72 /** 73 * This interface allows partial reads and writes from the buffers in the 74 * startupCache. 75 */ 76 77 inline nsresult GetPrototypeInputStream(nsIURI* aURI, 78 nsIObjectInputStream** objectInput) { 79 return GetInputStream(CacheType::Prototype, aURI, objectInput); 80 } 81 inline nsresult GetScriptInputStream(nsIURI* aURI, 82 nsIObjectInputStream** objectInput) { 83 return GetInputStream(CacheType::Script, aURI, objectInput); 84 } 85 inline nsresult FinishScriptInputStream(nsIURI* aURI) { 86 return FinishInputStream(aURI); 87 } 88 89 inline nsresult GetPrototypeOutputStream( 90 nsIURI* aURI, nsIObjectOutputStream** objectOutput) { 91 return GetOutputStream(aURI, objectOutput); 92 } 93 inline nsresult GetScriptOutputStream(nsIURI* aURI, 94 nsIObjectOutputStream** objectOutput) { 95 return GetOutputStream(aURI, objectOutput); 96 } 97 98 inline nsresult FinishPrototypeOutputStream(nsIURI* aURI) { 99 return FinishOutputStream(CacheType::Prototype, aURI); 100 } 101 inline nsresult FinishScriptOutputStream(nsIURI* aURI) { 102 return FinishOutputStream(CacheType::Script, aURI); 103 } 104 105 inline nsresult HasPrototype(nsIURI* aURI, bool* exists) { 106 return HasData(CacheType::Prototype, aURI, exists); 107 } 108 inline nsresult HasScript(nsIURI* aURI, bool* exists) { 109 return HasData(CacheType::Script, aURI, exists); 110 } 111 112 private: 113 nsresult GetInputStream(CacheType cacheType, nsIURI* uri, 114 nsIObjectInputStream** stream); 115 nsresult FinishInputStream(nsIURI* aURI); 116 117 nsresult GetOutputStream(nsIURI* aURI, nsIObjectOutputStream** objectOutput); 118 nsresult FinishOutputStream(CacheType cacheType, nsIURI* aURI); 119 nsresult HasData(CacheType cacheType, nsIURI* aURI, bool* exists); 120 121 public: 122 static nsXULPrototypeCache* GetInstance(); 123 static nsXULPrototypeCache* MaybeGetInstance() { return sInstance; } 124 125 static void ReleaseGlobals() { NS_IF_RELEASE(sInstance); } 126 127 void MarkInCCGeneration(uint32_t aGeneration); 128 129 static void CollectMemoryReports(nsIHandleReportCallback* aHandleReport, 130 nsISupports* aData); 131 132 protected: 133 friend nsresult NS_NewXULPrototypeCache(REFNSIID aIID, void** aResult); 134 135 nsXULPrototypeCache(); 136 virtual ~nsXULPrototypeCache() = default; 137 138 static nsXULPrototypeCache* sInstance; 139 140 nsRefPtrHashtable<nsURIHashKey, nsXULPrototypeDocument> 141 mPrototypeTable; // owns the prototypes 142 143 class StencilHashKey : public nsURIHashKey { 144 public: 145 explicit StencilHashKey(const nsIURI* aKey) : nsURIHashKey(aKey) {} 146 StencilHashKey(StencilHashKey&&) = default; 147 148 RefPtr<JS::Stencil> mStencil; 149 }; 150 151 nsTHashtable<StencilHashKey> mStencilTable; 152 153 // URIs already written to the startup cache, to prevent double-caching. 154 nsTHashtable<nsURIHashKey> mStartupCacheURITable; 155 156 nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable; 157 nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable; 158 159 // Bootstrap caching service 160 nsresult BeginCaching(nsIURI* aDocumentURI); 161 }; 162 163 #endif // nsXULPrototypeCache_h__