Merge fx-team to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 20 Apr 2016 14:17:46 -0700
changeset 331940 4feb4dd910a5a2d3061dbdd376a80975206819c6
parent 331926 93090fa3065335c9f830e9c70cbfbbc2f40fd979 (current diff)
parent 331939 6a3291366533e40960df1f859d52734f13f3d7a3 (diff)
child 331941 4e3ad95d689a5beabf3c1f41d958794fe00e3767
child 331956 6d48e6b9edc64b919c1055073406bf991a3f16cd
child 332042 898c9f87a4c48c0cbc5d9afe6ced9eb3c71f9388
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.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
Merge fx-team to central, a=merge MozReview-Commit-ID: FKKE7Ry6SbZ
toolkit/themes/osx/global/passwordmgr.css
toolkit/themes/windows/global/passwordmgr.css
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -341,58 +341,20 @@ pref("image.mem.surfacecache.max_size_kb
 pref("image.mem.surfacecache.size_factor", 8);  // 1/8 of main memory
 pref("image.mem.surfacecache.discard_factor", 2);  // Discard 1/2 of the surface cache at a time.
 pref("image.mem.surfacecache.min_expiration_ms", 86400000); // 24h, we rely on the out of memory hook
 
 pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
 pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
 
 #ifdef MOZ_SAFE_BROWSING
-pref("browser.safebrowsing.enabled", true);
-// Prevent loading of pages identified as malware
-pref("browser.safebrowsing.malware.enabled", true);
 pref("browser.safebrowsing.downloads.enabled", true);
 pref("browser.safebrowsing.downloads.remote.enabled", true);
-pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000);
-pref("browser.safebrowsing.downloads.remote.url", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.downloads.remote.block_dangerous",            true);
-pref("browser.safebrowsing.downloads.remote.block_dangerous_host",       true);
-pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
-pref("browser.safebrowsing.downloads.remote.block_uncommon",             false);
-pref("browser.safebrowsing.debug", false);
-
-pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,goog-malware-shavar,goog-unwanted-shavar");
-pref("browser.safebrowsing.provider.google.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.provider.google.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
-pref("browser.safebrowsing.provider.google.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
-
-pref("browser.safebrowsing.reportPhishMistakeURL", "https://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportMalwareMistakeURL", "https://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%&url=");
 
 pref("browser.safebrowsing.id", "Firefox");
-
-// Tables for application reputation.
-pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
-
-// The number of random entries to send with a gethash request.
-pref("urlclassifier.gethashnoise", 4);
-
-// Gethash timeout for Safebrowsing.
-pref("urlclassifier.gethash.timeout_ms", 5000);
-
-// If an urlclassifier table has not been updated in this number of seconds,
-// a gethash request will be forced to check that the result is still in
-// the database.
-pref("urlclassifier.max-complete-age", 2700);
-
-// Tracking protection
-pref("privacy.trackingprotection.enabled", false);
-pref("privacy.trackingprotection.pbmode.enabled", true);
-
 #endif
 
 // True if this is the first time we are showing about:firstrun
 pref("browser.firstrun.show.uidiscovery", true);
 pref("browser.firstrun.show.localepicker", true);
 
 // initiated by a user
 pref("content.ime.strict_policy", true);
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -775,59 +775,29 @@ pref("gecko.handlerService.schemes.ircs.
 pref("gecko.handlerService.schemes.ircs.2.uriTemplate", "chrome://browser-region/locale/region.properties");
 pref("gecko.handlerService.schemes.ircs.3.name", "chrome://browser-region/locale/region.properties");
 pref("gecko.handlerService.schemes.ircs.3.uriTemplate", "chrome://browser-region/locale/region.properties");
 
 // By default, we don't want protocol/content handlers to be registered from a different host, see bug 402287
 pref("gecko.handlerService.allowRegisterFromDifferentHost", false);
 
 #ifdef MOZ_SAFE_BROWSING
-pref("browser.safebrowsing.enabled", true);
-pref("browser.safebrowsing.malware.enabled", true);
 pref("browser.safebrowsing.downloads.enabled", true);
 pref("browser.safebrowsing.downloads.remote.enabled", true);
-pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000);
-pref("browser.safebrowsing.downloads.remote.url", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.downloads.remote.block_dangerous",            true);
-pref("browser.safebrowsing.downloads.remote.block_dangerous_host",       true);
-pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
-pref("browser.safebrowsing.downloads.remote.block_uncommon",             false);
-pref("browser.safebrowsing.debug", false);
-
-pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,goog-malware-shavar,goog-unwanted-shavar");
-pref("browser.safebrowsing.provider.google.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.provider.google.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
-pref("browser.safebrowsing.provider.google.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
-
-pref("browser.safebrowsing.reportPhishMistakeURL", "https://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportMalwareMistakeURL", "https://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%&url=");
 
 #ifdef MOZILLA_OFFICIAL
 // Normally the "client ID" sent in updates is appinfo.name, but for
 // official Firefox releases from Mozilla we use a special identifier.
 pref("browser.safebrowsing.id", "navclient-auto-ffox");
 #endif
 
 // Name of the about: page contributed by safebrowsing to handle display of error
 // pages on phishing/malware hits.  (bug 399233)
 pref("urlclassifier.alternate_error_page", "blocked");
 
-// The number of random entries to send with a gethash request.
-pref("urlclassifier.gethashnoise", 4);
-
-// Gethash timeout for Safebrowsing.
-pref("urlclassifier.gethash.timeout_ms", 5000);
-
-// If an urlclassifier table has not been updated in this number of seconds,
-// a gethash request will be forced to check that the result is still in
-// the database.
-pref("urlclassifier.max-complete-age", 2700);
-// Tables for application reputation.
-pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
 #ifdef XP_WIN
 // Only download the whitelist on Windows, since the whitelist is
 // only useful for suppressing remote lookups for signed binaries which we can
 // only verify on Windows (Bug 974579). Other platforms always do remote lookups.
 pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-digest256");
 #endif
 #endif
 
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -463,23 +463,30 @@
         <menupopup id="bookmarksToolbarFolderPopup"
 #ifndef XP_MACOSX
                    placespopup="true"
 #endif
                    context="placesContext"
                    onpopupshowing="if (!this.parentNode._placesView)
                                      new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
       </menu>
+      <menu id="menu_unsortedBookmarks"
+            class="menu-iconic bookmark-item"
+            label="&otherBookmarksCmd.label;"
+            container="true">
+        <menupopup id="otherBookmarksFolderPopup"
+#ifndef XP_MACOSX
+                   placespopup="true"
+#endif
+                   context="placesContext"
+                   onpopupshowing="if (!this.parentNode._placesView)
+                                     new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS');"/>
+      </menu>
       <menuseparator id="bookmarksMenuItemsSeparator"/>
       <!-- Bookmarks menu items -->
-      <menuseparator builder="end"
-                     class="hide-if-empty-places-result"/>
-      <menuitem id="menu_unsortedBookmarks"
-                label="&otherBookmarksCmd.label;"
-                oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/>
     </menupopup>
   </menu>
 
             <menu id="tools-menu"
                   label="&toolsMenu.label;"
                   accesskey="&toolsMenu.accesskey;"
                   onpopupshowing="mirrorShow(this)">
               <menupopup id="menu_ToolsPopup"
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -523,39 +523,46 @@ this.DownloadsCommon = {
    *
    * @param aVerdict
    *        The detailed reason why the download was blocked, according to the
    *        "Downloads.Error.BLOCK_VERDICT_" constants. If an unknown reason is
    *        specified, "Downloads.Error.BLOCK_VERDICT_MALWARE" is assumed.
    * @param aOwnerWindow
    *        The window with which this action is associated.
    *
-   * @return True to unblock the file, false to keep the user safe and
-   *         cancel the operation.
+   * @return {Promise}
+   * @resolves String representing the action that should be executed:
+   *            - "unblock" to allow the download without opening the file.
+   *            - "confirmBlock" to delete the blocked data permanently.
+   *            - "cancel" to do nothing and cancel the operation.
    */
   confirmUnblockDownload: Task.async(function* (aVerdict, aOwnerWindow) {
     let s = DownloadsCommon.strings;
     let title = s.unblockHeader;
     let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
-                      (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1) +
-                      Ci.nsIPrompt.BUTTON_POS_1_DEFAULT;
+                      (Ci.nsIPrompt.BUTTON_TITLE_CANCEL * Ci.nsIPrompt.BUTTON_POS_1);
     let type = "";
     let message = s.unblockTip;
-    let okButton = s.unblockButtonContinue;
-    let cancelButton = s.unblockButtonCancel;
+    let unblockButton = s.unblockButtonContinue;
+    let confirmBlockButton = s.unblockButtonCancel;
 
     switch (aVerdict) {
       case Downloads.Error.BLOCK_VERDICT_UNCOMMON:
         type = s.unblockTypeUncommon;
+        buttonFlags += (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_2) +
+                       Ci.nsIPrompt.BUTTON_POS_0_DEFAULT;
         break;
       case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
         type = s.unblockTypePotentiallyUnwanted;
+        buttonFlags += (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_2) +
+                       Ci.nsIPrompt.BUTTON_POS_2_DEFAULT;
         break;
       default: // Assume Downloads.Error.BLOCK_VERDICT_MALWARE
         type = s.unblockTypeMalware;
+        buttonFlags += Ci.nsIPrompt.BUTTON_POS_1_DEFAULT;
         break;
     }
 
     if (type) {
       message = type + "\n\n" + message;
     }
 
     Services.ww.registerNotification(function onOpen(subj, topic) {
@@ -575,18 +582,19 @@ this.DownloadsCommon = {
           }
         });
       }
     });
 
     // The ordering of the ok/cancel buttons is used this way to allow "cancel"
     // to have the same result as hitting the ESC or Close button (see bug 345067).
     let rv = Services.prompt.confirmEx(aOwnerWindow, title, message, buttonFlags,
-                                       okButton, cancelButton, null, null, {});
-    return (rv == 0);
+                                       unblockButton, null, confirmBlockButton,
+                                       null, {});
+    return ["unblock", "cancel", "confirmBlock"][rv];
   }),
 };
 
 XPCOMUtils.defineLazyGetter(this.DownloadsCommon, "log", () => {
   return DownloadsLogger.log.bind(DownloadsLogger);
 });
 XPCOMUtils.defineLazyGetter(this.DownloadsCommon, "error", () => {
   return DownloadsLogger.error.bind(DownloadsLogger);
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -12,16 +12,18 @@
 this.EXPORTED_SYMBOLS = [
   "DownloadsViewUI",
 ];
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
+                                  "resource://gre/modules/Downloads.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
                                   "resource://gre/modules/DownloadUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
                                   "resource:///modules/DownloadsCommon.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 
 this.DownloadsViewUI = {
@@ -107,16 +109,24 @@ this.DownloadsViewUI.DownloadElementShel
    * update in order to improve performance.
    */
   _updateState() {
     this.element.setAttribute("displayName", this.displayName);
     this.element.setAttribute("image", this.image);
     this.element.setAttribute("state",
                               DownloadsCommon.stateOfDownload(this.download));
 
+    if (this.download.error &&
+        this.download.error.becauseBlockedByReputationCheck) {
+      this.element.setAttribute("verdict",
+                                this.download.error.reputationCheckVerdict);
+    } else {
+      this.element.removeAttribute("verdict");
+    }
+
     // Since state changed, reset the time left estimation.
     this.lastEstimatedSecondsLeft = Infinity;
 
     this._updateProgress();
   },
 
   /**
    * Updates the elements that change regularly for in-progress downloads,
@@ -127,16 +137,21 @@ this.DownloadsViewUI.DownloadElementShel
       // We only need to add or remove this attribute for succeeded downloads.
       if (this.download.target.exists) {
         this.element.setAttribute("exists", "true");
       } else {
         this.element.removeAttribute("exists");
       }
     }
 
+    // When a block is confirmed, the removal of blocked data will not trigger a
+    // state change for the download, so this class must be updated here.
+    this.element.classList.toggle("temporary-block",
+                                  !!this.download.hasBlockedData);
+
     // The progress bar is only displayed for in-progress downloads.
     if (this.download.hasProgress) {
       this.element.setAttribute("progressmode", "normal");
       this.element.setAttribute("progress", this.download.progress);
     } else {
       this.element.setAttribute("progressmode", "undetermined");
     }
 
@@ -215,17 +230,27 @@ this.DownloadsViewUI.DownloadElementShel
           // History downloads may not have a size defined.
           stateLabel = s.sizeUnknown;
         }
       } else if (this.download.canceled) {
         stateLabel = s.stateCanceled;
       } else if (this.download.error.becauseBlockedByParentalControls) {
         stateLabel = s.stateBlockedParentalControls;
       } else if (this.download.error.becauseBlockedByReputationCheck) {
-        stateLabel = s.stateDirty;
+        switch (this.download.error.reputationCheckVerdict) {
+          case Downloads.Error.BLOCK_VERDICT_UNCOMMON:
+            stateLabel = s.blockedUncommon;
+            break;
+          case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
+            stateLabel = s.blockedPotentiallyUnwanted;
+            break;
+          default: // Assume Downloads.Error.BLOCK_VERDICT_MALWARE
+            stateLabel = s.blockedMalware;
+            break;
+        }
       } else {
         stateLabel = s.stateFailed;
       }
 
       let referrer = this.download.source.referrer || this.download.source.url;
       let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
 
       let date = new Date(this.download.endTime);
@@ -235,16 +260,35 @@ this.DownloadsViewUI.DownloadElementShel
       text = s.statusSeparator(firstPart, displayDate);
       tip = s.statusSeparator(fullHost, fullDate);
     }
 
     return { text, tip: tip || text };
   },
 
   /**
+   * Shows the appropriate unblock dialog based on the verdict, and executes the
+   * action selected by the user in the dialog, which may involve unblocking,
+   * opening or removing the file.
+   *
+   * @param window
+   *        The window to which the dialog should be anchored.
+   */
+  confirmUnblock(window) {
+    let verdict = this.download.error.reputationCheckVerdict;
+    DownloadsCommon.confirmUnblockDownload(verdict, window).then(action => {
+      if (action == "unblock") {
+        return this.download.unblock();
+      } else if (action == "confirmBlock") {
+        return this.download.confirmBlock();
+      }
+    }).catch(Cu.reportError);
+  },
+
+  /**
    * 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:
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -293,19 +293,17 @@ HistoryDownloadElementShell.prototype = 
       status.text = status.tip;
     }
     status.tip = "";
 
     return status;
   },
 
   onStateChanged() {
-    this.element.setAttribute("image", this.image);
-    this.element.setAttribute("state",
-                              DownloadsCommon.stateOfDownload(this.download));
+    this._updateState();
 
     if (this.element.selected) {
       goUpdateDownloadCommands();
     } else {
       goUpdateCommand("downloadsCmd_clearDownloads");
     }
   },
 
@@ -374,22 +372,17 @@ HistoryDownloadElementShell.prototype = 
     }
     if (this._historyDownload) {
       let uri = NetUtil.newURI(this.download.source.url);
       PlacesUtils.bhistory.removePage(uri);
     }
   },
 
   downloadsCmd_unblock() {
-    let verdict = this.download.error.reputationCheckVerdict;
-    DownloadsCommon.confirmUnblockDownload(verdict, window).then(confirmed => {
-      if (confirmed) {
-        return this.download.unblock();
-      }
-    }).catch(Cu.reportError);
+    this.confirmUnblock(window);
   },
 
   // 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;
--- a/browser/components/downloads/content/download.xml
+++ b/browser/components/downloads/content/download.xml
@@ -42,32 +42,35 @@
                            min="0"
                            max="100"
                            xbl:inherits="mode=progressmode,value=progress"/>
         <xul:description class="downloadDetails"
                          crop="end"
                          xbl:inherits="value=status,tooltiptext=statusTip"/>
       </xul:vbox>
       <xul:stack>
-        <xul:button class="downloadButton downloadCancel"
+        <xul:button class="downloadButton downloadCancel downloadIconCancel"
                     tooltiptext="&cmd.cancel.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
-        <xul:button class="downloadButton downloadRetry"
+        <xul:button class="downloadButton downloadRetry downloadIconRetry"
                     tooltiptext="&cmd.retry.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_retry');"/>
-        <xul:button class="downloadButton downloadShow"
+        <xul:button class="downloadButton downloadShow downloadIconShow"
 #ifdef XP_MACOSX
                     tooltiptext="&cmd.showMac.label;"
 #else
                     tooltiptext="&cmd.show.label;"
 #endif
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_show');"/>
-        <xul:button class="downloadButton downloadConfirmBlock"
+        <xul:button class="downloadButton downloadConfirmBlock downloadIconCancel"
                     tooltiptext="&cmd.removeFile.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_confirmBlock');"/>
+        <xul:button class="downloadButton downloadUnblock downloadIconShow"
+                    tooltiptext="&cmd.unblock.label;"
+                    oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_unblock');"/>
       </xul:stack>
     </content>
   </binding>
 
   <binding id="download-toolbarbutton"
            extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
     <content>
       <children />
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -113,21 +113,32 @@ richlistitem.download button {
 
 .download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
                               [state="5"], /* Starting (queued)  */
                               [state="0"], /* Downloading        */
                               [state="4"]) /* Paused             */)
                                            .downloadCancel,
 
 /* Blocked (dirty) downloads that have not been confirmed and
-   have temporary data. */
+   have temporary data, for the Malware case. */
 .download-state:not(          [state="8"]  /* Blocked (dirty)    */)
                                            .downloadConfirmBlock,
 .download-state[state="8"]:not(.temporary-block)
                                            .downloadConfirmBlock,
+.download-state[state="8"].temporary-block:not([verdict="Malware"])
+                                           .downloadConfirmBlock,
+
+/* Blocked (dirty) downloads that have not been confirmed and
+   have temporary data, for cases other than Malware. */
+.download-state:not(          [state="8"]  /* Blocked (dirty)    */)
+                                           .downloadUnblock,
+.download-state[state="8"]:not(.temporary-block)
+                                           .downloadUnblock,
+.download-state[state="8"].temporary-block[verdict="Malware"]
+                                           .downloadUnblock,
 
 .download-state:not(:-moz-any([state="2"], /* Failed             */
                               [state="3"]) /* Canceled           */)
                                            .downloadRetry,
 
 .download-state:not(          [state="1"]  /* Finished           */)
                                            .downloadShow
 
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -1030,27 +1030,20 @@ DownloadsViewItem.prototype = {
   __proto__: DownloadsViewUI.DownloadElementShell.prototype,
 
   /**
    * The XUL element corresponding to the associated richlistbox item.
    */
   _element: null,
 
   onStateChanged() {
-    this.element.setAttribute("image", this.image);
-    this.element.setAttribute("state",
-                              DownloadsCommon.stateOfDownload(this.download));
+    this._updateState();
   },
 
   onChanged() {
-    // This cannot be placed within onStateChanged because
-    // when a download goes from hasBlockedData to !hasBlockedData
-    // it will still remain in the same state.
-    this.element.classList.toggle("temporary-block",
-                                  !!this.download.hasBlockedData);
     this._updateProgress();
   },
 
   isCommandEnabled(aCommand) {
     switch (aCommand) {
       case "downloadsCmd_open": {
         if (!this.download.succeeded) {
           return false;
@@ -1094,22 +1087,17 @@ DownloadsViewItem.prototype = {
   cmd_delete() {
     DownloadsCommon.removeAndFinalizeDownload(this.download);
     PlacesUtils.bhistory.removePage(
                            NetUtil.newURI(this.download.source.url));
   },
 
   downloadsCmd_unblock() {
     DownloadsPanel.hidePanel();
-    let verdict = this.download.error.reputationCheckVerdict;
-    DownloadsCommon.confirmUnblockDownload(verdict, window).then(confirmed => {
-      if (confirmed) {
-        return this.download.unblock();
-      }
-    }).catch(Cu.reportError);
+    this.confirmUnblock(window);
   },
 
   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
--- a/browser/components/downloads/test/browser/browser_confirm_unblock_download.js
+++ b/browser/components/downloads/test/browser/browser_confirm_unblock_download.js
@@ -30,17 +30,17 @@ function addDialogOpenObserver(buttonAct
     }
   });
 }
 
 add_task(function* test_confirm_unblock_dialog_unblock() {
   addDialogOpenObserver("accept");
   let result = yield DownloadsCommon.confirmUnblockDownload(Downloads.Error.BLOCK_VERDICT_MALWARE,
                                                             window);
-  ok(result, "Should return true when the user clicks on `Unblock` button.");
+  is(result, "unblock");
 });
 
 add_task(function* test_confirm_unblock_dialog_keep_safe() {
   addDialogOpenObserver("cancel");
   let result = yield DownloadsCommon.confirmUnblockDownload(Downloads.Error.BLOCK_VERDICT_MALWARE,
                                                             window);
-  ok(!result, "Should return false when the user clicks on `Keep me safe` button.");
+  is(result, "cancel");
 });
--- a/browser/themes/linux/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/linux/downloads/allDownloadsViewOverlay.css
@@ -6,95 +6,95 @@
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 5em;
 }
 
 .blockedIcon {
-  list-style-image: url("moz-icon://stock/gtk-dialog-error?size=dialog");
+  list-style-image: url("moz-icon://stock/gtk-dialog-error?size=32");
+}
+
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("moz-icon://stock/gtk-dialog-warning?size=32");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("moz-icon://stock/gtk-dialog-info?size=32");
 }
 
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
-@itemFocused@ .downloadButton.downloadConfirmBlock,
-@itemFocused@ .downloadButton.downloadCancel {
+@itemFocused@ .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 80px, 16px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock,
-@itemFocused@:hover .downloadButton.downloadCancel {
+@itemFocused@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 96px, 16px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-@itemFocused@:hover .downloadButton.downloadCancel:hover {
+@itemFocused@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 112px, 16px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-@itemFocused@:hover .downloadButton.downloadCancel:active {
+@itemFocused@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 128px, 16px, 112px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@item@:hover .downloadButton.downloadShow {
+@item@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-@item@:hover .downloadButton.downloadShow:hover {
+@item@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
-@item@:hover .downloadButton.downloadShow:active {
+@item@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 64px, 32px, 48px);
 }
-@itemFocused@ .downloadButton.downloadShow {
+@itemFocused@ .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 80px, 32px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadShow {
+@itemFocused@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 96px, 32px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadShow:hover {
+@itemFocused@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 112px, 32px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadShow:active {
+@itemFocused@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 128px, 32px, 112px);
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
-@itemFocused@ .downloadButton.downloadRetry {
+@itemFocused@ .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 80px, 48px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry {
+@itemFocused@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 96px, 48px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry:hover {
+@itemFocused@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 112px, 48px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry:active {
+@itemFocused@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 128px, 48px, 112px);
 }
--- a/browser/themes/linux/downloads/downloads.css
+++ b/browser/themes/linux/downloads/downloads.css
@@ -32,17 +32,25 @@
   --downloads-item-border-bottom-color: hsla(0,0%,0%,.15);
   --downloads-item-font-size-factor: 0.9;
   --downloads-item-target-margin-bottom: 7px;
   --downloads-item-details-margin-top: 1px;
   --downloads-item-details-opacity: 0.6;
 }
 
 .blockedIcon {
-  list-style-image: url("moz-icon://stock/gtk-dialog-error?size=dialog");
+  list-style-image: url("moz-icon://stock/gtk-dialog-error?size=32");
+}
+
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("moz-icon://stock/gtk-dialog-warning?size=32");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("moz-icon://stock/gtk-dialog-info?size=32");
 }
 
 .downloadButton:focus > .button-box {
   outline: 1px -moz-dialogtext dotted;
 }
 
 /*** Highlighted list items ***/
 
@@ -58,50 +66,55 @@
   background-color: Highlight;
   background-image: linear-gradient(hsla(0,0%,100%,.1), transparent);
   color: HighlightText;
   cursor: pointer;
 }
 
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow {
+@itemNotFinished@:hover .downloadButton.downloadIconShow {
+  -moz-image-region: rect(16px, 32px, 32px, 16px);
+}
+@itemNotFinished@:hover .downloadButton.downloadIconShow:hover {
+  -moz-image-region: rect(16px, 48px, 32px, 32px);
+}
+@itemNotFinished@:hover .downloadButton.downloadIconShow:active {
+  -moz-image-region: rect(16px, 64px, 32px, 48px);
+}
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 96px, 32px, 80px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:hover {
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 112px, 32px, 96px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:active {
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 128px, 32px, 112px);
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
--- a/browser/themes/osx/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/osx/downloads/allDownloadsViewOverlay.css
@@ -5,185 +5,177 @@
 %include ../../shared/downloads/allDownloadsViewOverlay.inc.css
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 6em;
 }
 
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/warning-32.png");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/information-32.png");
+}
+
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
-@itemFocused@ .downloadButton.downloadConfirmBlock,
-@itemFocused@ .downloadButton.downloadCancel {
+@itemFocused@ .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 80px, 16px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock,
-@itemFocused@:hover .downloadButton.downloadCancel {
+@itemFocused@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 96px, 16px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-@itemFocused@:hover .downloadButton.downloadCancel:hover {
+@itemFocused@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 112px, 16px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-@itemFocused@:hover .downloadButton.downloadCancel:active {
+@itemFocused@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 128px, 16px, 112px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@item@:hover .downloadButton.downloadShow {
+@item@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-@item@:hover .downloadButton.downloadShow:hover {
+@item@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
-@item@:hover .downloadButton.downloadShow:active {
+@item@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 64px, 32px, 48px);
 }
-@itemFocused@ .downloadButton.downloadShow {
+@itemFocused@ .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 80px, 32px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadShow {
+@itemFocused@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 96px, 32px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadShow:hover {
+@itemFocused@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 112px, 32px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadShow:active {
+@itemFocused@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 128px, 32px, 112px);
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
-@itemFocused@ .downloadButton.downloadRetry {
+@itemFocused@ .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 80px, 48px, 64px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry {
+@itemFocused@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 96px, 48px, 80px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry:hover {
+@itemFocused@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 112px, 48px, 96px);
 }
-@itemFocused@:hover .downloadButton.downloadRetry:active {
+@itemFocused@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 128px, 48px, 112px);
 }
 
 @media (min-resolution: 2dppx) {
   .downloadButton {
     list-style-image: url("chrome://browser/skin/downloads/buttons@2x.png");
   }
   .downloadButton > .button-box > .button-icon {
     width: 16px;
     height: 16px;
   }
 
-  .downloadButton.downloadConfirmBlock,
-  .downloadButton.downloadCancel {
+  .downloadButton.downloadIconCancel {
      -moz-image-region: rect(0px, 32px, 32px, 0px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock,
-  @item@:hover .downloadButton.downloadCancel {
+  @item@:hover .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 64px, 32px, 32px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock:hover,
-  @item@:hover .downloadButton.downloadCancel:hover {
+  @item@:hover .downloadButton.downloadIconCancel:hover {
     -moz-image-region: rect(0px, 96px, 32px, 64px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock:active,
-  @item@:hover .downloadButton.downloadCancel:active {
+  @item@:hover .downloadButton.downloadIconCancel:active {
     -moz-image-region: rect(0px, 128px, 32px, 96px);
   }
-  @itemFocused@ .downloadButton.downloadConfirmBlock,
-  @itemFocused@ .downloadButton.downloadCancel {
+  @itemFocused@ .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 160px, 32px, 128px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock,
-  @itemFocused@:hover .downloadButton.downloadCancel {
+  @itemFocused@:hover .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 192px, 32px, 160px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-  @itemFocused@:hover .downloadButton.downloadCancel:hover {
+  @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
     -moz-image-region: rect(0px, 224px, 32px, 192px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-  @itemFocused@:hover .downloadButton.downloadCancel:active {
+  @itemFocused@:hover .downloadButton.downloadIconCancel:active {
     -moz-image-region: rect(0px, 256px, 32px, 224px);
   }
 
-  .downloadButton.downloadShow {
+  .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 32px, 64px, 0px);
   }
-  @item@:hover .downloadButton.downloadShow {
+  @item@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 64px, 64px, 32px);
   }
-  @item@:hover .downloadButton.downloadShow:hover {
+  @item@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(32px, 96px, 64px, 64px);
   }
-  @item@:hover .downloadButton.downloadShow:active {
+  @item@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(32px, 128px, 64px, 96px);
   }
-  @itemFocused@ .downloadButton.downloadShow {
+  @itemFocused@ .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 160px, 64px, 128px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow {
+  @itemFocused@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 192px, 64px, 160px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow:hover {
+  @itemFocused@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(32px, 224px, 64px, 192px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow:active {
+  @itemFocused@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(32px, 256px, 64px, 224px);
   }
 
-  .downloadButton.downloadRetry {
+  .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 32px, 96px, 0px);
   }
-  @item@:hover .downloadButton.downloadRetry {
+  @item@:hover .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 64px, 96px, 32px);
   }
-  @item@:hover .downloadButton.downloadRetry:hover {
+  @item@:hover .downloadButton.downloadIconRetry:hover {
     -moz-image-region: rect(64px, 96px, 96px, 64px);
   }
-  @item@:hover .downloadButton.downloadRetry:active {
+  @item@:hover .downloadButton.downloadIconRetry:active {
     -moz-image-region: rect(64px, 128px, 96px, 96px);
   }
-  @itemFocused@ .downloadButton.downloadRetry {
+  @itemFocused@ .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 160px, 96px, 128px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry {
+  @itemFocused@:hover .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 192px, 96px, 160px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry:hover {
+  @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
     -moz-image-region: rect(64px, 224px, 96px, 192px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry:active {
+  @itemFocused@:hover .downloadButton.downloadIconRetry:active {
     -moz-image-region: rect(64px, 256px, 96px, 224px);
   }
 }
--- a/browser/themes/osx/downloads/downloads.css
+++ b/browser/themes/osx/downloads/downloads.css
@@ -42,16 +42,24 @@
   --downloads-item-details-opacity: 0.7;
 }
 
 .downloadButton:focus > .button-box {
   outline: 2px -moz-mac-focusring solid;
   outline-offset: -2px;
 }
 
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/warning-32.png");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/information-32.png");
+}
+
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@,
 @notKeyfocus@ @itemFinished@[exists]:hover {
   border-radius: 3px;
   border-top: 1px solid hsla(0,0%,100%,.2);
   border-bottom: 1px solid hsla(0,0%,0%,.4);
   background-color: Highlight;
@@ -59,189 +67,179 @@
 }
 
 @notKeyfocus@ @itemFinished@[exists]:hover {
   cursor: pointer;
 }
 
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
-@keyfocus@ @itemFocused@ .downloadButton.downloadConfirmBlock,
-@keyfocus@ @itemFocused@ .downloadButton.downloadCancel {
+@keyfocus@ @itemFocused@ .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 80px, 16px, 64px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 96px, 16px, 80px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel:hover {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 112px, 16px, 96px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel:active {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 128px, 16px, 112px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow {
+@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow,
+@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow:hover {
+@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:hover,
+@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow:active {
+@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:active,
+@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 64px, 32px, 48px);
 }
-@keyfocus@ @itemFocused@ .downloadButton.downloadShow {
+@keyfocus@ @itemFocused@ .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 80px, 32px, 64px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShow {
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow,
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 96px, 32px, 80px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:hover,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShow:hover {
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover,
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 112px, 32px, 96px);
 }
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:active,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShow:active {
+@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active,
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 128px, 32px, 112px);
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
-@keyfocus@ @itemFocused@ .downloadButton.downloadRetry {
+@keyfocus@ @itemFocused@ .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 80px, 48px, 64px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 96px, 48px, 80px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry:hover {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 112px, 48px, 96px);
 }
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry:active {
+@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 128px, 48px, 112px);
 }
 
 @media (min-resolution: 2dppx) {
   .downloadButton {
     list-style-image: url("chrome://browser/skin/downloads/buttons@2x.png");
   }
   .downloadButton > .button-box > .button-icon {
     width: 16px;
     height: 16px;
   }
 
-  .downloadButton.downloadConfirmBlock,
-  .downloadButton.downloadCancel {
+  .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 32px, 32px, 0px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock,
-  @item@:hover .downloadButton.downloadCancel {
+  @item@:hover .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 64px, 32px, 32px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock:hover,
-  @item@:hover .downloadButton.downloadCancel:hover {
+  @item@:hover .downloadButton.downloadIconCancel:hover {
     -moz-image-region: rect(0px, 96px, 32px, 64px);
   }
-  @item@:hover .downloadButton.downloadConfirmBlock:active,
-  @item@:hover .downloadButton.downloadCancel:active {
+  @item@:hover .downloadButton.downloadIconCancel:active {
     -moz-image-region: rect(0px, 128px, 32px, 96px);
   }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadConfirmBlock,
-  @keyfocus@ @itemFocused@ .downloadButton.downloadCancel {
+  @keyfocus@ @itemFocused@ .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 160px, 32px, 128px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 192px, 32px, 160px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel:hover {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
     -moz-image-region: rect(0px, 224px, 32px, 192px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadCancel:active {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:active {
     -moz-image-region: rect(0px, 256px, 32px, 224px);
   }
 
-  .downloadButton.downloadShow {
+  .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 32px, 64px, 0px);
   }
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow {
+  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow,
+  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 64px, 64px, 32px);
   }
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow:hover {
+  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:hover,
+  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(32px, 96px, 64px, 64px);
   }
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadShow:active {
+  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:active,
+  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(32px, 128px, 64px, 96px);
   }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadShow {
+  @keyfocus@ @itemFocused@ .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 160px, 64px, 128px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShow {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow,
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(32px, 192px, 64px, 160px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:hover,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShow:hover {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover,
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(32px, 224px, 64px, 192px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:active,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShow:active {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active,
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(32px, 256px, 64px, 224px);
   }
 
-  .downloadButton.downloadRetry {
+  .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 32px, 96px, 0px);
   }
-  @item@:hover .downloadButton.downloadRetry {
+  @item@:hover .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 64px, 96px, 32px);
   }
-  @item@:hover .downloadButton.downloadRetry:hover {
+  @item@:hover .downloadButton.downloadIconRetry:hover {
     -moz-image-region: rect(64px, 96px, 96px, 64px);
   }
-  @item@:hover .downloadButton.downloadRetry:active {
+  @item@:hover .downloadButton.downloadIconRetry:active {
     -moz-image-region: rect(64px, 128px, 96px, 96px);
   }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadRetry {
+  @keyfocus@ @itemFocused@ .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 160px, 96px, 128px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry {
     -moz-image-region: rect(64px, 192px, 96px, 160px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry:hover {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
     -moz-image-region: rect(64px, 224px, 96px, 192px);
   }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadRetry:active {
+  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:active {
     -moz-image-region: rect(64px, 256px, 96px, 224px);
   }
 }
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %filter substitution
 
 %define keyfocus #downloadsPanel[keyfocus]
 %define notKeyfocus #downloadsPanel:not([keyfocus])
 %define item richlistitem[type="download"]
 %define itemFinished @item@[state="1"]
+%define itemNotFinished @item@:not([state="1"])
 %define itemFocused #downloadsListBox:focus > @item@[selected]
 
 /*** Panel and outer controls ***/
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
--- a/browser/themes/windows/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/windows/downloads/allDownloadsViewOverlay.css
@@ -5,16 +5,24 @@
 %include ../../shared/downloads/allDownloadsViewOverlay.inc.css
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 6em;
 }
 
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/Warning.png");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/information-32.png");
+}
+
 /*** Highlighted list items ***/
 
 @media not all and (-moz-os-version: windows-xp) {
   @media (-moz-windows-default-theme) {
     /*
     -moz-appearance: menuitem is almost right, but the hover effect is not
     transparent and is lighter than desired.
 
@@ -39,95 +47,87 @@
       -moz-outline-radius: 3px;
       outline-offset: -2px;
     }
   }
 }
 
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@item@:hover .downloadButton.downloadShow {
+@item@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-@item@:hover .downloadButton.downloadShow:hover {
+@item@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
-@item@:hover .downloadButton.downloadShow:active {
+@item@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 64px, 32px, 48px);
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
 
 @media (-moz-os-version: windows-xp) {
-  @itemFocused@ .downloadButton.downloadConfirmBlock,
-  @itemFocused@ .downloadButton.downloadCancel {
+  @itemFocused@ .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 80px, 16px, 64px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock,
-  @itemFocused@:hover .downloadButton.downloadCancel {
+  @itemFocused@:hover .downloadButton.downloadIconCancel {
     -moz-image-region: rect(0px, 96px, 16px, 80px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock:hover,
-  @itemFocused@:hover .downloadButton.downloadCancel:hover {
+  @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
     -moz-image-region: rect(0px, 112px, 16px, 96px);
   }
-  @itemFocused@:hover .downloadButton.downloadConfirmBlock:active,
-  @itemFocused@:hover .downloadButton.downloadCancel:active {
+  @itemFocused@:hover .downloadButton.downloadIconCancel:active {
     -moz-image-region: rect(0px, 128px, 16px, 112px);
   }
 
-  @itemFocused@ .downloadButton.downloadShow {
+  @itemFocused@ .downloadButton.downloadIconShow {
     -moz-image-region: rect(16px, 80px, 32px, 64px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow {
+  @itemFocused@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(16px, 96px, 32px, 80px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow:hover {
+  @itemFocused@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(16px, 112px, 32px, 96px);
   }
-  @itemFocused@:hover .downloadButton.downloadShow:active {
+  @itemFocused@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(16px, 128px, 32px, 112px);
   }
 
-  @itemFocused@ .downloadButton.downloadRetry {
+  @itemFocused@ .downloadButton.downloadIconRetry {
     -moz-image-region: rect(32px, 80px, 48px, 64px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry {
+  @itemFocused@:hover .downloadButton.downloadIconRetry {
     -moz-image-region: rect(32px, 96px, 48px, 80px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry:hover {
+  @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
     -moz-image-region: rect(32px, 112px, 48px, 96px);
   }
-  @itemFocused@:hover .downloadButton.downloadRetry:active {
+  @itemFocused@:hover .downloadButton.downloadIconRetry:active {
     -moz-image-region: rect(32px, 128px, 48px, 112px);
   }
 }
--- a/browser/themes/windows/downloads/downloads.css
+++ b/browser/themes/windows/downloads/downloads.css
@@ -91,16 +91,24 @@
 .downloadButton > .button-box {
   border: 1px solid transparent;
 }
 
 @keyfocus@ .downloadButton:focus > .button-box {
   border: 1px dotted ThreeDDarkShadow;
 }
 
+@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/Warning.png");
+}
+
+@item@[verdict="Uncommon"] .blockedIcon {
+  list-style-image: url("chrome://global/skin/icons/information-32.png");
+}
+
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@ {
   outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
 }
 
 @notKeyfocus@ @itemFinished@[exists]:hover {
@@ -143,70 +151,66 @@
                 0 1px 0 hsla(0,0%,100%,.3) inset;
     background-image: linear-gradient(hsl(212,86%,92%), hsl(212,91%,86%));
     color: black;
   }
 }
 
 /*** Button icons ***/
 
-.downloadButton.downloadConfirmBlock,
-.downloadButton.downloadCancel {
+.downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock,
-@item@:hover .downloadButton.downloadCancel {
+@item@:hover .downloadButton.downloadIconCancel {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:hover,
-@item@:hover .downloadButton.downloadCancel:hover {
+@item@:hover .downloadButton.downloadIconCancel:hover {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
-@item@:hover .downloadButton.downloadConfirmBlock:active,
-@item@:hover .downloadButton.downloadCancel:active {
+@item@:hover .downloadButton.downloadIconCancel:active {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
-.downloadButton.downloadShow {
+.downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-@item@:hover .downloadButton.downloadShow {
+@item@:hover .downloadButton.downloadIconShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-@item@:hover .downloadButton.downloadShow:hover {
+@item@:hover .downloadButton.downloadIconShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
-@item@:hover .downloadButton.downloadShow:active {
+@item@:hover .downloadButton.downloadIconShow:active {
   -moz-image-region: rect(16px, 64px, 32px, 48px);
 }
 @media (-moz-os-version: windows-xp) {
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadShow {
+  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(16px, 32px, 32px, 16px);
   }
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadShow:hover {
+  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(16px, 48px, 32px, 32px);
   }
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadShow:active {
+  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(16px, 64px, 32px, 48px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
     -moz-image-region: rect(16px, 96px, 32px, 80px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:hover {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
     -moz-image-region: rect(16px, 112px, 32px, 96px);
   }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadShow:active {
+  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
     -moz-image-region: rect(16px, 128px, 32px, 112px);
   }
 }
 
-.downloadButton.downloadRetry {
+.downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-@item@:hover .downloadButton.downloadRetry {
+@item@:hover .downloadButton.downloadIconRetry {
   -moz-image-region: rect(32px, 32px, 48px, 16px);
 }
-@item@:hover .downloadButton.downloadRetry:hover {
+@item@:hover .downloadButton.downloadIconRetry:hover {
   -moz-image-region: rect(32px, 48px, 48px, 32px);
 }
-@item@:hover .downloadButton.downloadRetry:active {
+@item@:hover .downloadButton.downloadIconRetry:active {
   -moz-image-region: rect(32px, 64px, 48px, 48px);
 }
--- a/devtools/client/shared/widgets/Spectrum.js
+++ b/devtools/client/shared/widgets/Spectrum.js
@@ -9,59 +9,60 @@ const EventEmitter = require("devtools/s
 /**
  * Spectrum creates a color picker widget in any container you give it.
  *
  * Simple usage example:
  *
  * const {Spectrum} = require("devtools/client/shared/widgets/Spectrum");
  * let s = new Spectrum(containerElement, [255, 126, 255, 1]);
  * s.on("changed", (event, rgba, color) => {
- *   console.log("rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ", " + rgba[3] + ")");
+ *   console.log("rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ", " +
+ *     rgba[3] + ")");
  * });
  * s.show();
  * s.destroy();
  *
  * Note that the color picker is hidden by default and you need to call show to
  * make it appear. This 2 stages initialization helps in cases you are creating
  * the color picker in a parent element that hasn't been appended anywhere yet
  * or that is hidden. Calling show() when the parent element is appended and
  * visible will allow spectrum to correctly initialize its various parts.
  *
  * Fires the following events:
  * - changed : When the user changes the current color
  */
 function Spectrum(parentEl, rgb) {
   EventEmitter.decorate(this);
 
-  this.element = parentEl.ownerDocument.createElement('div');
+  this.element = parentEl.ownerDocument.createElement("div");
   this.parentEl = parentEl;
 
   this.element.className = "spectrum-container";
-  this.element.innerHTML = [
-    "<div class='spectrum-top'>",
-      "<div class='spectrum-fill'></div>",
-      "<div class='spectrum-top-inner'>",
-        "<div class='spectrum-color spectrum-box'>",
-          "<div class='spectrum-sat'>",
-            "<div class='spectrum-val'>",
-              "<div class='spectrum-dragger'></div>",
-            "</div>",
-          "</div>",
-        "</div>",
-        "<div class='spectrum-hue spectrum-box'>",
-          "<div class='spectrum-slider spectrum-slider-control'></div>",
-        "</div>",
-      "</div>",
-    "</div>",
-    "<div class='spectrum-alpha spectrum-checker spectrum-box'>",
-      "<div class='spectrum-alpha-inner'>",
-        "<div class='spectrum-alpha-handle spectrum-slider-control'></div>",
-      "</div>",
-    "</div>",
-  ].join("");
+  this.element.innerHTML = `
+    <div class="spectrum-top">
+      <div class="spectrum-fill"></div>
+      <div class="spectrum-top-inner">
+        <div class="spectrum-color spectrum-box">
+          <div class="spectrum-sat">
+            <div class="spectrum-val">
+              <div class="spectrum-dragger"></div>
+            </div>
+          </div>
+        </div>
+        <div class="spectrum-hue spectrum-box">
+          <div class="spectrum-slider spectrum-slider-control"></div>
+        </div>
+      </div>
+    </div>
+    <div class="spectrum-alpha spectrum-checker spectrum-box">
+      <div class="spectrum-alpha-inner">
+        <div class="spectrum-alpha-handle spectrum-slider-control"></div>
+      </div>
+    </div>
+  `;
 
   this.onElementClick = this.onElementClick.bind(this);
   this.element.addEventListener("click", this.onElementClick, false);
 
   this.parentEl.appendChild(this.element);
 
   this.slider = this.element.querySelector(".spectrum-hue");
   this.slideHelper = this.element.querySelector(".spectrum-slider");
@@ -89,42 +90,42 @@ Spectrum.hsvToRgb = function(h, s, v, a)
 
   let i = Math.floor(h * 6);
   let f = h * 6 - i;
   let p = v * (1 - s);
   let q = v * (1 - f * s);
   let t = v * (1 - (1 - f) * s);
 
   switch(i % 6) {
-    case 0: r = v, g = t, b = p; break;
-    case 1: r = q, g = v, b = p; break;
-    case 2: r = p, g = v, b = t; break;
-    case 3: r = p, g = q, b = v; break;
-    case 4: r = t, g = p, b = v; break;
-    case 5: r = v, g = p, b = q; break;
+    case 0: r = v; g = t; b = p; break;
+    case 1: r = q; g = v; b = p; break;
+    case 2: r = p; g = v; b = t; break;
+    case 3: r = p; g = q; b = v; break;
+    case 4: r = t; g = p; b = v; break;
+    case 5: r = v; g = p; b = q; break;
   }
 
   return [r * 255, g * 255, b * 255, a];
 };
 
 Spectrum.rgbToHsv = function(r, g, b, a) {
   r = r / 255;
   g = g / 255;
   b = b / 255;
 
   let max = Math.max(r, g, b), min = Math.min(r, g, b);
   let h, s, v = max;
 
   let d = max - min;
   s = max == 0 ? 0 : d / max;
 
-  if(max == min) {
-    h = 0; // achromatic
-  }
-  else {
+  if (max == min) {
+    // achromatic
+    h = 0;
+  } else {
     switch(max) {
       case r: h = (g - b) / d + (g < b ? 6 : 0); break;
       case g: h = (b - r) / d + 2; break;
       case b: h = (r - g) / d + 4; break;
     }
     h /= 6;
   }
   return [h, s, v, a];
@@ -215,32 +216,35 @@ Spectrum.draggable = function(element, o
 };
 
 Spectrum.prototype = {
   set rgb(color) {
     this.hsv = Spectrum.rgbToHsv(color[0], color[1], color[2], color[3]);
   },
 
   get rgb() {
-    let rgb = Spectrum.hsvToRgb(this.hsv[0], this.hsv[1], this.hsv[2], this.hsv[3]);
-    return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2]), Math.round(rgb[3]*100)/100];
+    let rgb = Spectrum.hsvToRgb(this.hsv[0], this.hsv[1], this.hsv[2],
+      this.hsv[3]);
+    return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2]),
+      Math.round(rgb[3] * 100) / 100];
   },
 
   get rgbNoSatVal() {
     let rgb = Spectrum.hsvToRgb(this.hsv[0], 1, 1);
     return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2]), rgb[3]];
   },
 
   get rgbCssString() {
     let rgb = this.rgb;
-    return "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " + rgb[3] + ")";
+    return "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " +
+      rgb[3] + ")";
   },
 
   show: function() {
-    this.element.classList.add('spectrum-show');
+    this.element.classList.add("spectrum-show");
 
     this.slideHeight = this.slider.offsetHeight;
     this.dragWidth = this.dragger.offsetWidth;
     this.dragHeight = this.dragger.offsetHeight;
     this.dragHelperHeight = this.dragHelper.offsetHeight;
     this.slideHelperHeight = this.slideHelper.offsetHeight;
     this.alphaSliderWidth = this.alphaSliderInner.offsetWidth;
     this.alphaSliderHelperWidth = this.alphaSliderHelper.offsetWidth;
@@ -271,64 +275,68 @@ Spectrum.prototype = {
     this.onChange();
   },
 
   onChange: function() {
     this.emit("changed", this.rgb, this.rgbCssString);
   },
 
   updateHelperLocations: function() {
-    // If the UI hasn't been shown yet then none of the dimensions will be correct
-    if (!this.element.classList.contains('spectrum-show'))
+    // If the UI hasn't been shown yet then none of the dimensions will be
+    // correct
+    if (!this.element.classList.contains("spectrum-show")) {
       return;
+    }
 
     let h = this.hsv[0];
     let s = this.hsv[1];
     let v = this.hsv[2];
 
     // Placing the color dragger
     let dragX = s * this.dragWidth;
     let dragY = this.dragHeight - (v * this.dragHeight);
-    let helperDim = this.dragHelperHeight/2;
+    let helperDim = this.dragHelperHeight / 2;
 
     dragX = Math.max(
       -helperDim,
       Math.min(this.dragWidth - helperDim, dragX - helperDim)
     );
     dragY = Math.max(
       -helperDim,
       Math.min(this.dragHeight - helperDim, dragY - helperDim)
     );
 
     this.dragHelper.style.top = dragY + "px";
     this.dragHelper.style.left = dragX + "px";
 
     // Placing the hue slider
-    let slideY = (h * this.slideHeight) - this.slideHelperHeight/2;
+    let slideY = (h * this.slideHeight) - this.slideHelperHeight / 2;
     this.slideHelper.style.top = slideY + "px";
 
     // Placing the alpha slider
-    let alphaSliderX = (this.hsv[3] * this.alphaSliderWidth) - (this.alphaSliderHelperWidth / 2);
+    let alphaSliderX = (this.hsv[3] * this.alphaSliderWidth) -
+      (this.alphaSliderHelperWidth / 2);
     this.alphaSliderHelper.style.left = alphaSliderX + "px";
   },
 
   updateUI: function() {
     this.updateHelperLocations();
 
     let rgb = this.rgb;
     let rgbNoSatVal = this.rgbNoSatVal;
 
-    let flatColor = "rgb(" + rgbNoSatVal[0] + ", " + rgbNoSatVal[1] + ", " + rgbNoSatVal[2] + ")";
-    let fullColor = "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " + rgb[3] + ")";
+    let flatColor = "rgb(" + rgbNoSatVal[0] + ", " + rgbNoSatVal[1] + ", " +
+      rgbNoSatVal[2] + ")";
 
     this.dragger.style.backgroundColor = flatColor;
 
-    var rgbNoAlpha = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")";
-    var rgbAlpha0 = "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ", 0)";
-    var alphaGradient = "linear-gradient(to right, " + rgbAlpha0 + ", " + rgbNoAlpha + ")";
+    let rgbNoAlpha = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")";
+    let rgbAlpha0 = "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ", 0)";
+    let alphaGradient = "linear-gradient(to right, " + rgbAlpha0 + ", " +
+      rgbNoAlpha + ")";
     this.alphaSliderInner.style.background = alphaGradient;
   },
 
   destroy: function() {
     this.element.removeEventListener("click", this.onElementClick, false);
 
     this.parentEl.removeChild(this.element);
 
--- a/devtools/client/webconsole/net/components/net-info-body.css
+++ b/devtools/client/webconsole/net/components/net-info-body.css
@@ -104,14 +104,13 @@
   border-color: var(--net-border);
 }
 
 .theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active a,
 .theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active:hover a,
 .theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active a:focus {
   border: 1px solid var(--net-border);
   border-bottom-color: transparent;
-  border-color: var(--net-border);
 }
 
 .theme-firebug .netInfoBody > .tabs .tabs-menu-item:hover a {
   border-bottom-color: transparent;
 }
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -300,19 +300,16 @@ pref("browser.search.geoSpecificDefaults
 pref("browser.search.defaultenginename.US", "chrome://browser/locale/region.properties");
 pref("browser.search.order.US.1", "chrome://browser/locale/region.properties");
 pref("browser.search.order.US.2", "chrome://browser/locale/region.properties");
 pref("browser.search.order.US.3", "chrome://browser/locale/region.properties");
 
 // disable updating
 pref("browser.search.update", false);
 
-// enable tracking protection for private browsing
-pref("privacy.trackingprotection.pbmode.enabled", true);
-
 // disable search suggestions by default
 pref("browser.search.suggest.enabled", false);
 pref("browser.search.suggest.prompted", false);
 
 // tell the search service that we don't really expose the "current engine"
 pref("browser.search.noCurrentEngine", true);
 
 // Control media casting & mirroring features
@@ -644,56 +641,24 @@ pref("media.android-media-codec.preferre
 
 // Enable MSE
 pref("media.mediasource.enabled", true);
 
 // optimize images memory usage
 pref("image.downscale-during-decode.enabled", true);
 
 #ifdef MOZ_SAFE_BROWSING
-pref("browser.safebrowsing.enabled", true);
-pref("browser.safebrowsing.malware.enabled", true);
 pref("browser.safebrowsing.downloads.enabled", false);
 pref("browser.safebrowsing.downloads.remote.enabled", false);
-pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000);
-pref("browser.safebrowsing.downloads.remote.url", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.downloads.remote.block_dangerous",            true);
-pref("browser.safebrowsing.downloads.remote.block_dangerous_host",       true);
-pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
-pref("browser.safebrowsing.downloads.remote.block_uncommon",             false);
-pref("browser.safebrowsing.debug", false);
-
-pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,goog-malware-shavar,goog-unwanted-shavar");
-pref("browser.safebrowsing.provider.google.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
-pref("browser.safebrowsing.provider.google.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
-pref("browser.safebrowsing.provider.google.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
-
-pref("browser.safebrowsing.reportPhishMistakeURL", "https://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
-pref("browser.safebrowsing.reportMalwareMistakeURL", "https://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%&url=");
 
 pref("browser.safebrowsing.id", @MOZ_APP_UA_NAME@);
 
 // Name of the about: page contributed by safebrowsing to handle display of error
 // pages on phishing/malware hits.  (bug 399233)
 pref("urlclassifier.alternate_error_page", "blocked");
-
-// The number of random entries to send with a gethash request.
-pref("urlclassifier.gethashnoise", 4);
-
-// Gethash timeout for Safebrowsing.
-pref("urlclassifier.gethash.timeout_ms", 5000);
-
-// If an urlclassifier table has not been updated in this number of seconds,
-// a gethash request will be forced to check that the result is still in
-// the database.
-pref("urlclassifier.max-complete-age", 2700);
-
-// Tables for application reputation.
-pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
 #endif
 
 // True if this is the first time we are showing about:firstrun
 pref("browser.firstrun.show.uidiscovery", true);
 pref("browser.firstrun.show.localepicker", false);
 
 // True if you always want dump() to work
 //
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java
@@ -42,16 +42,21 @@ import java.util.ArrayList;
  *   * Copy the current version of the database into (robocop-assets)/browser_db_upgrade/v##.db database. You can do
  * this via Margaret's copy profile addon - take browser.db from the profile directory. This db copy should contain a
  * used profile - e.g. history items, bookmarks. A good way to get a used profile is to sign into sync.
  *   * MAKE SURE YOU COPY YOUR DB FIRST. Then make your changes to the DB schema code.
  *   * Test!
  *   * Note: when the application starts for testing, it may need to upgrade the database from your existing version. If
  * this fails, the application will crash and the test may fail to start.
  *
+ * IMPORTANT:
+ * Test DBs must be created on the oldest version of Android that is currently supported. SQLite
+ * is not forwards compatible. E.g. uploading a DB created on a 6.0 device will cause failures
+ * when robocop tests running on 4.3 are unable to load it.
+ *
  * Implementation inspired by:
  *   http://riggaroo.co.za/automated-testing-sqlite-database-upgrades-android/
  */
 public class testBrowserDatabaseHelperUpgrades extends UITest {
     private static final int TEST_FROM_VERSION = 27; // We only started testing on this version.
 
     private ArrayList<File> temporaryDbFiles;
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4952,28 +4952,64 @@ pref("dom.voicemail.enabled", false);
 pref("dom.voicemail.defaultServiceId", 0);
 
 // DOM Inter-App Communication API.
 pref("dom.inter-app-communication-api.enabled", false);
 
 // Disable mapped array buffer by default.
 pref("dom.mapped_arraybuffer.enabled", false);
 
+#ifdef MOZ_SAFE_BROWSING
 // The tables used for Safebrowsing phishing and malware checks.
 pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,test-malware-simple,test-unwanted-simple");
 pref("urlclassifier.phishTable", "goog-phish-shavar,test-phish-simple");
 pref("urlclassifier.downloadBlockTable", "");
 pref("urlclassifier.downloadAllowTable", "");
 pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,test-forbid-simple,goog-downloadwhite-digest256,mozstd-track-digest256,mozstd-trackwhite-digest256,mozfull-track-digest256,test-block-simple,mozplugin-block-digest256,mozplugin2-block-digest256");
 
 // The table and update/gethash URLs for Safebrowsing phishing and malware
 // checks.
 pref("urlclassifier.trackingTable", "test-track-simple,mozstd-track-digest256");
 pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
 
+// Tables for application reputation.
+pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
+
+// The number of random entries to send with a gethash request.
+pref("urlclassifier.gethashnoise", 4);
+
+// Gethash timeout for Safebrowsing.	
+pref("urlclassifier.gethash.timeout_ms", 5000);
+
+// If an urlclassifier table has not been updated in this number of seconds,
+// a gethash request will be forced to check that the result is still in
+// the database.
+pref("urlclassifier.max-complete-age", 2700);
+
+pref("browser.safebrowsing.enabled", true);
+pref("browser.safebrowsing.malware.enabled", true);
+
+pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000);
+pref("browser.safebrowsing.downloads.remote.url", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
+pref("browser.safebrowsing.downloads.remote.block_dangerous",            true);
+pref("browser.safebrowsing.downloads.remote.block_dangerous_host",       true);
+pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
+pref("browser.safebrowsing.downloads.remote.block_uncommon",             false);
+pref("browser.safebrowsing.debug", false);
+
+pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,goog-malware-shavar,goog-unwanted-shavar");
+pref("browser.safebrowsing.provider.google.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
+pref("browser.safebrowsing.provider.google.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.safebrowsing.provider.google.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
+
+pref("browser.safebrowsing.reportPhishMistakeURL", "https://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%&url=");
+pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
+pref("browser.safebrowsing.reportMalwareMistakeURL", "https://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%&url=");
+
+
 // The table and global pref for blocking access to sites forbidden by policy
 pref("browser.safebrowsing.forbiddenURIs.enabled", false);
 pref("urlclassifier.forbiddenTable", "test-forbid-simple");
 
 // The table and global pref for blocking plugin content
 pref("browser.safebrowsing.blockedURIs.enabled", false);
 pref("urlclassifier.blockedTable", "test-block-simple,mozplugin-block-digest256");
 
@@ -4986,16 +5022,17 @@ pref("browser.safebrowsing.provider.mozi
 // to lookup the localized name in preferences.properties.
 pref("browser.safebrowsing.provider.mozilla.lists.mozstd.name", "mozstdName");
 pref("browser.safebrowsing.provider.mozilla.lists.mozstd.description", "mozstdDesc");
 pref("browser.safebrowsing.provider.mozilla.lists.mozfull.name", "mozfullName");
 pref("browser.safebrowsing.provider.mozilla.lists.mozfull.description", "mozfullDesc");
 
 // Allow users to ignore Safe Browsing warnings.
 pref("browser.safebrowsing.allowOverride", true);
+#endif
 
 // Turn off Spatial navigation by default.
 pref("snav.enabled", false);
 
 // New implementation to unify touch-caret and selection-carets.
 pref("layout.accessiblecaret.enabled", false);
 
 // CSS attributes of the AccessibleCaret in CSS pixels.
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -1,15 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*** =================== SAVED SIGNONS CODE =================== ***/
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
+                                  "resource://gre/modules/DeferredTask.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
 
 var kSignonBundle;
 var showingPasswords = false;
 var dateFormatter = new Intl.DateTimeFormat(undefined,
                       { day: "numeric", month: "short", year: "numeric" });
 var dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
                              { day: "numeric", month: "short", year: "numeric",
                                hour: "numeric", minute: "numeric" });
@@ -39,26 +45,56 @@ function SignonsStartup() {
 }
 
 function setFilter(aFilterString) {
   document.getElementById("filter").value = aFilterString;
   _filterPasswords();
 }
 
 var signonsTreeView = {
-  _filterSet : [],
-  _lastSelectedRanges : [],
+  // Keep track of which favicons we've fetched or started fetching.
+  // Maps a login origin to a favicon URL.
+  _faviconMap: new Map(),
+  _filterSet: [],
+  // Coalesce invalidations to avoid repeated flickering.
+  _invalidateTask: new DeferredTask(() => {
+    signonsTree.treeBoxObject.invalidateColumn(signonsTree.columns.siteCol);
+  }, 10),
+  _lastSelectedRanges: [],
   selection: null,
 
-  rowCount : 0,
-  setTree : function(tree) {},
-  getImageSrc : function(row,column) {},
-  getProgressMode : function(row,column) {},
-  getCellValue : function(row,column) {},
-  getCellText : function(row,column) {
+  rowCount: 0,
+  setTree(tree) {},
+  getImageSrc(row, column) {
+    if (column.element.getAttribute("id") !== "siteCol") {
+      return "";
+    }
+
+    const signon = this._filterSet.length ? this._filterSet[row] : signons[row];
+
+    // We already have the favicon URL or we started to fetch (value is null).
+    if (this._faviconMap.has(signon.hostname)) {
+      return this._faviconMap.get(signon.hostname);
+    }
+
+    // Record the fact that we already starting fetching a favicon for this
+    // origin in order to avoid multiple requests for the same origin.
+    this._faviconMap.set(signon.hostname, null);
+
+    PlacesUtils.promiseFaviconLinkUrl(signon.hostname)
+      .then(faviconURI => {
+        this._faviconMap.set(signon.hostname, faviconURI.spec);
+        this._invalidateTask.arm();
+      }).catch(Cu.reportError);
+
+    return "";
+  },
+  getProgressMode(row, column) {},
+  getCellValue(row, column) {},
+  getCellText(row, column) {
     var time;
     var signon = this._filterSet.length ? this._filterSet[row] : signons[row];
     switch (column.id) {
       case "siteCol":
         return signon.httpRealm ?
                (signon.hostname + " (" + signon.httpRealm + ")"):
                signon.hostname;
       case "userCol":
@@ -75,35 +111,35 @@ var signonsTreeView = {
         time = new Date(signon.timePasswordChanged);
         return dateFormatter.format(time);
       case "timesUsedCol":
         return signon.timesUsed;
       default:
         return "";
     }
   },
-  isEditable : function(row, col) {
+  isEditable(row, col) {
     if (col.id == "userCol" || col.id == "passwordCol") {
       return true;
     }
     return false;
   },
-  isSeparator : function(index) { return false; },
-  isSorted : function() { return false; },
-  isContainer : function(index) { return false; },
-  cycleHeader : function(column) {},
-  getRowProperties : function(row) { return ""; },
-  getColumnProperties : function(column) { return ""; },
-  getCellProperties : function(row,column) {
+  isSeparator(index) { return false; },
+  isSorted() { return false; },
+  isContainer(index) { return false; },
+  cycleHeader(column) {},
+  getRowProperties(row) { return ""; },
+  getColumnProperties(column) { return ""; },
+  getCellProperties(row, column) {
     if (column.element.getAttribute("id") == "siteCol")
       return "ltr";
 
     return "";
   },
-  setCellText : function(row, col, value) {
+  setCellText(row, col, value) {
     // If there is a filter, _filterSet needs to be used, otherwise signons is used.
     let table = signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons;
     function _editLogin(field) {
       if (value == table[row][field]) {
         return;
       }
       let existingLogin = table[row].clone();
       table[row][field] = value;
@@ -219,17 +255,17 @@ function AskUserShowPasswords() {
   // Confirm the user wants to display passwords
   return prompter.confirmEx(window,
           null,
           kSignonBundle.getString("noMasterPasswordPrompt"), prompter.STD_YES_NO_BUTTONS,
           null, null, null, null, dummy) == 0;    // 0=="Yes" button
 }
 
 function FinalizeSignonDeletions(syncNeeded) {
-  for (var s=0; s<deletedSignons.length; s++) {
+  for (var s = 0; s < deletedSignons.length; s++) {
     passwordmanager.removeLogin(deletedSignons[s]);
     Services.telemetry.getHistogramById("PWMGR_MANAGE_DELETED").add(1);
   }
   // If the deletion has been performed in a filtered view, reflect the deletion in the unfiltered table.
   // See bug 405389.
   if (syncNeeded) {
     try {
       signons = passwordmanager.getAllLogins();
@@ -355,18 +391,17 @@ function SignonSaveState() {
   var rangeCount = seln.getRangeCount();
   for (var i = 0; i < rangeCount; ++i) {
     var min = {}; var max = {};
     seln.getRangeAt(i, min, max);
     signonsTreeView._lastSelectedRanges.push({ min: min.value, max: max.value });
   }
 }
 
-function _filterPasswords()
-{
+function _filterPasswords() {
   var filter = document.getElementById("filter").value;
   if (filter == "") {
     SignonClearFilter();
     return;
   }
 
   var newFilterSet = FilterPasswords(filter, signonsTreeView);
   if (!signonsTreeView._filterSet.length) {
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -24,17 +24,16 @@ toolkit.jar:
   skin/classic/global/groupbox.css
   skin/classic/global/linkTree.css
   skin/classic/global/listbox.css
   skin/classic/global/menu.css
   skin/classic/global/menulist.css
 * skin/classic/global/notification.css
   skin/classic/global/netError.css
   skin/classic/global/numberbox.css
-  skin/classic/global/passwordmgr.css
   skin/classic/global/popup.css
   skin/classic/global/preferences.css
   skin/classic/global/progressmeter.css
   skin/classic/global/radio.css
   skin/classic/global/resizer.css
   skin/classic/global/richlistbox.css
   skin/classic/global/scrollbars.css                                 (nativescrollbars.css)
   skin/classic/global/scale.css
deleted file mode 100644
--- a/toolkit/themes/osx/global/passwordmgr.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-.contentPane {
-  margin: 9px 8px 5px 8px;
-}
-
-.actionButtons {
-  margin: 0px 3px 6px 3px !important;
-}
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -41,16 +41,17 @@ toolkit.jar:
   skin/classic/global/menu/shared-menu-check-active.svg    (../../shared/menu-check-active.svg)
   skin/classic/global/menu/shared-menu-check-black.svg     (../../shared/menu-check-black.svg)
   skin/classic/global/menu/shared-menu-check-hover.svg     (../../shared/menu-check-hover.svg)
   skin/classic/global/in-content/check.svg                 (../../shared/in-content/check.svg)
   skin/classic/global/in-content/check-partial.svg         (../../shared/in-content/check-partial.svg)
   skin/classic/global/in-content/dropdown.svg              (../../shared/in-content/dropdown.svg)
   skin/classic/global/in-content/help-glyph.svg            (../../shared/in-content/help-glyph.svg)
   skin/classic/global/in-content/radio.svg                 (../../shared/in-content/radio.svg)
+  skin/classic/global/passwordmgr.css                      (../../shared/passwordmgr.css)
   skin/classic/global/reader/RM-Close-24x24.svg            (../../shared/reader/RM-Close-24x24.svg)
   skin/classic/global/reader/RM-Minus-24x24.svg            (../../shared/reader/RM-Minus-24x24.svg)
   skin/classic/global/reader/RM-Plus-24x24.svg             (../../shared/reader/RM-Plus-24x24.svg)
   skin/classic/global/reader/RM-Type-Controls-24x24.svg    (../../shared/reader/RM-Type-Controls-24x24.svg)
   skin/classic/global/reader/RM-Type-Controls-Arrow.svg    (../../shared/reader/RM-Type-Controls-Arrow.svg)
 #ifdef MOZ_PLACES
   skin/classic/mozapps/places/defaultFavicon.png           (../../shared/places/defaultFavicon.png)
   skin/classic/mozapps/places/defaultFavicon@2x.png        (../../shared/places/defaultFavicon@2x.png)
--- a/toolkit/themes/shared/non-mac.jar.inc.mn
+++ b/toolkit/themes/shared/non-mac.jar.inc.mn
@@ -13,17 +13,16 @@
   skin/classic/global/arrow.css                            (../../windows/global/arrow.css)
   skin/classic/global/customizeToolbar.css                 (../../windows/global/customizeToolbar.css)
   skin/classic/global/datetimepicker.css                   (../../windows/global/datetimepicker.css)
   skin/classic/global/dialog.css                           (../../windows/global/dialog.css)
   skin/classic/global/expander.css                         (../../windows/global/expander.css)
   skin/classic/global/filefield.css                        (../../windows/global/filefield.css)
   skin/classic/global/globalBindings.xml                   (../../windows/global/globalBindings.xml)
   skin/classic/global/linkTree.css                         (../../windows/global/linkTree.css)
-  skin/classic/global/passwordmgr.css                      (../../windows/global/passwordmgr.css)
   skin/classic/global/progressmeter.css                    (../../windows/global/progressmeter.css)
   skin/classic/global/resizer.css                          (../../windows/global/resizer.css)
   skin/classic/global/richlistbox.css                      (../../windows/global/richlistbox.css)
   skin/classic/global/scale.css                            (../../windows/global/scale.css)
 #ifndef MOZ_THEME_FASTSTRIPE
   skin/classic/global/scrollbars.css                       (../../windows/global/xulscrollbars.css)
 #endif
   skin/classic/global/spinbuttons.css                      (../../windows/global/spinbuttons.css)
rename from toolkit/themes/windows/global/passwordmgr.css
rename to toolkit/themes/shared/passwordmgr.css
--- a/toolkit/themes/windows/global/passwordmgr.css
+++ b/toolkit/themes/shared/passwordmgr.css
@@ -6,8 +6,21 @@
 
 .contentPane {
   margin: 9px 8px 5px 8px;
 }
 
 .actionButtons {
   margin: 0px 3px 6px 3px !important;
 }
+
+treechildren::-moz-tree-image(siteCol) {
+  list-style-image: url(chrome://mozapps/skin/places/defaultFavicon.png);
+  width: 16px;
+  height: 16px;
+  -moz-margin-end: 5px;
+}
+
+@media (min-resolution: 1.1dppx) {
+  treechildren::-moz-tree-image(siteCol) {
+    list-style-image: url(chrome://mozapps/skin/places/defaultFavicon@2x.png);
+  }
+}