/src/mozilla-central/netwerk/cache2/CacheStorageService.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifndef CacheStorageService__h__ |
6 | | #define CacheStorageService__h__ |
7 | | |
8 | | #include "nsICacheStorageService.h" |
9 | | #include "nsIMemoryReporter.h" |
10 | | #include "nsINamed.h" |
11 | | #include "nsITimer.h" |
12 | | #include "nsICacheTesting.h" |
13 | | |
14 | | #include "nsClassHashtable.h" |
15 | | #include "nsDataHashtable.h" |
16 | | #include "nsString.h" |
17 | | #include "nsThreadUtils.h" |
18 | | #include "nsProxyRelease.h" |
19 | | #include "mozilla/Monitor.h" |
20 | | #include "mozilla/Mutex.h" |
21 | | #include "mozilla/Atomics.h" |
22 | | #include "mozilla/TimeStamp.h" |
23 | | #include "nsTArray.h" |
24 | | |
25 | | class nsIURI; |
26 | | class nsICacheEntryDoomCallback; |
27 | | class nsICacheStorageVisitor; |
28 | | class nsIRunnable; |
29 | | class nsIThread; |
30 | | class nsIEventTarget; |
31 | | |
32 | | namespace mozilla { |
33 | | |
34 | | class OriginAttributes; |
35 | | |
36 | | namespace net { |
37 | | |
38 | | class CacheStorageService; |
39 | | class CacheStorage; |
40 | | class CacheEntry; |
41 | | class CacheEntryHandle; |
42 | | |
43 | | class CacheMemoryConsumer |
44 | | { |
45 | | private: |
46 | | friend class CacheStorageService; |
47 | | uint32_t mReportedMemoryConsumption : 30; |
48 | | uint32_t mFlags : 2; |
49 | | |
50 | | private: |
51 | | CacheMemoryConsumer() = delete; |
52 | | |
53 | | protected: |
54 | | enum { |
55 | | // No special treatment, reports always to the disk-entries pool. |
56 | | NORMAL = 0, |
57 | | // This consumer is belonging to a memory-only cache entry, used to decide |
58 | | // which of the two disk and memory pools count this consumption at. |
59 | | MEMORY_ONLY = 1 << 0, |
60 | | // Prevent reports of this consumer at all, used for disk data chunks since |
61 | | // we throw them away as soon as the entry is not used by any consumer and |
62 | | // don't want to make them wipe the whole pool out during their short life. |
63 | | DONT_REPORT = 1 << 1 |
64 | | }; |
65 | | |
66 | | explicit CacheMemoryConsumer(uint32_t aFlags); |
67 | 0 | ~CacheMemoryConsumer() { DoMemoryReport(0); } |
68 | | void DoMemoryReport(uint32_t aCurrentSize); |
69 | | }; |
70 | | |
71 | | class CacheStorageService final : public nsICacheStorageService |
72 | | , public nsIMemoryReporter |
73 | | , public nsITimerCallback |
74 | | , public nsICacheTesting |
75 | | , public nsINamed |
76 | | { |
77 | | public: |
78 | | NS_DECL_THREADSAFE_ISUPPORTS |
79 | | NS_DECL_NSICACHESTORAGESERVICE |
80 | | NS_DECL_NSIMEMORYREPORTER |
81 | | NS_DECL_NSITIMERCALLBACK |
82 | | NS_DECL_NSICACHETESTING |
83 | | NS_DECL_NSINAMED |
84 | | |
85 | | CacheStorageService(); |
86 | | |
87 | | void Shutdown(); |
88 | | void DropPrivateBrowsingEntries(); |
89 | | |
90 | | // Takes care of deleting any pending trashes for both cache1 and cache2 |
91 | | // as well as old cache directory. |
92 | | static void CleaupCacheDirectories(); |
93 | | |
94 | 0 | static CacheStorageService* Self() { return sSelf; } |
95 | 0 | static nsISupports* SelfISupports() { return static_cast<nsICacheStorageService*>(Self()); } |
96 | | nsresult Dispatch(nsIRunnable* aEvent); |
97 | 0 | static bool IsRunning() { return sSelf && !sSelf->mShutdown; } |
98 | | static bool IsOnManagementThread(); |
99 | | already_AddRefed<nsIEventTarget> Thread() const; |
100 | 0 | mozilla::Mutex& Lock() { return mLock; } |
101 | | |
102 | | // Tracks entries that may be forced valid in a pruned hashtable. |
103 | | nsDataHashtable<nsCStringHashKey, TimeStamp> mForcedValidEntries; |
104 | | void ForcedValidEntriesPrune(TimeStamp &now); |
105 | | |
106 | | // Helper thread-safe interface to pass entry info, only difference from |
107 | | // nsICacheStorageVisitor is that instead of nsIURI only the uri spec is |
108 | | // passed. |
109 | | class EntryInfoCallback { |
110 | | public: |
111 | | virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance, |
112 | | int64_t aDataSize, int32_t aFetchCount, |
113 | | uint32_t aLastModifiedTime, uint32_t aExpirationTime, |
114 | | bool aPinned, nsILoadContextInfo* aInfo) = 0; |
115 | | }; |
116 | | |
117 | | // Invokes OnEntryInfo for the given aEntry, synchronously. |
118 | | static void GetCacheEntryInfo(CacheEntry* aEntry, EntryInfoCallback *aVisitor); |
119 | | |
120 | | nsresult GetCacheIndexEntryAttrs(CacheStorage const* aStorage, |
121 | | const nsACString &aURI, |
122 | | const nsACString &aIdExtension, |
123 | | bool *aHasAltData, |
124 | | uint32_t *aFileSizeKb); |
125 | | |
126 | | static uint32_t CacheQueueSize(bool highPriority); |
127 | | |
128 | | // Memory reporting |
129 | | size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; |
130 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; |
131 | | MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) |
132 | | |
133 | | private: |
134 | | virtual ~CacheStorageService(); |
135 | | void ShutdownBackground(); |
136 | | |
137 | | private: |
138 | | // The following methods may only be called on the management |
139 | | // thread. |
140 | | friend class CacheEntry; |
141 | | |
142 | | /** |
143 | | * Registers the entry in management ordered arrays, a mechanism |
144 | | * helping with weighted purge of entries. |
145 | | * Management arrays keep hard reference to the entry. Entry is |
146 | | * responsible to remove it self or the service is responsible to |
147 | | * remove the entry when it's no longer needed. |
148 | | */ |
149 | | void RegisterEntry(CacheEntry* aEntry); |
150 | | |
151 | | /** |
152 | | * Deregisters the entry from management arrays. References are |
153 | | * then released. |
154 | | */ |
155 | | void UnregisterEntry(CacheEntry* aEntry); |
156 | | |
157 | | /** |
158 | | * Removes the entry from the related entry hash table, if still present. |
159 | | */ |
160 | | bool RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced = false); |
161 | | |
162 | | /** |
163 | | * Tells the storage service whether this entry is only to be stored in |
164 | | * memory. |
165 | | */ |
166 | | void RecordMemoryOnlyEntry(CacheEntry* aEntry, |
167 | | bool aOnlyInMemory, |
168 | | bool aOverwrite); |
169 | | |
170 | | /** |
171 | | * Sets a cache entry valid (overrides the default loading behavior by loading |
172 | | * directly from cache) for the given number of seconds |
173 | | * See nsICacheEntry.idl for more details |
174 | | */ |
175 | | void ForceEntryValidFor(nsACString const &aContextKey, |
176 | | nsACString const &aEntryKey, |
177 | | uint32_t aSecondsToTheFuture); |
178 | | |
179 | | /** |
180 | | * Remove the validity info |
181 | | */ |
182 | | void RemoveEntryForceValid(nsACString const &aContextKey, |
183 | | nsACString const &aEntryKey); |
184 | | |
185 | | /** |
186 | | * Retrieves the status of the cache entry to see if it has been forced valid |
187 | | * (so it will loaded directly from cache without further validation) |
188 | | */ |
189 | | bool IsForcedValidEntry(nsACString const &aContextKey, |
190 | | nsACString const &aEntryKey); |
191 | | |
192 | | private: |
193 | | friend class CacheIndex; |
194 | | |
195 | | /** |
196 | | * CacheIndex uses this to prevent a cache entry from being prememptively |
197 | | * thrown away when forced valid |
198 | | * See nsICacheEntry.idl for more details |
199 | | */ |
200 | | bool IsForcedValidEntry(nsACString const &aEntryKeyWithContext); |
201 | | |
202 | | private: |
203 | | // These are helpers for telemetry monitoring of the memory pools. |
204 | | void TelemetryPrune(TimeStamp &now); |
205 | | void TelemetryRecordEntryCreation(CacheEntry const* entry); |
206 | | void TelemetryRecordEntryRemoval(CacheEntry const* entry); |
207 | | |
208 | | private: |
209 | | // Following methods are thread safe to call. |
210 | | friend class CacheStorage; |
211 | | |
212 | | /** |
213 | | * Get, or create when not existing and demanded, an entry for the storage |
214 | | * and uri+id extension. |
215 | | */ |
216 | | nsresult AddStorageEntry(CacheStorage const* aStorage, |
217 | | const nsACString & aURI, |
218 | | const nsACString & aIdExtension, |
219 | | bool aReplace, |
220 | | CacheEntryHandle** aResult); |
221 | | |
222 | | /** |
223 | | * Check existance of an entry. This may throw NS_ERROR_NOT_AVAILABLE |
224 | | * when the information cannot be obtained synchronously w/o blocking. |
225 | | */ |
226 | | nsresult CheckStorageEntry(CacheStorage const* aStorage, |
227 | | const nsACString & aURI, |
228 | | const nsACString & aIdExtension, |
229 | | bool* aResult); |
230 | | |
231 | | /** |
232 | | * Removes the entry from the related entry hash table, if still present |
233 | | * and returns it. |
234 | | */ |
235 | | nsresult DoomStorageEntry(CacheStorage const* aStorage, |
236 | | const nsACString & aURI, |
237 | | const nsACString & aIdExtension, |
238 | | nsICacheEntryDoomCallback* aCallback); |
239 | | |
240 | | /** |
241 | | * Removes and returns entry table for the storage. |
242 | | */ |
243 | | nsresult DoomStorageEntries(CacheStorage const* aStorage, |
244 | | nsICacheEntryDoomCallback* aCallback); |
245 | | |
246 | | /** |
247 | | * Walk all entiries beloging to the storage. |
248 | | */ |
249 | | nsresult WalkStorageEntries(CacheStorage const* aStorage, |
250 | | bool aVisitEntries, |
251 | | nsICacheStorageVisitor* aVisitor); |
252 | | |
253 | | private: |
254 | | friend class CacheFileIOManager; |
255 | | |
256 | | /** |
257 | | * CacheFileIOManager uses this method to notify CacheStorageService that |
258 | | * an active entry was removed. This method is called even if the entry |
259 | | * removal was originated by CacheStorageService. |
260 | | */ |
261 | | void CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo, |
262 | | const nsACString & aIdExtension, |
263 | | const nsACString & aURISpec); |
264 | | |
265 | | /** |
266 | | * Tries to find an existing entry in the hashtables and synchronously call |
267 | | * OnCacheEntryInfo of the aVisitor callback when found. |
268 | | * @retuns |
269 | | * true, when the entry has been found that also implies the callbacks has |
270 | | * beem invoked |
271 | | * false, when an entry has not been found |
272 | | */ |
273 | | bool GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo, |
274 | | const nsACString & aIdExtension, |
275 | | const nsACString & aURISpec, |
276 | | EntryInfoCallback *aCallback); |
277 | | |
278 | | private: |
279 | | friend class CacheMemoryConsumer; |
280 | | |
281 | | /** |
282 | | * When memory consumption of this entry radically changes, this method |
283 | | * is called to reflect the size of allocated memory. This call may purge |
284 | | * unspecified number of entries from memory (but not from disk). |
285 | | */ |
286 | | void OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer, |
287 | | uint32_t aCurrentMemoryConsumption); |
288 | | |
289 | | /** |
290 | | * If not already pending, it schedules mPurgeTimer that fires after 1 second |
291 | | * and dispatches PurgeOverMemoryLimit(). |
292 | | */ |
293 | | void SchedulePurgeOverMemoryLimit(); |
294 | | |
295 | | /** |
296 | | * Called on the management thread, removes all expired and then least used |
297 | | * entries from the memory, first from the disk pool and then from the memory |
298 | | * pool. |
299 | | */ |
300 | | void PurgeOverMemoryLimit(); |
301 | | |
302 | | private: |
303 | | nsresult DoomStorageEntries(const nsACString& aContextKey, |
304 | | nsILoadContextInfo* aContext, |
305 | | bool aDiskStorage, |
306 | | bool aPin, |
307 | | nsICacheEntryDoomCallback* aCallback); |
308 | | nsresult AddStorageEntry(const nsACString& aContextKey, |
309 | | const nsACString & aURI, |
310 | | const nsACString & aIdExtension, |
311 | | bool aWriteToDisk, |
312 | | bool aSkipSizeCheck, |
313 | | bool aPin, |
314 | | bool aReplace, |
315 | | CacheEntryHandle** aResult); |
316 | | |
317 | | nsresult ClearOriginInternal(const nsAString& aOrigin, |
318 | | const mozilla::OriginAttributes& aOriginAttributes, |
319 | | bool aAnonymous); |
320 | | |
321 | | static CacheStorageService* sSelf; |
322 | | |
323 | | mozilla::Mutex mLock; |
324 | | mozilla::Mutex mForcedValidEntriesLock; |
325 | | |
326 | | bool mShutdown; |
327 | | |
328 | | // Accessible only on the service thread |
329 | | class MemoryPool |
330 | | { |
331 | | public: |
332 | | enum EType |
333 | | { |
334 | | DISK, |
335 | | MEMORY, |
336 | | } mType; |
337 | | |
338 | | explicit MemoryPool(EType aType); |
339 | | ~MemoryPool(); |
340 | | |
341 | | nsTArray<RefPtr<CacheEntry> > mFrecencyArray; |
342 | | nsTArray<RefPtr<CacheEntry> > mExpirationArray; |
343 | | Atomic<uint32_t, Relaxed> mMemorySize; |
344 | | |
345 | | bool OnMemoryConsumptionChange(uint32_t aSavedMemorySize, |
346 | | uint32_t aCurrentMemoryConsumption); |
347 | | /** |
348 | | * Purges entries from memory based on the frecency ordered array. |
349 | | */ |
350 | | void PurgeOverMemoryLimit(); |
351 | | void PurgeExpired(); |
352 | | void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat); |
353 | | void PurgeAll(uint32_t aWhat); |
354 | | |
355 | | private: |
356 | | uint32_t Limit() const; |
357 | | MemoryPool() = delete; |
358 | | }; |
359 | | |
360 | | MemoryPool mDiskPool; |
361 | | MemoryPool mMemoryPool; |
362 | | TimeStamp mLastPurgeTime; |
363 | | MemoryPool& Pool(bool aUsingDisk) |
364 | 0 | { |
365 | 0 | return aUsingDisk ? mDiskPool : mMemoryPool; |
366 | 0 | } |
367 | | MemoryPool const& Pool(bool aUsingDisk) const |
368 | 0 | { |
369 | 0 | return aUsingDisk ? mDiskPool : mMemoryPool; |
370 | 0 | } |
371 | | |
372 | | nsCOMPtr<nsITimer> mPurgeTimer; |
373 | | |
374 | | class PurgeFromMemoryRunnable : public Runnable |
375 | | { |
376 | | public: |
377 | | PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat) |
378 | | : Runnable("net::CacheStorageService::PurgeFromMemoryRunnable") |
379 | | , mService(aService) |
380 | | , mWhat(aWhat) |
381 | 0 | { |
382 | 0 | } |
383 | | |
384 | | private: |
385 | 0 | virtual ~PurgeFromMemoryRunnable() = default; |
386 | | |
387 | | NS_IMETHOD Run() override; |
388 | | |
389 | | RefPtr<CacheStorageService> mService; |
390 | | uint32_t mWhat; |
391 | | }; |
392 | | |
393 | | // Used just for telemetry purposes, accessed only on the management thread. |
394 | | // Note: not included in the memory reporter, this is not expected to be huge |
395 | | // and also would be complicated to report since reporting happens on the main |
396 | | // thread but this table is manipulated on the management thread. |
397 | | nsDataHashtable<nsCStringHashKey, mozilla::TimeStamp> mPurgeTimeStamps; |
398 | | |
399 | | // nsICacheTesting |
400 | | class IOThreadSuspender : public Runnable |
401 | | { |
402 | | public: |
403 | | IOThreadSuspender() |
404 | | : Runnable("net::CacheStorageService::IOThreadSuspender") |
405 | | , mMon("IOThreadSuspender") |
406 | | , mSignaled(false) |
407 | 0 | { |
408 | 0 | } |
409 | | void Notify(); |
410 | | private: |
411 | 0 | virtual ~IOThreadSuspender() = default; |
412 | | NS_IMETHOD Run() override; |
413 | | |
414 | | Monitor mMon; |
415 | | bool mSignaled; |
416 | | }; |
417 | | |
418 | | RefPtr<IOThreadSuspender> mActiveIOSuspender; |
419 | | }; |
420 | | |
421 | | template<class T> |
422 | | void ProxyRelease(const char* aName, nsCOMPtr<T> &object, nsIEventTarget* target) |
423 | 0 | { |
424 | 0 | NS_ProxyRelease(aName, target, object.forget()); |
425 | 0 | } Unexecuted instantiation: void mozilla::net::ProxyRelease<nsIApplicationCache>(char const*, nsCOMPtr<nsIApplicationCache>&, nsIEventTarget*) Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheEntryOpenCallback>(char const*, nsCOMPtr<nsICacheEntryOpenCallback>&, nsIEventTarget*) Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheStorageVisitor>(char const*, nsCOMPtr<nsICacheStorageVisitor>&, nsIEventTarget*) Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheEntryDoomCallback>(char const*, nsCOMPtr<nsICacheEntryDoomCallback>&, nsIEventTarget*) |
426 | | |
427 | | template<class T> |
428 | | void ProxyReleaseMainThread(const char* aName, nsCOMPtr<T> &object) |
429 | 0 | { |
430 | 0 | ProxyRelease(aName, object, GetMainThreadEventTarget()); |
431 | 0 | } Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsIApplicationCache>(char const*, nsCOMPtr<nsIApplicationCache>&) Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsICacheStorageVisitor>(char const*, nsCOMPtr<nsICacheStorageVisitor>&) Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsICacheEntryDoomCallback>(char const*, nsCOMPtr<nsICacheEntryDoomCallback>&) |
432 | | |
433 | | } // namespace net |
434 | | } // namespace mozilla |
435 | | |
436 | | #define NS_CACHE_STORAGE_SERVICE_CID \ |
437 | | { 0xea70b098, 0x5014, 0x4e21, \ |
438 | | { 0xae, 0xe1, 0x75, 0xe6, 0xb2, 0xc4, 0xb8, 0xe0 } } \ |
439 | | |
440 | | #define NS_CACHE_STORAGE_SERVICE_CONTRACTID \ |
441 | | "@mozilla.org/netwerk/cache-storage-service;1" |
442 | | |
443 | | #define NS_CACHE_STORAGE_SERVICE_CONTRACTID2 \ |
444 | | "@mozilla.org/network/cache-storage-service;1" |
445 | | |
446 | | #endif |