From 470a4da0015f4f574f3c7d6f6ce46e60cc935b66 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 11 Feb 2013 15:47:21 +0100 Subject: [PATCH] Bug 239254 - [Linux] Support disk cache on a local path, r=michal.novotny --- netwerk/cache/nsCacheService.cpp | 68 ++++++++++++++++++++++++++------ netwerk/cache/nsCacheService.h | 4 ++ startupcache/StartupCache.cpp | 14 +++++++ toolkit/xre/nsXREDirProvider.cpp | 32 +++++++++++---- toolkit/xre/nsXREDirProvider.h | 3 +- 5 files changed, 102 insertions(+), 19 deletions(-) diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index 83032eda8dc..657085ee161 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -719,17 +719,8 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch) if (!directory) directory = profDir; else if (profDir) { - bool same; - if (NS_SUCCEEDED(profDir->Equals(directory, &same)) && !same) { - // We no longer store the cache directory in the main - // profile directory, so we should cleanup the old one. - rv = profDir->AppendNative(NS_LITERAL_CSTRING("Cache")); - if (NS_SUCCEEDED(rv)) { - bool exists; - if (NS_SUCCEEDED(profDir->Exists(&exists)) && exists) - nsDeleteDir::DeleteDir(profDir, false); - } - } + nsCacheService::MoveOrRemoveDiskCache(profDir, directory, + "Cache"); } } // use file cache in build tree only if asked, to avoid cache dir litter @@ -795,6 +786,10 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch) getter_AddRefs(directory)); if (!directory) directory = profDir; + else if (profDir) { + nsCacheService::MoveOrRemoveDiskCache(profDir, directory, + "OfflineCache"); + } } #if DEBUG if (!directory) { @@ -3008,6 +3003,57 @@ nsCacheService::SetDiskSmartSize_Locked() return NS_OK; } +void +nsCacheService::MoveOrRemoveDiskCache(nsIFile *aOldCacheDir, + nsIFile *aNewCacheDir, + const char *aCacheSubdir) +{ + bool same; + if (NS_FAILED(aOldCacheDir->Equals(aNewCacheDir, &same)) || same) + return; + + nsCOMPtr aOldCacheSubdir; + aOldCacheDir->Clone(getter_AddRefs(aOldCacheSubdir)); + + nsresult rv = aOldCacheSubdir->AppendNative( + nsDependentCString(aCacheSubdir)); + if (NS_FAILED(rv)) + return; + + bool exists; + if (NS_FAILED(aOldCacheSubdir->Exists(&exists)) || !exists) + return; + + nsCOMPtr aNewCacheSubdir; + aNewCacheDir->Clone(getter_AddRefs(aNewCacheSubdir)); + + rv = aNewCacheSubdir->AppendNative(nsDependentCString(aCacheSubdir)); + if (NS_FAILED(rv)) + return; + + nsAutoCString newPath; + rv = aNewCacheSubdir->GetNativePath(newPath); + if (NS_FAILED(rv)) + return; + + if (NS_SUCCEEDED(aNewCacheSubdir->Exists(&exists)) && !exists) { + // New cache directory does not exist, try to move the old one here + // rename needs an empty target directory + rv = aNewCacheSubdir->Create(nsIFile::DIRECTORY_TYPE, 0777); + if (NS_SUCCEEDED(rv)) { + nsAutoCString oldPath; + rv = aOldCacheSubdir->GetNativePath(oldPath); + if (NS_FAILED(rv)) + return; + if(rename(oldPath.get(), newPath.get()) == 0) + return; + } + } + + // Delay delete by 1 minute to avoid IO thrash on startup. + nsDeleteDir::DeleteDir(aOldCacheSubdir, false, 60000); +} + static bool IsEntryPrivate(nsCacheEntry* entry) { diff --git a/netwerk/cache/nsCacheService.h b/netwerk/cache/nsCacheService.h index e008b7fa668..46b46ec9ded 100644 --- a/netwerk/cache/nsCacheService.h +++ b/netwerk/cache/nsCacheService.h @@ -196,6 +196,10 @@ public: // Starts smart cache size computation if disk device is available static nsresult SetDiskSmartSize(); + static void MoveOrRemoveDiskCache(nsIFile *aOldCacheDir, + nsIFile *aNewCacheDir, + const char *aCacheSubdir); + nsresult Init(); void Shutdown(); diff --git a/startupcache/StartupCache.cpp b/startupcache/StartupCache.cpp index 934c2c3f583..4c174258252 100644 --- a/startupcache/StartupCache.cpp +++ b/startupcache/StartupCache.cpp @@ -181,6 +181,20 @@ StartupCache::Init() return rv; } + nsCOMPtr profDir; + NS_GetSpecialDirectory("ProfDS", getter_AddRefs(profDir)); + if (profDir) { + bool same; + if (NS_SUCCEEDED(profDir->Equals(file, &same)) && !same) { + // We no longer store the startup cache in the main profile + // directory, so we should cleanup the old one. + if (NS_SUCCEEDED( + profDir->AppendNative(NS_LITERAL_CSTRING("startupCache")))) { + profDir->Remove(true); + } + } + } + rv = file->AppendNative(NS_LITERAL_CSTRING("startupCache")); NS_ENSURE_SUCCESS(rv, rv); diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index e12d89e6c2c..2256ce0556d 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -1142,8 +1142,22 @@ nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal) if (!homeDir || !*homeDir) return NS_ERROR_FAILURE; - rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true, - getter_AddRefs(localDir)); + if (aLocal) { + // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache. + const char* cacheHome = getenv("XDG_CACHE_HOME"); + if (cacheHome && *cacheHome) { + rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true, + getter_AddRefs(localDir)); + } else { + rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true, + getter_AddRefs(localDir)); + if (NS_SUCCEEDED(rv)) + rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache")); + } + } else { + rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true, + getter_AddRefs(localDir)); + } #else #error "Don't know how to get product dir on your platform" #endif @@ -1228,7 +1242,7 @@ nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal, nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal); NS_ENSURE_SUCCESS(rv, rv); - rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName); + rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal); NS_ENSURE_SUCCESS(rv, rv); #ifdef DEBUG_jungshik @@ -1349,7 +1363,8 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, const nsACString* aProfileName, const nsACString* aAppName, - const nsACString* aVendorName) + const nsACString* aVendorName, + PRBool aLocal) { NS_ASSERTION(aFile, "Null pointer!"); @@ -1411,8 +1426,11 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile, rv = aFile->AppendNative(nsDependentCString("mozilla")); NS_ENSURE_SUCCESS(rv, rv); #elif defined(XP_UNIX) - // Make it hidden (i.e. using the ".") - nsAutoCString folder("."); + nsAutoCString folder; + // Make it hidden (by starting with "."), except when local (the + // profile is already under ~/.cache or XDG_CACHE_HOME). + if (!aLocal) + folder.Assign('.'); if (!profile.IsEmpty()) { // Skip any leading path characters @@ -1422,7 +1440,7 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile, // On the off chance that someone wanted their folder to be hidden don't // let it become ".." - if (*profileStart == '.') + if (*profileStart == '.' && !aLocal) profileStart++; folder.Append(profileStart); diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index 77d109f6c88..868cd059323 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -114,7 +114,8 @@ protected: static nsresult AppendProfilePath(nsIFile* aFile, const nsACString* aProfileName, const nsACString* aAppName, - const nsACString* aVendorName); + const nsACString* aVendorName, + PRBool aLocal); static nsresult AppendSysUserExtensionPath(nsIFile* aFile);