1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/cache/nsCacheService.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,395 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef _nsCacheService_h_ 1.11 +#define _nsCacheService_h_ 1.12 + 1.13 +#include "nsICacheService.h" 1.14 +#include "nsCacheSession.h" 1.15 +#include "nsCacheDevice.h" 1.16 +#include "nsCacheEntry.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "nsICacheListener.h" 1.19 +#include "nsIMemoryReporter.h" 1.20 + 1.21 +#include "prthread.h" 1.22 +#include "nsIObserver.h" 1.23 +#include "nsString.h" 1.24 +#include "nsTArray.h" 1.25 +#include "nsRefPtrHashtable.h" 1.26 +#include "mozilla/CondVar.h" 1.27 +#include "mozilla/Mutex.h" 1.28 +#include "mozilla/Telemetry.h" 1.29 + 1.30 +class nsCacheRequest; 1.31 +class nsCacheProfilePrefObserver; 1.32 +class nsDiskCacheDevice; 1.33 +class nsMemoryCacheDevice; 1.34 +class nsOfflineCacheDevice; 1.35 +class nsCacheServiceAutoLock; 1.36 +class nsITimer; 1.37 +class mozIStorageService; 1.38 + 1.39 + 1.40 +/****************************************************************************** 1.41 + * nsNotifyDoomListener 1.42 + *****************************************************************************/ 1.43 + 1.44 +class nsNotifyDoomListener : public nsRunnable { 1.45 +public: 1.46 + nsNotifyDoomListener(nsICacheListener *listener, 1.47 + nsresult status) 1.48 + : mListener(listener) // transfers reference 1.49 + , mStatus(status) 1.50 + {} 1.51 + 1.52 + NS_IMETHOD Run() 1.53 + { 1.54 + mListener->OnCacheEntryDoomed(mStatus); 1.55 + NS_RELEASE(mListener); 1.56 + return NS_OK; 1.57 + } 1.58 + 1.59 +private: 1.60 + nsICacheListener *mListener; 1.61 + nsresult mStatus; 1.62 +}; 1.63 + 1.64 +/****************************************************************************** 1.65 + * nsCacheService 1.66 + ******************************************************************************/ 1.67 + 1.68 +class nsCacheService : public nsICacheServiceInternal, 1.69 + public nsIMemoryReporter 1.70 +{ 1.71 +public: 1.72 + NS_DECL_THREADSAFE_ISUPPORTS 1.73 + NS_DECL_NSICACHESERVICE 1.74 + NS_DECL_NSICACHESERVICEINTERNAL 1.75 + NS_DECL_NSIMEMORYREPORTER 1.76 + 1.77 + nsCacheService(); 1.78 + virtual ~nsCacheService(); 1.79 + 1.80 + // Define a Create method to be used with a factory: 1.81 + static nsresult 1.82 + Create(nsISupports* outer, const nsIID& iid, void* *result); 1.83 + 1.84 + 1.85 + /** 1.86 + * Methods called by nsCacheSession 1.87 + */ 1.88 + static nsresult OpenCacheEntry(nsCacheSession * session, 1.89 + const nsACString & key, 1.90 + nsCacheAccessMode accessRequested, 1.91 + bool blockingMode, 1.92 + nsICacheListener * listener, 1.93 + nsICacheEntryDescriptor ** result); 1.94 + 1.95 + static nsresult EvictEntriesForSession(nsCacheSession * session); 1.96 + 1.97 + static nsresult IsStorageEnabledForPolicy(nsCacheStoragePolicy storagePolicy, 1.98 + bool * result); 1.99 + 1.100 + static nsresult DoomEntry(nsCacheSession *session, 1.101 + const nsACString &key, 1.102 + nsICacheListener *listener); 1.103 + 1.104 + /** 1.105 + * Methods called by nsCacheEntryDescriptor 1.106 + */ 1.107 + 1.108 + static void CloseDescriptor(nsCacheEntryDescriptor * descriptor); 1.109 + 1.110 + static nsresult GetFileForEntry(nsCacheEntry * entry, 1.111 + nsIFile ** result); 1.112 + 1.113 + static nsresult OpenInputStreamForEntry(nsCacheEntry * entry, 1.114 + nsCacheAccessMode mode, 1.115 + uint32_t offset, 1.116 + nsIInputStream ** result); 1.117 + 1.118 + static nsresult OpenOutputStreamForEntry(nsCacheEntry * entry, 1.119 + nsCacheAccessMode mode, 1.120 + uint32_t offset, 1.121 + nsIOutputStream ** result); 1.122 + 1.123 + static nsresult OnDataSizeChange(nsCacheEntry * entry, int32_t deltaSize); 1.124 + 1.125 + static nsresult SetCacheElement(nsCacheEntry * entry, nsISupports * element); 1.126 + 1.127 + static nsresult ValidateEntry(nsCacheEntry * entry); 1.128 + 1.129 + static int32_t CacheCompressionLevel(); 1.130 + 1.131 + static bool GetClearingEntries(); 1.132 + 1.133 + static void GetCacheBaseDirectoty(nsIFile ** result); 1.134 + static void GetDiskCacheDirectory(nsIFile ** result); 1.135 + static void GetAppCacheDirectory(nsIFile ** result); 1.136 + 1.137 + /** 1.138 + * Methods called by any cache classes 1.139 + */ 1.140 + 1.141 + static 1.142 + nsCacheService * GlobalInstance() { return gService; } 1.143 + 1.144 + static nsresult DoomEntry(nsCacheEntry * entry); 1.145 + 1.146 + static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy); 1.147 + 1.148 + /** 1.149 + * Called by disk cache to notify us to use the new max smart size 1.150 + */ 1.151 + static void MarkStartingFresh(); 1.152 + 1.153 + /** 1.154 + * Methods called by nsApplicationCacheService 1.155 + */ 1.156 + 1.157 + nsresult GetOfflineDevice(nsOfflineCacheDevice ** aDevice); 1.158 + 1.159 + /** 1.160 + * Creates an offline cache device that works over a specific profile directory. 1.161 + * A tool to preload offline cache for profiles different from the current 1.162 + * application's profile directory. 1.163 + */ 1.164 + nsresult GetCustomOfflineDevice(nsIFile *aProfileDir, 1.165 + int32_t aQuota, 1.166 + nsOfflineCacheDevice **aDevice); 1.167 + 1.168 + // This method may be called to release an object while the cache service 1.169 + // lock is being held. If a non-null target is specified and the target 1.170 + // does not correspond to the current thread, then the release will be 1.171 + // proxied to the specified target. Otherwise, the object will be added to 1.172 + // the list of objects to be released when the cache service is unlocked. 1.173 + static void ReleaseObject_Locked(nsISupports * object, 1.174 + nsIEventTarget * target = nullptr); 1.175 + 1.176 + static nsresult DispatchToCacheIOThread(nsIRunnable* event); 1.177 + 1.178 + // Calling this method will block the calling thread until all pending 1.179 + // events on the cache-io thread has finished. The calling thread must 1.180 + // hold the cache-lock 1.181 + static nsresult SyncWithCacheIOThread(); 1.182 + 1.183 + 1.184 + /** 1.185 + * Methods called by nsCacheProfilePrefObserver 1.186 + */ 1.187 + static void OnProfileShutdown(bool cleanse); 1.188 + static void OnProfileChanged(); 1.189 + 1.190 + static void SetDiskCacheEnabled(bool enabled); 1.191 + // Sets the disk cache capacity (in kilobytes) 1.192 + static void SetDiskCacheCapacity(int32_t capacity); 1.193 + // Set max size for a disk-cache entry (in KB). -1 disables limit up to 1.194 + // 1/8th of disk cache size 1.195 + static void SetDiskCacheMaxEntrySize(int32_t maxSize); 1.196 + // Set max size for a memory-cache entry (in kilobytes). -1 disables 1.197 + // limit up to 90% of memory cache size 1.198 + static void SetMemoryCacheMaxEntrySize(int32_t maxSize); 1.199 + 1.200 + static void SetOfflineCacheEnabled(bool enabled); 1.201 + // Sets the offline cache capacity (in kilobytes) 1.202 + static void SetOfflineCacheCapacity(int32_t capacity); 1.203 + 1.204 + static void SetMemoryCache(); 1.205 + 1.206 + static void SetCacheCompressionLevel(int32_t level); 1.207 + 1.208 + // Starts smart cache size computation if disk device is available 1.209 + static nsresult SetDiskSmartSize(); 1.210 + 1.211 + static void MoveOrRemoveDiskCache(nsIFile *aOldCacheDir, 1.212 + nsIFile *aNewCacheDir, 1.213 + const char *aCacheSubdir); 1.214 + 1.215 + nsresult Init(); 1.216 + void Shutdown(); 1.217 + 1.218 + static bool IsInitialized() 1.219 + { 1.220 + if (!gService) { 1.221 + return false; 1.222 + } 1.223 + return gService->mInitialized; 1.224 + } 1.225 + 1.226 + static void AssertOwnsLock() 1.227 + { gService->mLock.AssertCurrentThreadOwns(); } 1.228 + 1.229 + static void LeavePrivateBrowsing(); 1.230 + bool IsDoomListEmpty(); 1.231 + 1.232 + typedef bool (*DoomCheckFn)(nsCacheEntry* entry); 1.233 + 1.234 +private: 1.235 + friend class nsCacheServiceAutoLock; 1.236 + friend class nsOfflineCacheDevice; 1.237 + friend class nsProcessRequestEvent; 1.238 + friend class nsSetSmartSizeEvent; 1.239 + friend class nsBlockOnCacheThreadEvent; 1.240 + friend class nsSetDiskSmartSizeCallback; 1.241 + friend class nsDoomEvent; 1.242 + friend class nsDisableOldMaxSmartSizePrefEvent; 1.243 + friend class nsDiskCacheMap; 1.244 + friend class nsAsyncDoomEvent; 1.245 + friend class nsCacheEntryDescriptor; 1.246 + 1.247 + /** 1.248 + * Internal Methods 1.249 + */ 1.250 + 1.251 + static void Lock(::mozilla::Telemetry::ID mainThreadLockerID); 1.252 + static void Unlock(); 1.253 + void LockAcquired(); 1.254 + void LockReleased(); 1.255 + 1.256 + nsresult CreateDiskDevice(); 1.257 + nsresult CreateOfflineDevice(); 1.258 + nsresult CreateCustomOfflineDevice(nsIFile *aProfileDir, 1.259 + int32_t aQuota, 1.260 + nsOfflineCacheDevice **aDevice); 1.261 + nsresult CreateMemoryDevice(); 1.262 + 1.263 + nsresult RemoveCustomOfflineDevice(nsOfflineCacheDevice *aDevice); 1.264 + 1.265 + nsresult CreateRequest(nsCacheSession * session, 1.266 + const nsACString & clientKey, 1.267 + nsCacheAccessMode accessRequested, 1.268 + bool blockingMode, 1.269 + nsICacheListener * listener, 1.270 + nsCacheRequest ** request); 1.271 + 1.272 + nsresult DoomEntry_Internal(nsCacheEntry * entry, 1.273 + bool doProcessPendingRequests); 1.274 + 1.275 + nsresult EvictEntriesForClient(const char * clientID, 1.276 + nsCacheStoragePolicy storagePolicy); 1.277 + 1.278 + // Notifies request listener asynchronously on the request's thread, and 1.279 + // releases the descriptor on the request's thread. If this method fails, 1.280 + // the descriptor is not released. 1.281 + nsresult NotifyListener(nsCacheRequest * request, 1.282 + nsICacheEntryDescriptor * descriptor, 1.283 + nsCacheAccessMode accessGranted, 1.284 + nsresult error); 1.285 + 1.286 + nsresult ActivateEntry(nsCacheRequest * request, 1.287 + nsCacheEntry ** entry, 1.288 + nsCacheEntry ** doomedEntry); 1.289 + 1.290 + nsCacheDevice * EnsureEntryHasDevice(nsCacheEntry * entry); 1.291 + 1.292 + nsCacheEntry * SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy, bool *collision); 1.293 + 1.294 + void DeactivateEntry(nsCacheEntry * entry); 1.295 + 1.296 + nsresult ProcessRequest(nsCacheRequest * request, 1.297 + bool calledFromOpenCacheEntry, 1.298 + nsICacheEntryDescriptor ** result); 1.299 + 1.300 + nsresult ProcessPendingRequests(nsCacheEntry * entry); 1.301 + 1.302 + void ClearDoomList(void); 1.303 + void DoomActiveEntries(DoomCheckFn check); 1.304 + void CloseAllStreams(); 1.305 + void FireClearNetworkCacheStoredAnywhereNotification(); 1.306 + 1.307 + static 1.308 + PLDHashOperator GetActiveEntries(PLDHashTable * table, 1.309 + PLDHashEntryHdr * hdr, 1.310 + uint32_t number, 1.311 + void * arg); 1.312 + static 1.313 + PLDHashOperator RemoveActiveEntry(PLDHashTable * table, 1.314 + PLDHashEntryHdr * hdr, 1.315 + uint32_t number, 1.316 + void * arg); 1.317 + 1.318 + static 1.319 + PLDHashOperator ShutdownCustomCacheDeviceEnum(const nsAString& aProfileDir, 1.320 + nsRefPtr<nsOfflineCacheDevice>& aDevice, 1.321 + void* aUserArg); 1.322 +#if defined(PR_LOGGING) 1.323 + void LogCacheStatistics(); 1.324 +#endif 1.325 + 1.326 + nsresult SetDiskSmartSize_Locked(); 1.327 + 1.328 + /** 1.329 + * Data Members 1.330 + */ 1.331 + 1.332 + static nsCacheService * gService; // there can be only one... 1.333 + 1.334 + nsCOMPtr<mozIStorageService> mStorageService; 1.335 + 1.336 + nsCacheProfilePrefObserver * mObserver; 1.337 + 1.338 + mozilla::Mutex mLock; 1.339 + mozilla::CondVar mCondVar; 1.340 + 1.341 + mozilla::Mutex mTimeStampLock; 1.342 + mozilla::TimeStamp mLockAcquiredTimeStamp; 1.343 + 1.344 + nsCOMPtr<nsIThread> mCacheIOThread; 1.345 + 1.346 + nsTArray<nsISupports*> mDoomedObjects; 1.347 + nsCOMPtr<nsITimer> mSmartSizeTimer; 1.348 + 1.349 + bool mInitialized; 1.350 + bool mClearingEntries; 1.351 + 1.352 + bool mEnableMemoryDevice; 1.353 + bool mEnableDiskDevice; 1.354 + bool mEnableOfflineDevice; 1.355 + 1.356 + nsMemoryCacheDevice * mMemoryDevice; 1.357 + nsDiskCacheDevice * mDiskDevice; 1.358 + nsOfflineCacheDevice * mOfflineDevice; 1.359 + 1.360 + nsRefPtrHashtable<nsStringHashKey, nsOfflineCacheDevice> mCustomOfflineDevices; 1.361 + 1.362 + nsCacheEntryHashTable mActiveEntries; 1.363 + PRCList mDoomedEntries; 1.364 + 1.365 + // stats 1.366 + 1.367 + uint32_t mTotalEntries; 1.368 + uint32_t mCacheHits; 1.369 + uint32_t mCacheMisses; 1.370 + uint32_t mMaxKeyLength; 1.371 + uint32_t mMaxDataSize; 1.372 + uint32_t mMaxMetaSize; 1.373 + 1.374 + // Unexpected error totals 1.375 + uint32_t mDeactivateFailures; 1.376 + uint32_t mDeactivatedUnboundEntries; 1.377 +}; 1.378 + 1.379 +/****************************************************************************** 1.380 + * nsCacheServiceAutoLock 1.381 + ******************************************************************************/ 1.382 + 1.383 +#define LOCK_TELEM(x) \ 1.384 + (::mozilla::Telemetry::CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_##x) 1.385 + 1.386 +// Instantiate this class to acquire the cache service lock for a particular 1.387 +// execution scope. 1.388 +class nsCacheServiceAutoLock { 1.389 +public: 1.390 + nsCacheServiceAutoLock(mozilla::Telemetry::ID mainThreadLockerID) { 1.391 + nsCacheService::Lock(mainThreadLockerID); 1.392 + } 1.393 + ~nsCacheServiceAutoLock() { 1.394 + nsCacheService::Unlock(); 1.395 + } 1.396 +}; 1.397 + 1.398 +#endif // _nsCacheService_h_