Bug 861894 - Avoid apps to schedule new offline cache downloads while device free space is low. r=honzab
☠☠ backed out by 07f18a9becbe ☠ ☠
authorFernando Jiménez <ferjmoreno@gmail.com>
Fri, 10 May 2013 16:16:56 +0200
changeset 142453 6d2e81a6bf1b17455d76476f5779a04d84d2eb8d
parent 142452 25c04296c67543149fefa4d447c5a689ec8099b6
child 142454 04623bf25b643bfc1527269986ad7ccbd1728776
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs861894
milestone23.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 861894 - Avoid apps to schedule new offline cache downloads while device free space is low. r=honzab
uriloader/prefetch/nsOfflineCacheUpdate.cpp
uriloader/prefetch/nsOfflineCacheUpdate.h
uriloader/prefetch/nsOfflineCacheUpdateService.cpp
--- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
@@ -1773,16 +1773,26 @@ nsOfflineCacheUpdate::Begin()
 {
     LOG(("nsOfflineCacheUpdate::Begin [%p]", this));
 
     // Keep the object alive through a ProcessNextURI()/Finish() call.
     nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
 
     mItemsInProgress = 0;
 
+    if (mState == STATE_CANCELLED) {
+      nsRefPtr<nsRunnableMethod<nsOfflineCacheUpdate> > errorNotification =
+        NS_NewRunnableMethod(this,
+                             &nsOfflineCacheUpdate::AsyncFinishWithError);
+      nsresult rv = NS_DispatchToMainThread(errorNotification);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      return NS_OK;
+    }
+
     if (mPartialUpdate) {
         mState = STATE_DOWNLOADING;
         NotifyState(nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING);
         ProcessNextURI();
         return NS_OK;
     }
 
     // Start checking the manifest.
@@ -2148,16 +2158,23 @@ nsOfflineCacheUpdate::Finish()
 {
     nsresult rv = FinishNoNotify();
 
     NotifyState(nsIOfflineCacheUpdateObserver::STATE_FINISHED);
 
     return rv;
 }
 
+void
+nsOfflineCacheUpdate::AsyncFinishWithError()
+{
+    NotifyState(nsOfflineCacheUpdate::STATE_ERROR);
+    Finish();
+}
+
 static nsresult
 EvictOneOfCacheGroups(nsIApplicationCacheService *cacheService,
                       uint32_t count, const char * const *groups)
 {
     nsresult rv;
     unsigned int i;
 
     for (i = 0; i < count; i++) {
--- a/uriloader/prefetch/nsOfflineCacheUpdate.h
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.h
@@ -234,16 +234,18 @@ private:
     bool CheckUpdateAvailability();
     void NotifyUpdateAvailability(bool updateAvailable);
 
     void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
     void NotifyState(uint32_t state);
     nsresult Finish();
     nsresult FinishNoNotify();
 
+    void AsyncFinishWithError();
+
     // Find one non-pinned cache group and evict it.
     nsresult EvictOneNonPinned();
 
     enum {
         STATE_UNINITIALIZED,
         STATE_INITIALIZED,
         STATE_CHECKING,
         STATE_DOWNLOADING,
@@ -350,11 +352,12 @@ public:
 
 private:
     nsresult ProcessNextUpdate();
 
     nsTArray<nsRefPtr<nsOfflineCacheUpdate> > mUpdates;
 
     bool mDisabled;
     bool mUpdateRunning;
+    bool mLowFreeSpace;
 };
 
 #endif
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -41,16 +41,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsStreamUtils.h"
 #include "nsThreadUtils.h"
 #include "nsProxyRelease.h"
 #include "prlog.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Attributes.h"
+#include "nsIDiskSpaceWatcher.h"
 
 using namespace mozilla;
 
 static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nullptr;
 
 typedef mozilla::docshell::OfflineCacheUpdateParent OfflineCacheUpdateParent;
 typedef mozilla::docshell::OfflineCacheUpdateChild OfflineCacheUpdateChild;
 typedef mozilla::docshell::OfflineCacheUpdateGlue OfflineCacheUpdateGlue;
@@ -256,16 +257,17 @@ NS_IMPL_ISUPPORTS3(nsOfflineCacheUpdateS
 
 //-----------------------------------------------------------------------------
 // nsOfflineCacheUpdateService <public>
 //-----------------------------------------------------------------------------
 
 nsOfflineCacheUpdateService::nsOfflineCacheUpdateService()
     : mDisabled(false)
     , mUpdateRunning(false)
+    , mLowFreeSpace(false)
 {
 }
 
 nsOfflineCacheUpdateService::~nsOfflineCacheUpdateService()
 {
     gOfflineCacheUpdateService = nullptr;
 }
 
@@ -283,16 +285,25 @@ nsOfflineCacheUpdateService::Init()
     if (!observerService)
       return NS_ERROR_FAILURE;
 
     nsresult rv = observerService->AddObserver(this,
                                                NS_XPCOM_SHUTDOWN_OBSERVER_ID,
                                                true);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // Get the current status of the disk in terms of free space and observe
+    // low device storage notifications.
+    nsCOMPtr<nsIDiskSpaceWatcher> diskSpaceWatcherService =
+      do_GetService("@mozilla.org/toolkit/disk-space-watcher;1");
+    diskSpaceWatcherService->GetIsDiskFull(&mLowFreeSpace);
+
+    rv = observerService->AddObserver(this, "disk-space-watcher", false);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     gOfflineCacheUpdateService = this;
 
     return NS_OK;
 }
 
 /* static */
 nsOfflineCacheUpdateService *
 nsOfflineCacheUpdateService::GetInstance()
@@ -403,16 +414,21 @@ nsOfflineCacheUpdateService::ProcessNext
     if (mDisabled)
         return NS_ERROR_ABORT;
 
     if (mUpdateRunning)
         return NS_OK;
 
     if (mUpdates.Length() > 0) {
         mUpdateRunning = true;
+        // Canceling the update before Begin() call will make the update
+        // asynchronously finish with an error.
+        if (mLowFreeSpace) {
+            mUpdates[0]->Cancel();
+        }
         return mUpdates[0]->Begin();
     }
 
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
@@ -594,16 +610,27 @@ nsOfflineCacheUpdateService::Observe(nsI
                                      const PRUnichar *aData)
 {
     if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
         if (mUpdates.Length() > 0)
             mUpdates[0]->Cancel();
         mDisabled = true;
     }
 
+    if (!strcmp(aTopic, "disk-space-watcher")) {
+        if (NS_LITERAL_STRING("full").Equals(aData)) {
+            mLowFreeSpace = true;
+            for (uint32_t i = 0; i < mUpdates.Length(); i++) {
+                mUpdates[i]->Cancel();
+            }
+        } else if (NS_LITERAL_STRING("free").Equals(aData)) {
+            mLowFreeSpace = false;
+        }
+    }
+
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP