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 "nsBaseHashtable.h" 10 #include "nsCOMPtr.h" 11 #include "nsIObserver.h" 12 #include "nsInterfaceHashtable.h" 13 #include "nsRefPtrHashtable.h" 14 #include "nsURIHashKey.h" 15 #include "nsXULPrototypeDocument.h" 16 #include "nsIStorageStream.h" 17 18 #include "mozilla/scache/StartupCache.h" 19 20 class nsIHandleReportCallback; 21 namespace mozilla { 22 class StyleSheet; 23 } // namespace mozilla 24 25 /** 26 * The XUL prototype cache can be used to store and retrieve shared data for 27 * XUL documents, style sheets, XBL, and scripts. 28 * 29 * The cache has two levels: 30 * 1. In-memory hashtables 31 * 2. The on-disk cache file. 32 */ 33 class nsXULPrototypeCache : public nsIObserver { 34 public: 35 // nsISupports 36 NS_DECL_THREADSAFE_ISUPPORTS 37 NS_DECL_NSIOBSERVER 38 IsCached(nsIURI * aURI)39 bool IsCached(nsIURI* aURI) { return GetPrototype(aURI) != nullptr; } 40 void AbortCaching(); 41 42 /** 43 * Whether the prototype cache is enabled. 44 */ 45 bool IsEnabled(); 46 47 /** 48 * Flush the cache; remove all XUL prototype documents, style 49 * sheets, and scripts. 50 */ 51 void Flush(); 52 53 // The following methods are used to put and retrive various items into and 54 // from the cache. 55 56 nsXULPrototypeDocument* GetPrototype(nsIURI* aURI); 57 nsresult PutPrototype(nsXULPrototypeDocument* aDocument); 58 59 JSScript* GetScript(nsIURI* aURI); 60 nsresult PutScript(nsIURI* aURI, JS::Handle<JSScript*> aScriptObject); 61 62 /** 63 * Get a style sheet by URI. If the style sheet is not in the cache, 64 * returns nullptr. 65 */ 66 mozilla::StyleSheet* GetStyleSheet(nsIURI* aURI); 67 68 /** 69 * Store a style sheet in the cache. The key, style sheet's URI is obtained 70 * from the style sheet itself. 71 */ 72 nsresult PutStyleSheet(RefPtr<mozilla::StyleSheet>&& aStyleSheet); 73 74 /** 75 * Write the XUL prototype document to a cache file. The proto must be 76 * fully loaded. 77 */ 78 nsresult WritePrototype(nsXULPrototypeDocument* aPrototypeDocument); 79 80 /** 81 * This interface allows partial reads and writes from the buffers in the 82 * startupCache. 83 */ 84 nsresult GetInputStream(nsIURI* aURI, nsIObjectInputStream** objectInput); 85 nsresult FinishInputStream(nsIURI* aURI); 86 nsresult GetOutputStream(nsIURI* aURI, nsIObjectOutputStream** objectOutput); 87 nsresult FinishOutputStream(nsIURI* aURI); 88 nsresult HasData(nsIURI* aURI, bool* exists); 89 90 static nsXULPrototypeCache* GetInstance(); MaybeGetInstance()91 static nsXULPrototypeCache* MaybeGetInstance() { return sInstance; } 92 ReleaseGlobals()93 static void ReleaseGlobals() { NS_IF_RELEASE(sInstance); } 94 95 void MarkInCCGeneration(uint32_t aGeneration); 96 void MarkInGC(JSTracer* aTrc); 97 void FlushScripts(); 98 99 static void CollectMemoryReports(nsIHandleReportCallback* aHandleReport, 100 nsISupports* aData); 101 102 protected: 103 friend nsresult NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, 104 void** aResult); 105 106 nsXULPrototypeCache(); 107 virtual ~nsXULPrototypeCache(); 108 109 static nsXULPrototypeCache* sInstance; 110 111 using StyleSheetTable = nsRefPtrHashtable<nsURIHashKey, mozilla::StyleSheet>; 112 113 nsRefPtrHashtable<nsURIHashKey, nsXULPrototypeDocument> 114 mPrototypeTable; // owns the prototypes 115 StyleSheetTable mStyleSheetTable; 116 117 class ScriptHashKey : public nsURIHashKey { 118 public: ScriptHashKey(const nsIURI * aKey)119 explicit ScriptHashKey(const nsIURI* aKey) : nsURIHashKey(aKey) {} 120 ScriptHashKey(ScriptHashKey&&) = default; 121 122 // Mark ALLOW_MEMMOVE as false, as hash tables containing JS:Heap<T> 123 // values must be copied rather than memmoved. 124 enum { ALLOW_MEMMOVE = false }; 125 126 JS::Heap<JSScript*> mScript; 127 }; 128 129 nsTHashtable<ScriptHashKey> mScriptTable; 130 131 // URIs already written to the startup cache, to prevent double-caching. 132 nsTHashtable<nsURIHashKey> mStartupCacheURITable; 133 134 nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable; 135 nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable; 136 137 // Bootstrap caching service 138 nsresult BeginCaching(nsIURI* aDocumentURI); 139 }; 140 141 #endif // nsXULPrototypeCache_h__ 142