From b9c6dbc105d631c2f440e43a8228285e043c1ad1 Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Wed, 14 Mar 2001 03:35:09 +0000 Subject: [PATCH] [not part of build] Using nsIPref::AddObserver() instead of krufty old callbacks. Using directory service to obtain profile directory and using a "profile-do-change" observer to regenerate the cache directory. --- netwerk/cache/src/nsDiskCacheDevice.cpp | 235 ++++++++++++++++-------- netwerk/cache/src/nsDiskCacheDevice.h | 4 + 2 files changed, 159 insertions(+), 80 deletions(-) diff --git a/netwerk/cache/src/nsDiskCacheDevice.cpp b/netwerk/cache/src/nsDiskCacheDevice.cpp index 71174d924e1d..237ed17530c7 100644 --- a/netwerk/cache/src/nsDiskCacheDevice.cpp +++ b/netwerk/cache/src/nsDiskCacheDevice.cpp @@ -27,13 +27,16 @@ #include "nsICacheService.h" #include "nsIFileTransportService.h" -#include "nsDirectoryServiceDefs.h" +#include "nsITransport.h" #include "nsICacheVisitor.h" #include "nsXPIDLString.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" #include "nsISupportsArray.h" -#include "nsITransport.h" +#include "nsDirectoryServiceDefs.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIObserverService.h" +#include "nsIPref.h" static const char DISK_CACHE_DEVICE_ID[] = { "disk" }; @@ -42,43 +45,67 @@ static const char DISK_CACHE_DEVICE_ID[] = { "disk" }; // Using nsIPref will be subsumed with nsIDirectoryService when a selector // for the cache directory has been defined. -#include "nsIPref.h" +#define CACHE_DIR_PREF "browser.newcache.directory" +#define CACHE_DISK_CAPACITY_PREF "browser.cache.disk_cache_size" -static const char CACHE_DIR_PREF[] = { "browser.newcache.directory" }; -static const char CACHE_DISK_CAPACITY[] = { "browser.cache.disk_cache_size" }; +class nsDiskCacheObserver : public nsIObserver { + nsDiskCacheDevice* mDevice; +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER -static int PR_CALLBACK cacheDirectoryChanged(const char *pref, void *closure) + nsDiskCacheObserver(nsDiskCacheDevice * device) + : mDevice(device) + { + } + + virtual ~nsDiskCacheObserver() {} +}; + +NS_IMPL_ISUPPORTS1(nsDiskCacheObserver, nsIObserver); + +NS_IMETHODIMP nsDiskCacheObserver::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData) { - nsresult rv; - NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; + nsresult rv; - nsCOMPtr cacheDirectory; - rv = prefs->GetFileXPref(CACHE_DIR_PREF, getter_AddRefs( cacheDirectory )); - if (NS_FAILED(rv)) - return rv; - - nsDiskCacheDevice* device = NS_STATIC_CAST(nsDiskCacheDevice*, closure); - device->setCacheDirectory(cacheDirectory); - - return NS_OK; -} - -static int PR_CALLBACK cacheCapacityChanged(const char *pref, void *closure) -{ - nsresult rv; - NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - PRInt32 cacheCapacity; - rv = prefs->GetIntPref(CACHE_DISK_CAPACITY, &cacheCapacity); - if (NS_FAILED(rv)) - return rv; - - nsDiskCacheDevice* device = NS_STATIC_CAST(nsDiskCacheDevice*, closure); - device->setCacheCapacity(cacheCapacity); + // did a preference change? + nsLiteralString aTopicString(aTopic); + if (aTopicString.Equals(NS_LITERAL_STRING("nsPref:changed"))) { + // when bug #71879 gets fixed, this QueryInterface will succeed! + nsCOMPtr prefs = do_QueryInterface(aSubject, &rv); + if (!prefs) { + prefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + } + + // which preference changed? + nsLiteralString prefName(someData); + if (prefName.Equals(NS_LITERAL_STRING(CACHE_DIR_PREF))) { + nsCOMPtr cacheDirectory; + rv = prefs->GetFileXPref(CACHE_DIR_PREF, getter_AddRefs(cacheDirectory)); + if (NS_SUCCEEDED(rv)) + mDevice->setCacheDirectory(cacheDirectory); + } else + if (prefName.Equals(NS_LITERAL_STRING(CACHE_DISK_CAPACITY_PREF))) { + PRInt32 cacheCapacity; + rv = prefs->GetIntPref(CACHE_DISK_CAPACITY_PREF, &cacheCapacity); + if (NS_SUCCEEDED(rv)) + mDevice->setCacheCapacity(cacheCapacity); + } + } else if (aTopicString.Equals(NS_LITERAL_STRING("profile-do-change"))) { + // XXX need to regenerate the cache directory. hopefully the + // cache service has already been informed of this change. + nsCOMPtr profileDir; + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, + getter_AddRefs(profileDir)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr cacheDirectory = do_QueryInterface(profileDir); + if (cacheDirectory) { + cacheDirectory->Append("NewCache"); + mDevice->setCacheDirectory(cacheDirectory); + } + } + } return NS_OK; } @@ -93,86 +120,121 @@ static nsresult ensureCacheDirectory(nsIFile * cacheDirectory) return rv; } -static nsresult installPrefListeners(nsDiskCacheDevice* device) +static nsresult installObservers(nsDiskCacheDevice* device) { nsresult rv; - NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - rv = prefs->RegisterCallback(CACHE_DISK_CAPACITY, cacheCapacityChanged, device); + nsCOMPtr observer = new nsDiskCacheObserver(device); + if (!observer) return NS_ERROR_OUT_OF_MEMORY; + + device->setPrefsObserver(observer); + + rv = prefs->AddObserver(CACHE_DISK_CAPACITY_PREF, observer); if (NS_FAILED(rv)) return rv; PRInt32 cacheCapacity; - rv = prefs->GetIntPref(CACHE_DISK_CAPACITY, &cacheCapacity); + rv = prefs->GetIntPref(CACHE_DISK_CAPACITY_PREF, &cacheCapacity); if (NS_FAILED(rv)) { #if DEBUG const PRInt32 kTenMegabytes = 10 * 1024 * 1024; - rv = prefs->SetIntPref(CACHE_DISK_CAPACITY, kTenMegabytes); + rv = prefs->SetIntPref(CACHE_DISK_CAPACITY_PREF, kTenMegabytes); #else return rv; #endif } else { - device->setCacheCapacity(cacheCapacity); + // XXX note the units of the pref seems to be in kilobytes. + device->setCacheCapacity(cacheCapacity * 1024); } - rv = prefs->RegisterCallback(CACHE_DIR_PREF, cacheDirectoryChanged, device); + rv = prefs->AddObserver(CACHE_DIR_PREF, observer); if (NS_FAILED(rv)) return rv; nsCOMPtr cacheDirectory; rv = prefs->GetFileXPref(CACHE_DIR_PREF, getter_AddRefs(cacheDirectory)); if (NS_FAILED(rv)) { + // XXX no preference has been defined, use the directory service. instead. + nsCOMPtr profileDir; + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, + getter_AddRefs(profileDir)); + if (NS_SUCCEEDED(rv)) { + // XXX this path will probably only succeed when running under Mozilla. + // store the new disk cache files in a directory called NewCache + // in the interim. + cacheDirectory = do_QueryInterface(profileDir, &rv); + if (NS_FAILED(rv)) + return rv; + + rv = cacheDirectory->Append("NewCache"); + if (NS_FAILED(rv)) + return rv; + + // XXX since we didn't find a preference, we'll assume that the cache directory + // can only change when profiles change, so remove the prefs listener and install + // a profile listener. + prefs->RemoveObserver(CACHE_DIR_PREF, observer); + + nsCOMPtr observerService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv); + if (observerService) + observerService->AddObserver(observer, NS_LITERAL_STRING("profile-do-change").get()); + } else { #if DEBUG - // XXX use current process directory during development only. - nsCOMPtr currentProcessDir; - rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, - getter_AddRefs(currentProcessDir)); - if (NS_FAILED(rv)) - return rv; + // XXX use current process directory during development only. + nsCOMPtr currentProcessDir; + rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, + getter_AddRefs(currentProcessDir)); + if (NS_FAILED(rv)) + return rv; - cacheDirectory = do_QueryInterface(currentProcessDir, &rv); - if (NS_FAILED(rv)) - return rv; - rv = cacheDirectory->Append("Cache"); - if (NS_FAILED(rv)) - return rv; + cacheDirectory = do_QueryInterface(currentProcessDir, &rv); + if (NS_FAILED(rv)) + return rv; - rv = ensureCacheDirectory(cacheDirectory); - if (NS_FAILED(rv)) - return rv; - - rv = prefs->SetFileXPref(CACHE_DIR_PREF, cacheDirectory); - if (NS_FAILED(rv)) - return rv; + rv = cacheDirectory->Append("Cache"); + if (NS_FAILED(rv)) + return rv; #else - return rv; -#endif - } else { - // always make sure the directory exists, the user may blow it away. - rv = ensureCacheDirectory(cacheDirectory); - if (NS_FAILED(rv)) return rv; - - // cause the preference to be set up initially. - device->setCacheDirectory(cacheDirectory); +#endif + } } + + // always make sure the directory exists, the user may blow it away. + rv = ensureCacheDirectory(cacheDirectory); + if (NS_FAILED(rv)) + return rv; + + // cause the preference to be set up initially. + device->setCacheDirectory(cacheDirectory); return NS_OK; } -static nsresult removePrefListeners(nsDiskCacheDevice* device) +static nsresult removeObservers(nsDiskCacheDevice* device) { - nsresult rv; - NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); - if ( NS_FAILED (rv ) ) - return rv; + nsresult rv; - rv = prefs->UnregisterCallback(CACHE_DIR_PREF, cacheDirectoryChanged, device); - if ( NS_FAILED( rv ) ) - return rv; + nsCOMPtr observer; + device->getPrefsObserver(getter_AddRefs(observer)); + device->setPrefsObserver(nsnull); + NS_ASSERTION(observer, "removePrefListeners"); + if (observer) { + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (prefs) { + prefs->RemoveObserver(CACHE_DISK_CAPACITY_PREF, observer); + prefs->RemoveObserver(CACHE_DIR_PREF, observer); + } + + nsCOMPtr observerService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv); + if (observerService) + observerService->RemoveObserver(observer, NS_LITERAL_STRING("profile-do-change").get()); + } + return NS_OK; } @@ -555,25 +617,28 @@ nsDiskCacheDevice::nsDiskCacheDevice() nsDiskCacheDevice::~nsDiskCacheDevice() { - removePrefListeners(this); + removeObservers(this); // XXX implement poor man's eviction strategy right here, // keep deleting cache entries from oldest to newest, until // cache usage is brought below limits. evictDiskCacheEntries(); + // XXX release the reference to the cached file transport service. gFileTransportService = nsnull; } nsresult nsDiskCacheDevice::Init() { - nsresult rv = installPrefListeners(this); + nsresult rv = installObservers(this); if (NS_FAILED(rv)) return rv; rv = mBoundEntries.Init(); if (NS_FAILED(rv)) return rv; + // XXX cache the file transport service to avoid repeated round trips + // through the service manager. gFileTransportService = do_GetService("@mozilla.org/network/file-transport-service;1", &rv); if (NS_FAILED(rv)) return rv; @@ -794,6 +859,16 @@ nsDiskCacheDevice::Visit(nsICacheVisitor * visitor) return NS_OK; } +void nsDiskCacheDevice::setPrefsObserver(nsIObserver* observer) +{ + mPrefsObserver = observer; +} + +void nsDiskCacheDevice::getPrefsObserver(nsIObserver** result) +{ + NS_IF_ADDREF(*result = mPrefsObserver); +} + void nsDiskCacheDevice::setCacheDirectory(nsILocalFile* cacheDirectory) { mCacheDirectory = cacheDirectory; diff --git a/netwerk/cache/src/nsDiskCacheDevice.h b/netwerk/cache/src/nsDiskCacheDevice.h index 2abf1d7bb4d7..39f498c51ea7 100644 --- a/netwerk/cache/src/nsDiskCacheDevice.h +++ b/netwerk/cache/src/nsDiskCacheDevice.h @@ -27,6 +27,7 @@ #include "nsCacheDevice.h" #include "nsILocalFile.h" #include "nsCacheEntry.h" +#include "nsIObserver.h" class DiskCacheEntry; class nsISupportsArray; @@ -58,6 +59,8 @@ public: virtual nsresult Visit(nsICacheVisitor * visitor); /* private: */ + void setPrefsObserver(nsIObserver* observer); + void getPrefsObserver(nsIObserver ** result); void setCacheDirectory(nsILocalFile* directory); void setCacheCapacity(PRUint32 capacity); PRUint32 getCacheCapacity(); @@ -81,6 +84,7 @@ private: nsresult evictDiskCacheEntries(); private: + nsCOMPtr mPrefsObserver; nsCOMPtr mCacheDirectory; nsCacheEntryHashTable mBoundEntries; PRUint32 mCacheCapacity;