Bug 709262 - Disable disk cache if the user chooses to sanitize private data on shutdown. r=michal.novotny
authorJosh Matthews <josh@joshmatthews.net>
Mon, 19 Dec 2011 12:18:29 -0500
changeset 84681 b121a045b4514177e9a31d6905ef68d518e94f3d
parent 84680 79b2b83c030ba9049a97e4bf5105cf8c9fa7854f
child 84682 18332142caa51bd7562fcc222c94852fead43e63
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs709262
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 709262 - Disable disk cache if the user chooses to sanitize private data on shutdown. r=michal.novotny
netwerk/cache/nsCacheService.cpp
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
@@ -103,16 +103,19 @@ using namespace mozilla;
 
 #define MEMORY_CACHE_ENABLE_PREF    "browser.cache.memory.enable"
 #define MEMORY_CACHE_CAPACITY_PREF  "browser.cache.memory.capacity"
 #define MEMORY_CACHE_MAX_ENTRY_SIZE_PREF "browser.cache.memory.max_entry_size"
 
 #define CACHE_COMPRESSION_LEVEL_PREF "browser.cache.compression_level"
 #define CACHE_COMPRESSION_LEVEL     1
 
+#define SANITIZE_ON_SHUTDOWN_PREF   "privacy.sanitize.sanitizeOnShutdown"
+#define CLEAR_ON_SHUTDOWN_PREF      "privacy.clearOnShutdown.cache"
+
 static const char * observerList[] = { 
     "profile-before-change",
     "profile-do-change",
     NS_XPCOM_SHUTDOWN_OBSERVER_ID,
     NS_PRIVATE_BROWSING_SWITCH_TOPIC
 };
 static const char * prefList[] = { 
     DISK_CACHE_ENABLE_PREF,
@@ -121,17 +124,19 @@ static const char * prefList[] = {
     DISK_CACHE_DIR_PREF,
     DISK_CACHE_MAX_ENTRY_SIZE_PREF,
     OFFLINE_CACHE_ENABLE_PREF,
     OFFLINE_CACHE_CAPACITY_PREF,
     OFFLINE_CACHE_DIR_PREF,
     MEMORY_CACHE_ENABLE_PREF,
     MEMORY_CACHE_CAPACITY_PREF,
     MEMORY_CACHE_MAX_ENTRY_SIZE_PREF,
-    CACHE_COMPRESSION_LEVEL_PREF
+    CACHE_COMPRESSION_LEVEL_PREF,
+    SANITIZE_ON_SHUTDOWN_PREF,
+    CLEAR_ON_SHUTDOWN_PREF
 };
 
 // Cache sizes, in KB
 const PRInt32 DEFAULT_CACHE_SIZE = 250 * 1024;  // 250 MB
 const PRInt32 MIN_CACHE_SIZE = 50 * 1024;       //  50 MB
 const PRInt32 MAX_CACHE_SIZE = 1024 * 1024;     //   1 GB
 // Default cache size was 50 MB for many years until FF 4:
 const PRInt32 PRE_GECKO_2_0_DEFAULT_CACHE_SIZE = 50 * 1024;
@@ -149,16 +154,18 @@ public:
         , mDiskCacheMaxEntrySize(-1) // -1 means "no limit"
         , mOfflineCacheEnabled(false)
         , mOfflineCacheCapacity(0)
         , mMemoryCacheEnabled(true)
         , mMemoryCacheCapacity(-1)
         , mMemoryCacheMaxEntrySize(-1) // -1 means "no limit"
         , mInPrivateBrowsing(false)
         , mCacheCompressionLevel(CACHE_COMPRESSION_LEVEL)
+        , mSanitizeOnShutdown(false)
+        , mClearCacheOnShutdown(false)
     {
     }
 
     virtual ~nsCacheProfilePrefObserver() {}
     
     nsresult        Install();
     void            Remove();
     nsresult        ReadPrefs(nsIPrefBranch* branch);
@@ -174,16 +181,18 @@ public:
     nsILocalFile *  OfflineCacheParentDirectory()  { return mOfflineCacheParentDirectory; }
     
     bool            MemoryCacheEnabled();
     PRInt32         MemoryCacheCapacity();
     PRInt32         MemoryCacheMaxEntrySize()     { return mMemoryCacheMaxEntrySize; }
 
     PRInt32         CacheCompressionLevel();
 
+    bool            SanitizeAtShutdown() { return mSanitizeOnShutdown && mClearCacheOnShutdown; }
+
     static PRUint32 GetSmartCacheSize(const nsAString& cachePath,
                                       PRUint32 currentSize);
 
 private:
     bool                    PermittedToSmartSize(nsIPrefBranch*, bool firstRun);
     bool                    mHaveProfile;
     
     bool                    mDiskCacheEnabled;
@@ -197,16 +206,19 @@ private:
     
     bool                    mMemoryCacheEnabled;
     PRInt32                 mMemoryCacheCapacity; // in kilobytes
     PRInt32                 mMemoryCacheMaxEntrySize; // in kilobytes
 
     bool                    mInPrivateBrowsing;
 
     PRInt32                 mCacheCompressionLevel;
+
+    bool                    mSanitizeOnShutdown;
+    bool                    mClearCacheOnShutdown;
 };
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
 
 // Runnable sent to main thread after the cache IO thread calculates available
 // disk space, so that there is no race in setting mDiskCacheCapacity.
 class nsSetSmartSizeEvent: public nsRunnable 
 {
@@ -518,16 +530,28 @@ nsCacheProfilePrefObserver::Observe(nsIS
             mMemoryCacheMaxEntrySize = NS_MAX(-1, newMaxSize);
             nsCacheService::SetMemoryCacheMaxEntrySize(mMemoryCacheMaxEntrySize);
         } else if (!strcmp(CACHE_COMPRESSION_LEVEL_PREF, data.get())) {
             mCacheCompressionLevel = CACHE_COMPRESSION_LEVEL;
             (void)branch->GetIntPref(CACHE_COMPRESSION_LEVEL_PREF,
                                      &mCacheCompressionLevel);
             mCacheCompressionLevel = NS_MAX(0, mCacheCompressionLevel);
             mCacheCompressionLevel = NS_MIN(9, mCacheCompressionLevel);
+        } else if (!strcmp(SANITIZE_ON_SHUTDOWN_PREF, data.get())) {
+            rv = branch->GetBoolPref(SANITIZE_ON_SHUTDOWN_PREF,
+                                     &mSanitizeOnShutdown);
+            if (NS_FAILED(rv))
+                return rv;
+            nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
+        } else if (!strcmp(CLEAR_ON_SHUTDOWN_PREF, data.get())) {
+            rv = branch->GetBoolPref(CLEAR_ON_SHUTDOWN_PREF,
+                                     &mClearCacheOnShutdown);
+            if (NS_FAILED(rv))
+                return rv;
+            nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
         }
     } else if (!strcmp(NS_PRIVATE_BROWSING_SWITCH_TOPIC, topic)) {
         if (!strcmp(NS_PRIVATE_BROWSING_ENTER, data.get())) {
             mInPrivateBrowsing = true;
 
             nsCacheService::OnEnterExitPrivateBrowsing();
 
             mDiskCacheEnabled = false;
@@ -815,16 +839,22 @@ nsCacheProfilePrefObserver::ReadPrefs(ns
 
     // read cache compression level pref
     mCacheCompressionLevel = CACHE_COMPRESSION_LEVEL;
     (void)branch->GetIntPref(CACHE_COMPRESSION_LEVEL_PREF,
                              &mCacheCompressionLevel);
     mCacheCompressionLevel = NS_MAX(0, mCacheCompressionLevel);
     mCacheCompressionLevel = NS_MIN(9, mCacheCompressionLevel);
 
+    // read cache shutdown sanitization prefs
+    (void) branch->GetBoolPref(SANITIZE_ON_SHUTDOWN_PREF,
+                               &mSanitizeOnShutdown);
+    (void) branch->GetBoolPref(CLEAR_ON_SHUTDOWN_PREF,
+                               &mClearCacheOnShutdown);
+
     return rv;
 }
 
 nsresult
 nsCacheService::DispatchToCacheIOThread(nsIRunnable* event)
 {
     if (!gService->mCacheIOThread) return NS_ERROR_NOT_AVAILABLE;
     return gService->mCacheIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
@@ -852,17 +882,17 @@ nsCacheService::SyncWithCacheIOThread()
     return rv;
 }
 
 
 bool
 nsCacheProfilePrefObserver::DiskCacheEnabled()
 {
     if ((mDiskCacheCapacity == 0) || (!mDiskCacheParentDirectory))  return false;
-    return mDiskCacheEnabled;
+    return mDiskCacheEnabled && (!mSanitizeOnShutdown || !mClearCacheOnShutdown);
 }
 
 
 bool
 nsCacheProfilePrefObserver::OfflineCacheEnabled()
 {
     if ((mOfflineCacheCapacity == 0) || (!mOfflineCacheParentDirectory))
         return false;
@@ -1091,33 +1121,39 @@ nsCacheService::Init()
 
 
 void
 nsCacheService::Shutdown()
 {
     nsCOMPtr<nsIThread> cacheIOThread;
     Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_SHUTDOWN> totalTimer;
 
+    bool shouldSanitize = false;
+    nsCOMPtr<nsILocalFile> parentDir;
+
     {
     nsCacheServiceAutoLock lock;
     NS_ASSERTION(mInitialized, 
                  "can't shutdown nsCacheService unless it has been initialized.");
 
     if (mInitialized) {
 
         mInitialized = false;
 
         // Clear entries
         ClearDoomList();
         ClearActiveEntries();
 
         // Make sure to wait for any pending cache-operations before
         // proceeding with destructive actions (bug #620660)
         (void) SyncWithCacheIOThread();
-        
+
+        // obtain the disk cache directory in case we need to sanitize it
+        parentDir = mObserver->DiskCacheParentDirectory();
+        shouldSanitize = mObserver->SanitizeAtShutdown();
         mObserver->Remove();
         NS_RELEASE(mObserver);
         
         // unregister memory reporter, before deleting the memory device, just
         // to be safe
         NS_UnregisterMemoryReporter(MemoryCacheReporter);
         MemoryCacheReporter = nsnull;
 
@@ -1136,37 +1172,28 @@ nsCacheService::Shutdown()
 
         mCacheIOThread.swap(cacheIOThread);
     }
     } // lock
 
     if (cacheIOThread)
         cacheIOThread->Shutdown();
 
-    bool finishDeleting = false;
-    nsresult rv;
-    nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
-    if (!branch) {
-        NS_WARNING("Failed to get pref service!");
+    if (shouldSanitize) {
+        nsresult rv = parentDir->AppendNative(NS_LITERAL_CSTRING("Cache"));
+        if (NS_SUCCEEDED(rv)) {
+            bool exists;
+            if (NS_SUCCEEDED(parentDir->Exists(&exists)) && exists)
+                nsDeleteDir::DeleteDir(parentDir, false);
+        }
+        Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_SHUTDOWN_CLEAR_PRIVATE> timer;
+        nsDeleteDir::Shutdown(shouldSanitize);
     } else {
-        bool isSet;
-        rv = branch->GetBoolPref("privacy.sanitize.sanitizeOnShutdown", &isSet);
-        if (NS_SUCCEEDED(rv) && isSet) {
-            rv = branch->GetBoolPref("privacy.clearOnShutdown.cache", &isSet);
-            if (NS_SUCCEEDED(rv) && isSet) {
-                finishDeleting = true;
-            }
-        }
-    }
-    if (finishDeleting) {
-      Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_SHUTDOWN_CLEAR_PRIVATE> timer;
-      nsDeleteDir::Shutdown(finishDeleting);
-    } else {
-      Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_DELETEDIR_SHUTDOWN> timer;
-      nsDeleteDir::Shutdown(finishDeleting);
+        Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_DELETEDIR_SHUTDOWN> timer;
+        nsDeleteDir::Shutdown(shouldSanitize);
     }
 }
 
 
 nsresult
 nsCacheService::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
 {
     nsresult  rv;