Bug 1117145 - Part 5 - Share the implementation of some of the download item commands. r=jaws draft
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Sun, 14 Feb 2016 17:28:12 +0000
changeset 330930 f66b321a86da8d3d7550a14414dd7f3a81e3f657
parent 330929 613897cae143156ab20438cd5a75198aa4414a99
child 514269 6ecfcd50f2beeefd234bbffc58a7401a367eef57
push id10859
push userpaolo.mozmail@amadzone.org
push dateSun, 14 Feb 2016 17:41:24 +0000
reviewersjaws
bugs1117145
milestone47.0a1
Bug 1117145 - Part 5 - Share the implementation of some of the download item commands. r=jaws MozReview-Commit-ID: La6km3izidY
browser/components/downloads/DownloadsViewUI.jsm
browser/components/downloads/content/allDownloadsViewOverlay.js
browser/components/downloads/content/downloads.js
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -154,17 +154,16 @@ this.DownloadsViewUI.DownloadElementShel
   get statusTextAndTip() {
     return this.rawStatusTextAndTip;
   },
 
   /**
    * Derived objects may call this to get the status text.
    */
   get rawStatusTextAndTip() {
-    const nsIDM = Ci.nsIDownloadManager;
     let s = DownloadsCommon.strings;
 
     let text = "";
     let tip = "";
 
     if (!this.download.stopped) {
       let totalBytes = this.download.hasProgress ? this.download.totalBytes
                                                  : -1;
@@ -226,9 +225,78 @@ this.DownloadsViewUI.DownloadElementShel
 
       let firstPart = s.statusSeparator(stateLabel, displayHost);
       text = s.statusSeparator(firstPart, displayDate);
       tip = s.statusSeparator(fullHost, fullDate);
     }
 
     return { text, tip: tip || text };
   },
+
+  /**
+   * Returns the name of the default command to use for the current state of the
+   * download, when there is a double click or another default interaction. If
+   * there is no default command for the current state, returns an empty string.
+   * The commands are implemented as functions on this object or derived ones.
+   */
+  get currentDefaultCommandName() {
+    switch (DownloadsCommon.stateOfDownload(this.download)) {
+      case Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED:
+        return "downloadsCmd_cancel";
+      case Ci.nsIDownloadManager.DOWNLOAD_FAILED:
+      case Ci.nsIDownloadManager.DOWNLOAD_CANCELED:
+        return "downloadsCmd_retry";
+      case Ci.nsIDownloadManager.DOWNLOAD_PAUSED:
+        return "downloadsCmd_pauseResume";
+      case Ci.nsIDownloadManager.DOWNLOAD_FINISHED:
+        return "downloadsCmd_open";
+      case Ci.nsIDownloadManager.DOWNLOAD_BLOCKED_PARENTAL:
+      case Ci.nsIDownloadManager.DOWNLOAD_DIRTY:
+        return "downloadsCmd_openReferrer";
+    }
+    return "";
+  },
+
+  /**
+   * Returns true if the specified command can be invoked on the current item.
+   * The commands are implemented as functions on this object or derived ones.
+   *
+   * @param aCommand
+   *        Name of the command to check, for example "downloadsCmd_retry".
+   */
+  isCommandEnabled(aCommand) {
+    switch (aCommand) {
+      case "downloadsCmd_retry":
+        return this.download.canceled || this.download.error;
+      case "downloadsCmd_pauseResume":
+        return this.download.hasPartialData && !this.download.error;
+      case "downloadsCmd_openReferrer":
+        return !!this.download.source.referrer;
+      case "downloadsCmd_confirmBlock":
+      case "downloadsCmd_unblock":
+        return this.download.hasBlockedData;
+    }
+    return false;
+  },
+
+  downloadsCmd_cancel() {
+    // This is the correct way to avoid race conditions when cancelling.
+    this.download.cancel().catch(() => {});
+    this.download.removePartialData().catch(Cu.reportError);
+  },
+
+  downloadsCmd_retry() {
+    // Errors when retrying are already reported as download failures.
+    this.download.start().catch(() => {});
+  },
+
+  downloadsCmd_pauseResume() {
+    if (this.download.stopped) {
+      this.download.start();
+    } else {
+      this.download.cancel();
+    }
+  },
+
+  downloadsCmd_confirmBlock() {
+    this.download.confirmBlock().catch(Cu.reportError);
+  },
 };
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -326,32 +326,24 @@ HistoryDownloadElementShell.prototype = 
           let partFile = new FileUtils.File(this.download.target.partFilePath);
           if (partFile.exists()) {
             return true;
           }
         }
 
         // This property is false if the download did not succeed.
         return this.download.target.exists;
-      case "downloadsCmd_pauseResume":
-        return this.download.hasPartialData && !this.download.error;
-      case "downloadsCmd_retry":
-        return this.download.canceled || this.download.error;
-      case "downloadsCmd_openReferrer":
-        return !!this.download.source.referrer;
       case "cmd_delete":
         // We don't want in-progress downloads to be removed accidentally.
         return this.download.stopped;
       case "downloadsCmd_cancel":
         return !!this._sessionDownload;
-      case "downloadsCmd_confirmBlock":
-      case "downloadsCmd_unblock":
-        return this.download.hasBlockedData;
     }
-    return false;
+    return DownloadsViewUI.DownloadElementShell.prototype
+                          .isCommandEnabled.call(this, aCommand);
   },
 
   doCommand(aCommand) {
     if (aCommand.startsWith("cmd_") || aCommand.startsWith("downloadsCmd_")) {
       this[aCommand](this);
     }
   },
 
@@ -364,96 +356,51 @@ HistoryDownloadElementShell.prototype = 
     let file = new FileUtils.File(this.download.target.path);
     DownloadsCommon.showDownloadedFile(file);
   },
 
   downloadsCmd_openReferrer() {
     openURL(this.download.source.referrer);
   },
 
-  downloadsCmd_cancel() {
-    this.download.cancel().catch(() => {});
-    this.download.removePartialData().catch(Cu.reportError);
-  },
-
   cmd_delete() {
     if (this._sessionDownload) {
       DownloadsCommon.removeAndFinalizeDownload(this.download);
     }
     if (this._historyDownload) {
       let uri = NetUtil.newURI(this.download.source.url);
       PlacesUtils.bhistory.removePage(uri);
     }
   },
 
-  downloadsCmd_retry() {
-    // Errors when retrying are already reported as download failures.
-    this.download.start().catch(() => {});
-  },
-
-  downloadsCmd_pauseResume() {
-    // This command is only enabled for session downloads.
-    if (this.download.stopped) {
-      this.download.start();
-    } else {
-      this.download.cancel();
-    }
-  },
-
   downloadsCmd_unblock() {
     DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
                                            window).then((confirmed) => {
       if (confirmed) {
         return this.download.unblock();
       }
     }).catch(Cu.reportError);
   },
 
-  downloadsCmd_confirmBlock() {
-    this.download.confirmBlock().catch(Cu.reportError);
-  },
-
   // Returns whether or not the download handled by this shell should
   // show up in the search results for the given term.  Both the display
   // name for the download and the url are searched.
   matchesSearchTerm(aTerm) {
     if (!aTerm) {
       return true;
     }
     aTerm = aTerm.toLowerCase();
     return this.displayName.toLowerCase().includes(aTerm) ||
            this.download.source.url.toLowerCase().includes(aTerm);
   },
 
   // Handles return keypress on the element (the keypress listener is
   // set in the DownloadsPlacesView object).
   doDefaultCommand() {
-    function getDefaultCommandForState(aState) {
-      switch (aState) {
-        case nsIDM.DOWNLOAD_FINISHED:
-          return "downloadsCmd_open";
-        case nsIDM.DOWNLOAD_PAUSED:
-          return "downloadsCmd_pauseResume";
-        case nsIDM.DOWNLOAD_NOTSTARTED:
-        case nsIDM.DOWNLOAD_QUEUED:
-          return "downloadsCmd_cancel";
-        case nsIDM.DOWNLOAD_FAILED:
-        case nsIDM.DOWNLOAD_CANCELED:
-          return "downloadsCmd_retry";
-        case nsIDM.DOWNLOAD_SCANNING:
-          return "downloadsCmd_show";
-        case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
-        case nsIDM.DOWNLOAD_DIRTY:
-        case nsIDM.DOWNLOAD_BLOCKED_POLICY:
-          return "downloadsCmd_openReferrer";
-      }
-      return "";
-    }
-    let state = DownloadsCommon.stateOfDownload(this.download);
-    let command = getDefaultCommandForState(state);
+    let command = this.currentDefaultCommandName;
     if (command && this.isCommandEnabled(command)) {
       this.doCommand(command);
     }
   },
 
   /**
    * This method is called by the outer download view, after the controller
    * commands have already been updated. In case we did not check for the
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -1067,32 +1067,24 @@ DownloadsViewItem.prototype = {
 
         if (!this.download.target.partFilePath) {
           return false;
         }
 
         let partFile = new FileUtils.File(this.download.target.partFilePath);
         return partFile.exists();
       }
-      case "downloadsCmd_pauseResume":
-        return this.download.hasPartialData && !this.download.error;
-      case "downloadsCmd_retry":
-        return this.download.canceled || this.download.error;
-      case "downloadsCmd_openReferrer":
-        return !!this.download.source.referrer;
       case "cmd_delete":
       case "downloadsCmd_cancel":
       case "downloadsCmd_copyLocation":
       case "downloadsCmd_doDefault":
         return true;
-      case "downloadsCmd_unblock":
-      case "downloadsCmd_confirmBlock":
-        return this.download.hasBlockedData;
     }
-    return false;
+    return DownloadsViewUI.DownloadElementShell.prototype
+                          .isCommandEnabled.call(this, aCommand);
   },
 
   doCommand(aCommand) {
     if (this.isCommandEnabled(aCommand)) {
       this[aCommand](this);
     }
   },
 
@@ -1100,35 +1092,26 @@ DownloadsViewItem.prototype = {
   //// Item commands
 
   cmd_delete() {
     DownloadsCommon.removeAndFinalizeDownload(this.download);
     PlacesUtils.bhistory.removePage(
                            NetUtil.newURI(this.download.source.url));
   },
 
-  downloadsCmd_cancel() {
-    this.download.cancel().catch(() => {});
-    this.download.removePartialData().catch(Cu.reportError);
-  },
-
   downloadsCmd_unblock() {
     DownloadsPanel.hidePanel();
     DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
                                            window).then((confirmed) => {
       if (confirmed) {
         return this.download.unblock();
       }
     }).catch(Cu.reportError);
   },
 
-  downloadsCmd_confirmBlock() {
-    this.download.confirmBlock().catch(Cu.reportError);
-  },
-
   downloadsCmd_open() {
     this.download.launch().catch(Cu.reportError);
 
     // We explicitly close the panel here to give the user the feedback that
     // their click has been received, and we're handling the action.
     // Otherwise, we'd have to wait for the file-type handler to execute
     // before the panel would close. This also helps to prevent the user from
     // accidentally opening a file several times.
@@ -1142,57 +1125,28 @@ DownloadsViewItem.prototype = {
     // We explicitly close the panel here to give the user the feedback that
     // their click has been received, and we're handling the action.
     // Otherwise, we'd have to wait for the operating system file manager
     // window to open before the panel closed. This also helps to prevent the
     // user from opening the containing folder several times.
     DownloadsPanel.hidePanel();
   },
 
-  downloadsCmd_pauseResume() {
-    if (this.download.stopped) {
-      this.download.start();
-    } else {
-      this.download.cancel();
-    }
-  },
-
-  downloadsCmd_retry() {
-    this.download.start().catch(() => {});
-  },
-
   downloadsCmd_openReferrer() {
     openURL(this.download.source.referrer);
   },
 
   downloadsCmd_copyLocation() {
     let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
                     .getService(Ci.nsIClipboardHelper);
     clipboard.copyString(this.download.source.url);
   },
 
   downloadsCmd_doDefault() {
-    const nsIDM = Ci.nsIDownloadManager;
-
-    // Determine the default command for the current item.
-    let defaultCommand = function () {
-      switch (DownloadsCommon.stateOfDownload(this.download)) {
-        case nsIDM.DOWNLOAD_NOTSTARTED:       return "downloadsCmd_cancel";
-        case nsIDM.DOWNLOAD_FINISHED:         return "downloadsCmd_open";
-        case nsIDM.DOWNLOAD_FAILED:           return "downloadsCmd_retry";
-        case nsIDM.DOWNLOAD_CANCELED:         return "downloadsCmd_retry";
-        case nsIDM.DOWNLOAD_PAUSED:           return "downloadsCmd_pauseResume";
-        case nsIDM.DOWNLOAD_QUEUED:           return "downloadsCmd_cancel";
-        case nsIDM.DOWNLOAD_BLOCKED_PARENTAL: return "downloadsCmd_openReferrer";
-        case nsIDM.DOWNLOAD_SCANNING:         return "downloadsCmd_show";
-        case nsIDM.DOWNLOAD_DIRTY:            return "downloadsCmd_openReferrer";
-        case nsIDM.DOWNLOAD_BLOCKED_POLICY:   return "downloadsCmd_openReferrer";
-      }
-      return "";
-    }.apply(this);
+    let defaultCommand = this.currentDefaultCommandName;
     if (defaultCommand && this.isCommandEnabled(defaultCommand)) {
       this.doCommand(defaultCommand);
     }
   },
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsViewController