Bug 1292566 - The "open" button in the subview for uncommon and potentially unwanted downloads should not ask for confirmation. r=Paolo a=ritu
authorDrew Willcoxon <adw@mozilla.com>
Wed, 24 Aug 2016 17:56:44 -0700
changeset 347918 bac8c738419eb9ff1fe0947120e879707d19c97b
parent 347917 0721c01c5e73a9228c27285fa2f422f091153eb2
child 347919 e17961c6b9ae20b89f931ee24430d563847d265d
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersPaolo, ritu
bugs1292566
milestone50.0a2
Bug 1292566 - The "open" button in the subview for uncommon and potentially unwanted downloads should not ask for confirmation. r=Paolo a=ritu MozReview-Commit-ID: AVDyaQSbriX
browser/components/downloads/DownloadsViewUI.jsm
browser/components/downloads/content/downloads.js
browser/components/downloads/content/downloadsOverlay.xul
browser/components/downloads/test/browser/browser_downloads_panel_block.js
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -290,26 +290,35 @@ this.DownloadsViewUI.DownloadElementShel
    */
   confirmUnblock(window, dialogType) {
     DownloadsCommon.confirmUnblockDownload({
       verdict: this.download.error.reputationCheckVerdict,
       window,
       dialogType,
     }).then(action => {
       if (action == "open") {
-        return this.download.unblock().then(() => this.downloadsCmd_open());
+        return this.unblockAndOpenDownload();
       } else if (action == "unblock") {
         return this.download.unblock();
       } else if (action == "confirmBlock") {
         return this.download.confirmBlock();
       }
     }).catch(Cu.reportError);
   },
 
   /**
+   * Unblocks the downloaded file and opens it.
+   *
+   * @return A promise that's resolved after the file has been opened.
+   */
+  unblockAndOpenDownload() {
+    return this.download.unblock().then(() => this.downloadsCmd_open());
+  },
+
+  /**
    * 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:
@@ -343,16 +352,17 @@ this.DownloadsViewUI.DownloadElementShel
       case "downloadsCmd_pauseResume":
         return this.download.hasPartialData && !this.download.error;
       case "downloadsCmd_openReferrer":
         return !!this.download.source.referrer;
       case "downloadsCmd_confirmBlock":
       case "downloadsCmd_chooseUnblock":
       case "downloadsCmd_chooseOpen":
       case "downloadsCmd_unblock":
+      case "downloadsCmd_unblockAndOpen":
         return this.download.hasBlockedData;
     }
     return false;
   },
 
   downloadsCmd_cancel() {
     // This is the correct way to avoid race conditions when cancelling.
     this.download.cancel().catch(() => {});
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -1108,19 +1108,19 @@ DownloadsViewItem.prototype = {
     this.confirmUnblock(window, "unblock");
   },
 
   downloadsCmd_chooseUnblock() {
     DownloadsPanel.hidePanel();
     this.confirmUnblock(window, "chooseUnblock");
   },
 
-  downloadsCmd_chooseOpen() {
+  downloadsCmd_unblockAndOpen() {
     DownloadsPanel.hidePanel();
-    this.confirmUnblock(window, "chooseOpen");
+    this.unblockAndOpenDownload().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
@@ -1195,17 +1195,17 @@ const DownloadsViewController = {
     if (!(aCommand in this) &&
         !(aCommand in DownloadsViewItem.prototype)) {
       return false;
     }
     // The currently supported commands depend on whether the blocked subview is
     // showing.  If it is, then take the following path.
     if (DownloadsBlockedSubview.view.showingSubView) {
       let blockedSubviewCmds = [
-        "downloadsCmd_chooseOpen",
+        "downloadsCmd_unblockAndOpen",
         "cmd_delete",
       ];
       return blockedSubviewCmds.indexOf(aCommand) >= 0;
     }
     // If the blocked subview is not showing, then determine if focus is on a
     // control in the downloads list.
     let element = document.commandDispatcher.focusedElement;
     while (element && element != DownloadsView.richListBox) {
--- a/browser/components/downloads/content/downloadsOverlay.xul
+++ b/browser/components/downloads/content/downloadsOverlay.xul
@@ -20,18 +20,18 @@
     <command id="downloadsCmd_pauseResume"
              oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
     <command id="downloadsCmd_cancel"
              oncommand="goDoCommand('downloadsCmd_cancel')"/>
     <command id="downloadsCmd_unblock"
              oncommand="goDoCommand('downloadsCmd_unblock')"/>
     <command id="downloadsCmd_chooseUnblock"
              oncommand="goDoCommand('downloadsCmd_chooseUnblock')"/>
-    <command id="downloadsCmd_chooseOpen"
-             oncommand="goDoCommand('downloadsCmd_chooseOpen')"/>
+    <command id="downloadsCmd_unblockAndOpen"
+             oncommand="goDoCommand('downloadsCmd_unblockAndOpen')"/>
     <command id="downloadsCmd_confirmBlock"
              oncommand="goDoCommand('downloadsCmd_confirmBlock')"/>
     <command id="downloadsCmd_open"
              oncommand="goDoCommand('downloadsCmd_open')"/>
     <command id="downloadsCmd_show"
              oncommand="goDoCommand('downloadsCmd_show')"/>
     <command id="downloadsCmd_retry"
              oncommand="goDoCommand('downloadsCmd_retry')"/>
@@ -163,17 +163,17 @@
           <description id="downloadsPanel-blockedSubview-details1"/>
           <description id="downloadsPanel-blockedSubview-details2"/>
           <spacer flex="1"/>
           <hbox id="downloadsPanel-blockedSubview-buttons"
                 class="downloadsPanelFooter"
                 align="stretch">
             <button id="downloadsPanel-blockedSubview-openButton"
                     class="plain downloadsPanelFooterButton"
-                    command="downloadsCmd_chooseOpen"
+                    command="downloadsCmd_unblockAndOpen"
                     flex="1"/>
             <toolbarseparator/>
             <button id="downloadsPanel-blockedSubview-deleteButton"
                     class="plain downloadsPanelFooterButton"
                     oncommand="DownloadsBlockedSubview.confirmBlock();"
                     default="true"
                     flex="1"/>
           </hbox>
--- a/browser/components/downloads/test/browser/browser_downloads_panel_block.js
+++ b/browser/components/downloads/test/browser/browser_downloads_panel_block.js
@@ -31,22 +31,25 @@ add_task(function* mainTest() {
     // back to it.
     EventUtils.synthesizeMouse(DownloadsPanel.panel, 10, 10, {}, window);
     yield promiseSubviewShown(false);
 
     // Show the subview again.
     EventUtils.sendMouseEvent({ type: "click" }, item);
     yield promiseSubviewShown(true);
 
-    // Click the Open button.  The alert blocked-download dialog should be
-    // shown.
-    let dialogPromise = promiseAlertDialogOpen("cancel");
+    // Click the Open button.  The download should be unblocked and then opened,
+    // i.e., unblockAndOpenDownload() should be called on the item.  The panel
+    // should also be closed as a result, so wait for that too.
+    let unblockOpenPromise = promiseUnblockAndOpenDownloadCalled(item);
+    let hidePromise = promisePanelHidden();
     EventUtils.synthesizeMouse(DownloadsBlockedSubview.elements.openButton,
                                10, 10, {}, window);
-    yield dialogPromise;
+    yield unblockOpenPromise;
+    yield hidePromise;
 
     window.focus();
     yield SimpleTest.promiseFocus(window);
 
     // Reopen the panel and show the subview again.
     yield openPanel();
 
     EventUtils.sendMouseEvent({ type: "click" }, item);
@@ -160,8 +163,21 @@ function promiseSubviewShown(shown) {
           !DownloadsBlockedSubview.view._transitioning) {
         clearInterval(interval);
         setTimeout(resolve, 1000);
         return;
       }
     }, 0);
   });
 }
+
+function promiseUnblockAndOpenDownloadCalled(item) {
+  return new Promise(resolve => {
+    let realFn = item._shell.unblockAndOpenDownload;
+    item._shell.unblockAndOpenDownload = () => {
+      item._shell.unblockAndOpenDownload = realFn;
+      resolve();
+      // unblockAndOpenDownload returns a promise (that's resolved when the file
+      // is opened).
+      return Promise.resolve();
+    };
+  });
+}