1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 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/. */
7 #ifndef _nsCacheService_h_
8 #define _nsCacheService_h_
10 #include "nsICacheService.h"
11 #include "nsCacheSession.h"
12 #include "nsCacheDevice.h"
13 #include "nsCacheEntry.h"
14 #include "nsThreadUtils.h"
15 #include "nsICacheListener.h"
16 #include "nsIMemoryReporter.h"
19 #include "nsIObserver.h"
22 #include "nsRefPtrHashtable.h"
23 #include "mozilla/CondVar.h"
24 #include "mozilla/Mutex.h"
25 #include "mozilla/Telemetry.h"
28 class nsCacheProfilePrefObserver
;
29 class nsDiskCacheDevice
;
30 class nsMemoryCacheDevice
;
31 class nsOfflineCacheDevice
;
32 class nsCacheServiceAutoLock
;
34 class mozIStorageService
;
37 /******************************************************************************
38 * nsNotifyDoomListener
39 *****************************************************************************/
41 class nsNotifyDoomListener
: public nsRunnable
{
43 nsNotifyDoomListener(nsICacheListener
*listener
,
45 : mListener(listener
) // transfers reference
51 mListener
->OnCacheEntryDoomed(mStatus
);
52 NS_RELEASE(mListener
);
57 nsICacheListener
*mListener
;
61 /******************************************************************************
63 ******************************************************************************/
65 class nsCacheService MOZ_FINAL
: public nsICacheServiceInternal
,
66 public nsIMemoryReporter
68 virtual ~nsCacheService();
71 NS_DECL_THREADSAFE_ISUPPORTS
72 NS_DECL_NSICACHESERVICE
73 NS_DECL_NSICACHESERVICEINTERNAL
74 NS_DECL_NSIMEMORYREPORTER
78 // Define a Create method to be used with a factory:
80 Create(nsISupports
* outer
, const nsIID
& iid
, void* *result
);
84 * Methods called by nsCacheSession
86 static nsresult
OpenCacheEntry(nsCacheSession
* session
,
87 const nsACString
& key
,
88 nsCacheAccessMode accessRequested
,
90 nsICacheListener
* listener
,
91 nsICacheEntryDescriptor
** result
);
93 static nsresult
EvictEntriesForSession(nsCacheSession
* session
);
95 static nsresult
IsStorageEnabledForPolicy(nsCacheStoragePolicy storagePolicy
,
98 static nsresult
DoomEntry(nsCacheSession
*session
,
99 const nsACString
&key
,
100 nsICacheListener
*listener
);
103 * Methods called by nsCacheEntryDescriptor
106 static void CloseDescriptor(nsCacheEntryDescriptor
* descriptor
);
108 static nsresult
GetFileForEntry(nsCacheEntry
* entry
,
111 static nsresult
OpenInputStreamForEntry(nsCacheEntry
* entry
,
112 nsCacheAccessMode mode
,
114 nsIInputStream
** result
);
116 static nsresult
OpenOutputStreamForEntry(nsCacheEntry
* entry
,
117 nsCacheAccessMode mode
,
119 nsIOutputStream
** result
);
121 static nsresult
OnDataSizeChange(nsCacheEntry
* entry
, int32_t deltaSize
);
123 static nsresult
SetCacheElement(nsCacheEntry
* entry
, nsISupports
* element
);
125 static nsresult
ValidateEntry(nsCacheEntry
* entry
);
127 static int32_t CacheCompressionLevel();
129 static bool GetClearingEntries();
131 static void GetCacheBaseDirectoty(nsIFile
** result
);
132 static void GetDiskCacheDirectory(nsIFile
** result
);
133 static void GetAppCacheDirectory(nsIFile
** result
);
136 * Methods called by any cache classes
140 nsCacheService
* GlobalInstance() { return gService
; }
142 static nsresult
DoomEntry(nsCacheEntry
* entry
);
144 static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy
);
147 * Called by disk cache to notify us to use the new max smart size
149 static void MarkStartingFresh();
152 * Methods called by nsApplicationCacheService
155 nsresult
GetOfflineDevice(nsOfflineCacheDevice
** aDevice
);
158 * Creates an offline cache device that works over a specific profile directory.
159 * A tool to preload offline cache for profiles different from the current
160 * application's profile directory.
162 nsresult
GetCustomOfflineDevice(nsIFile
*aProfileDir
,
164 nsOfflineCacheDevice
**aDevice
);
166 // This method may be called to release an object while the cache service
167 // lock is being held. If a non-null target is specified and the target
168 // does not correspond to the current thread, then the release will be
169 // proxied to the specified target. Otherwise, the object will be added to
170 // the list of objects to be released when the cache service is unlocked.
171 static void ReleaseObject_Locked(nsISupports
* object
,
172 nsIEventTarget
* target
= nullptr);
174 static nsresult
DispatchToCacheIOThread(nsIRunnable
* event
);
176 // Calling this method will block the calling thread until all pending
177 // events on the cache-io thread has finished. The calling thread must
178 // hold the cache-lock
179 static nsresult
SyncWithCacheIOThread();
183 * Methods called by nsCacheProfilePrefObserver
185 static void OnProfileShutdown(bool cleanse
);
186 static void OnProfileChanged();
188 static void SetDiskCacheEnabled(bool enabled
);
189 // Sets the disk cache capacity (in kilobytes)
190 static void SetDiskCacheCapacity(int32_t capacity
);
191 // Set max size for a disk-cache entry (in KB). -1 disables limit up to
192 // 1/8th of disk cache size
193 static void SetDiskCacheMaxEntrySize(int32_t maxSize
);
194 // Set max size for a memory-cache entry (in kilobytes). -1 disables
195 // limit up to 90% of memory cache size
196 static void SetMemoryCacheMaxEntrySize(int32_t maxSize
);
198 static void SetOfflineCacheEnabled(bool enabled
);
199 // Sets the offline cache capacity (in kilobytes)
200 static void SetOfflineCacheCapacity(int32_t capacity
);
202 static void SetMemoryCache();
204 static void SetCacheCompressionLevel(int32_t level
);
206 // Starts smart cache size computation if disk device is available
207 static nsresult
SetDiskSmartSize();
209 static void MoveOrRemoveDiskCache(nsIFile
*aOldCacheDir
,
210 nsIFile
*aNewCacheDir
,
211 const char *aCacheSubdir
);
216 static bool IsInitialized()
221 return gService
->mInitialized
;
224 static void AssertOwnsLock()
225 { gService
->mLock
.AssertCurrentThreadOwns(); }
227 static void LeavePrivateBrowsing();
228 bool IsDoomListEmpty();
230 typedef bool (*DoomCheckFn
)(nsCacheEntry
* entry
);
232 // Accessors to the disabled functionality
233 nsresult
CreateSessionInternal(const char * clientID
,
234 nsCacheStoragePolicy storagePolicy
,
236 nsICacheSession
**result
);
237 nsresult
VisitEntriesInternal(nsICacheVisitor
*visitor
);
238 nsresult
EvictEntriesInternal(nsCacheStoragePolicy storagePolicy
);
241 friend class nsCacheServiceAutoLock
;
242 friend class nsOfflineCacheDevice
;
243 friend class nsProcessRequestEvent
;
244 friend class nsSetSmartSizeEvent
;
245 friend class nsBlockOnCacheThreadEvent
;
246 friend class nsSetDiskSmartSizeCallback
;
247 friend class nsDoomEvent
;
248 friend class nsDisableOldMaxSmartSizePrefEvent
;
249 friend class nsDiskCacheMap
;
250 friend class nsAsyncDoomEvent
;
251 friend class nsCacheEntryDescriptor
;
257 static void Lock(::mozilla::Telemetry::ID mainThreadLockerID
);
258 static void Unlock();
262 nsresult
CreateDiskDevice();
263 nsresult
CreateOfflineDevice();
264 nsresult
CreateCustomOfflineDevice(nsIFile
*aProfileDir
,
266 nsOfflineCacheDevice
**aDevice
);
267 nsresult
CreateMemoryDevice();
269 nsresult
RemoveCustomOfflineDevice(nsOfflineCacheDevice
*aDevice
);
271 nsresult
CreateRequest(nsCacheSession
* session
,
272 const nsACString
& clientKey
,
273 nsCacheAccessMode accessRequested
,
275 nsICacheListener
* listener
,
276 nsCacheRequest
** request
);
278 nsresult
DoomEntry_Internal(nsCacheEntry
* entry
,
279 bool doProcessPendingRequests
);
281 nsresult
EvictEntriesForClient(const char * clientID
,
282 nsCacheStoragePolicy storagePolicy
);
284 // Notifies request listener asynchronously on the request's thread, and
285 // releases the descriptor on the request's thread. If this method fails,
286 // the descriptor is not released.
287 nsresult
NotifyListener(nsCacheRequest
* request
,
288 nsICacheEntryDescriptor
* descriptor
,
289 nsCacheAccessMode accessGranted
,
292 nsresult
ActivateEntry(nsCacheRequest
* request
,
293 nsCacheEntry
** entry
,
294 nsCacheEntry
** doomedEntry
);
296 nsCacheDevice
* EnsureEntryHasDevice(nsCacheEntry
* entry
);
298 nsCacheEntry
* SearchCacheDevices(nsCString
* key
, nsCacheStoragePolicy policy
, bool *collision
);
300 void DeactivateEntry(nsCacheEntry
* entry
);
302 nsresult
ProcessRequest(nsCacheRequest
* request
,
303 bool calledFromOpenCacheEntry
,
304 nsICacheEntryDescriptor
** result
);
306 nsresult
ProcessPendingRequests(nsCacheEntry
* entry
);
308 void ClearDoomList(void);
309 void DoomActiveEntries(DoomCheckFn check
);
310 void CloseAllStreams();
311 void FireClearNetworkCacheStoredAnywhereNotification();
314 PLDHashOperator
GetActiveEntries(PLDHashTable
* table
,
315 PLDHashEntryHdr
* hdr
,
319 PLDHashOperator
RemoveActiveEntry(PLDHashTable
* table
,
320 PLDHashEntryHdr
* hdr
,
325 PLDHashOperator
ShutdownCustomCacheDeviceEnum(const nsAString
& aProfileDir
,
326 nsRefPtr
<nsOfflineCacheDevice
>& aDevice
,
328 #if defined(PR_LOGGING)
329 void LogCacheStatistics();
332 nsresult
SetDiskSmartSize_Locked();
338 static nsCacheService
* gService
; // there can be only one...
340 nsCOMPtr
<mozIStorageService
> mStorageService
;
342 nsCacheProfilePrefObserver
* mObserver
;
344 mozilla::Mutex mLock
;
345 mozilla::CondVar mCondVar
;
347 mozilla::Mutex mTimeStampLock
;
348 mozilla::TimeStamp mLockAcquiredTimeStamp
;
350 nsCOMPtr
<nsIThread
> mCacheIOThread
;
352 nsTArray
<nsISupports
*> mDoomedObjects
;
353 nsCOMPtr
<nsITimer
> mSmartSizeTimer
;
356 bool mClearingEntries
;
358 bool mEnableMemoryDevice
;
359 bool mEnableDiskDevice
;
360 bool mEnableOfflineDevice
;
362 nsMemoryCacheDevice
* mMemoryDevice
;
363 nsDiskCacheDevice
* mDiskDevice
;
364 nsOfflineCacheDevice
* mOfflineDevice
;
366 nsRefPtrHashtable
<nsStringHashKey
, nsOfflineCacheDevice
> mCustomOfflineDevices
;
368 nsCacheEntryHashTable mActiveEntries
;
369 PRCList mDoomedEntries
;
373 uint32_t mTotalEntries
;
375 uint32_t mCacheMisses
;
376 uint32_t mMaxKeyLength
;
377 uint32_t mMaxDataSize
;
378 uint32_t mMaxMetaSize
;
380 // Unexpected error totals
381 uint32_t mDeactivateFailures
;
382 uint32_t mDeactivatedUnboundEntries
;
385 /******************************************************************************
386 * nsCacheServiceAutoLock
387 ******************************************************************************/
389 #define LOCK_TELEM(x) \
390 (::mozilla::Telemetry::CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_##x)
392 // Instantiate this class to acquire the cache service lock for a particular
394 class nsCacheServiceAutoLock
{
396 explicit nsCacheServiceAutoLock(mozilla::Telemetry::ID mainThreadLockerID
) {
397 nsCacheService::Lock(mainThreadLockerID
);
399 ~nsCacheServiceAutoLock() {
400 nsCacheService::Unlock();
404 #endif // _nsCacheService_h_