зеркало из https://github.com/mozilla/gecko-dev.git
[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.
This commit is contained in:
Родитель
752a3f6947
Коммит
b9c6dbc105
|
@ -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<nsILocalFile> 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<nsIPref> 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<nsILocalFile> 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<nsIFile> profileDir;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsILocalFile> 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<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = prefs->RegisterCallback(CACHE_DISK_CAPACITY, cacheCapacityChanged, device);
|
||||
nsCOMPtr<nsIObserver> 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<nsILocalFile> 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<nsIFile> 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<nsIObserverService> 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<nsIFile> 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<nsIFile> 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<nsIObserver> observer;
|
||||
device->getPrefsObserver(getter_AddRefs(observer));
|
||||
device->setPrefsObserver(nsnull);
|
||||
NS_ASSERTION(observer, "removePrefListeners");
|
||||
|
||||
if (observer) {
|
||||
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID, &rv);
|
||||
if (prefs) {
|
||||
prefs->RemoveObserver(CACHE_DISK_CAPACITY_PREF, observer);
|
||||
prefs->RemoveObserver(CACHE_DIR_PREF, observer);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> 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;
|
||||
|
|
|
@ -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<nsIObserver> mPrefsObserver;
|
||||
nsCOMPtr<nsILocalFile> mCacheDirectory;
|
||||
nsCacheEntryHashTable mBoundEntries;
|
||||
PRUint32 mCacheCapacity;
|
||||
|
|
Загрузка…
Ссылка в новой задаче