1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "nsCOMPtr.h"
10 #include "nsIObserver.h"
11 #include "nsXBLDocumentInfo.h"
12 #include "nsJSThingHashtable.h"
13 #include "nsInterfaceHashtable.h"
14 #include "nsRefPtrHashtable.h"
15 #include "nsURIHashKey.h"
16 #include "nsXULPrototypeDocument.h"
17 #include "nsIInputStream.h"
18 #include "nsIStorageStream.h"
19 
20 #include "mozilla/scache/StartupCache.h"
21 
22 namespace mozilla {
23 class CSSStyleSheet;
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 {
36 public:
37     // nsISupports
38     NS_DECL_THREADSAFE_ISUPPORTS
39     NS_DECL_NSIOBSERVER
40 
IsCached(nsIURI * aURI)41     bool IsCached(nsIURI* aURI) {
42         return GetPrototype(aURI) != nullptr;
43     }
44     void AbortCaching();
45 
46 
47     /**
48      * Whether the prototype cache is enabled.
49      */
50     bool IsEnabled();
51 
52     /**
53      * Flush the cache; remove all XUL prototype documents, style
54      * sheets, and scripts.
55      */
56     void Flush();
57 
58 
59     // The following methods are used to put and retrive various items into and
60     // from the cache.
61 
62     nsXULPrototypeDocument* GetPrototype(nsIURI* aURI);
63     nsresult PutPrototype(nsXULPrototypeDocument* aDocument);
64 
65     JSScript* GetScript(nsIURI* aURI);
66     nsresult PutScript(nsIURI* aURI, JS::Handle<JSScript*> aScriptObject);
67 
GetXBLDocumentInfo(nsIURI * aURL)68     nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURL) {
69         return mXBLDocTable.GetWeak(aURL);
70     }
71     nsresult PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo);
72 
73     /**
74      * Get a style sheet by URI. If the style sheet is not in the cache,
75      * returns nullptr.
76      */
GetStyleSheet(nsIURI * aURI)77     mozilla::CSSStyleSheet* GetStyleSheet(nsIURI* aURI) {
78         return mStyleSheetTable.GetWeak(aURI);
79     }
80 
81     /**
82      * Store a style sheet in the cache. The key, style sheet's URI is obtained
83      * from the style sheet itself.
84      */
85     nsresult PutStyleSheet(mozilla::CSSStyleSheet* aStyleSheet);
86 
87     /**
88      * Write the XUL prototype document to a cache file. The proto must be
89      * fully loaded.
90      */
91     nsresult WritePrototype(nsXULPrototypeDocument* aPrototypeDocument);
92 
93     /**
94      * This interface allows partial reads and writes from the buffers in the
95      * startupCache.
96      */
97     nsresult GetInputStream(nsIURI* aURI, nsIObjectInputStream** objectInput);
98     nsresult FinishInputStream(nsIURI* aURI);
99     nsresult GetOutputStream(nsIURI* aURI, nsIObjectOutputStream** objectOutput);
100     nsresult FinishOutputStream(nsIURI* aURI);
101     nsresult HasData(nsIURI* aURI, bool* exists);
102 
103     static nsXULPrototypeCache* GetInstance();
MaybeGetInstance()104     static nsXULPrototypeCache* MaybeGetInstance() { return sInstance; }
105 
ReleaseGlobals()106     static void ReleaseGlobals()
107     {
108         NS_IF_RELEASE(sInstance);
109     }
110 
111     void MarkInCCGeneration(uint32_t aGeneration);
112     void MarkInGC(JSTracer* aTrc);
113     void FlushScripts();
114 protected:
115     friend nsresult
116     NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult);
117 
118     nsXULPrototypeCache();
119     virtual ~nsXULPrototypeCache();
120 
121     static nsXULPrototypeCache* sInstance;
122 
123     void FlushSkinFiles();
124 
125     nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument>   mPrototypeTable; // owns the prototypes
126     nsRefPtrHashtable<nsURIHashKey,mozilla::CSSStyleSheet>   mStyleSheetTable;
127     nsJSThingHashtable<nsURIHashKey, JSScript*>              mScriptTable;
128     nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo>        mXBLDocTable;
129 
130     // URIs already written to the startup cache, to prevent double-caching.
131     nsTHashtable<nsURIHashKey>                               mStartupCacheURITable;
132 
133     nsInterfaceHashtable<nsURIHashKey, nsIStorageStream>     mOutputStreamTable;
134     nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
135 
136     // Bootstrap caching service
137     nsresult BeginCaching(nsIURI* aDocumentURI);
138 };
139 
140 #endif // nsXULPrototypeCache_h__
141