Bug 1492404 - Remove all downloads when Fennec asked to sanitize them; r=JanH
authorPetru Lingurar <petru.lingurar@softvision.ro>
Mon, 01 Oct 2018 13:06:56 +0000
changeset 487347 bc16bc807209cc0f2d7610372e026274cdfc3ca7
parent 487346 351f159a3fd8b9bdd6916fb99c795501f1f261e5
child 487348 526b8427a5bfa7b45867f865a83672b5191f7395
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersJanH
bugs1492404
milestone64.0a1
Bug 1492404 - Remove all downloads when Fennec asked to sanitize them; r=JanH Whenever Fennec asks to sanitize downloads all downloads will be deleted, irrespective of their current status (will include in progress downloads). Only when browsingData.removeDownloads WebExtension asks to sanitize downloads we will check to make sure a specific download conforms and can be deleted. Differential Revision: https://phabricator.services.mozilla.com/D6911
mobile/android/chrome/content/browser.js
mobile/android/modules/Sanitizer.jsm
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1574,16 +1574,23 @@ var BrowserApp = {
 
       key = key.replace("private.data.", "");
 
       switch (key) {
         case "cookies_sessions":
           promises.push(Sanitizer.clearItem("cookies"));
           promises.push(Sanitizer.clearItem("sessions"));
           break;
+        case "downloadFiles":
+          // If the user is quiting the app and the downloads are to be sanitized
+          // means he chose to "Clear private data -> Downloads" upon exit so
+          // all downloads will be purged, irrespective of their current state (in progress/error/completed)
+          let clearUnfinishedDownloads = aShutdown === true;
+          promises.push(Sanitizer.clearItem(key, undefined, clearUnfinishedDownloads));
+          break;
         case "openTabs":
           if (aShutdown === true) {
             Services.obs.notifyObservers(null, "browser:purge-session-tabs");
             break;
           }
           // fall-through if aShutdown is false
         default:
           promises.push(Sanitizer.clearItem(key));
--- a/mobile/android/modules/Sanitizer.jsm
+++ b/mobile/android/modules/Sanitizer.jsm
@@ -24,30 +24,32 @@ XPCOMUtils.defineLazyServiceGetters(this
   quotaManagerService: ["@mozilla.org/dom/quota-manager-service;1", "nsIQuotaManagerService"],
 });
 
 
 var EXPORTED_SYMBOLS = ["Sanitizer"];
 
 function Sanitizer() {}
 Sanitizer.prototype = {
-  clearItem: function(aItemName, startTime) {
+  clearItem: function(aItemName, startTime, clearUnfinishedDownloads) {
     // Only a subset of items support deletion with startTime.
     // Those who do not will be rejected with error message.
     if (typeof startTime != "undefined") {
       switch (aItemName) {
         // Normal call to DownloadFiles remove actual data from storage, but our web-extension consumer
         // deletes only download history. So, for this reason we are passing a flag 'deleteFiles'.
         case "downloadHistory":
           return this._clear("downloadFiles", { startTime, deleteFiles: false });
         case "formdata":
           return this._clear(aItemName, { startTime });
         default:
           return Promise.reject({message: `Invalid argument: ${aItemName} does not support startTime argument.`});
       }
+    } else if (aItemName === "downloadFiles" && typeof clearUnfinishedDownloads != "undefined") {
+      return this._clear(aItemName, { clearUnfinishedDownloads });
     } else {
       return this._clear(aItemName);
     }
   },
 
  _clear: function(aItemName, options) {
     let item = this.items[aItemName];
     let canClear = item.canClear;
@@ -311,34 +313,34 @@ Sanitizer.prototype = {
           handleCompletion: function(aReason) { aCallback(aReason == 0 && count > 0); }
         };
         FormHistory.count({}, countDone);
       }
     },
 
     // Adapted from desktop, but heavily modified - see comments below.
     downloadFiles: {
-      clear: Task.async(function* ({ startTime = 0, deleteFiles = true} = {}) {
+      clear: Task.async(function* ({ startTime = 0,
+                                     deleteFiles = true,
+                                     clearUnfinishedDownloads = false } = {}) {
         let refObj = {};
         TelemetryStopwatch.start("FX_SANITIZE_DOWNLOADS", refObj);
 
         let list = yield Downloads.getList(Downloads.ALL);
         let downloads = yield list.getAll();
         var finalizePromises = [];
 
         // Logic copied from DownloadList.removeFinished. Ideally, we would
         // just use that method directly, but we want to be able to remove the
         // downloaded files as well.
         for (let download of downloads) {
-          // Remove downloads that have been canceled, even if the cancellation
-          // operation hasn't completed yet so we don't check "stopped" here.
-          // Failed downloads with partial data are also removed. The startTime
-          // check is provided for addons that may want to delete only recent downloads.
-          if (download.stopped && (!download.hasPartialData || download.error) &&
-              download.startTime.getTime() >= startTime) {
+          let downloadFinished = download.stopped &&
+                                 (!download.hasPartialData || download.error);
+          if ((downloadFinished || clearUnfinishedDownloads) &&
+               download.startTime.getTime() >= startTime) {
             // Remove the download first, so that the views don't get the change
             // notifications that may occur during finalization.
             yield list.remove(download);
             // Ensure that the download is stopped and no partial data is kept.
             // This works even if the download state has changed meanwhile.  We
             // don't need to wait for the procedure to be complete before
             // processing the other downloads in the list.
             finalizePromises.push(download.finalize(true).then(() => null, Cu.reportError));