Bug 1499704 - Use html:progress for downloads. r=dao,bgrins
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Wed, 17 Oct 2018 15:25:00 +0100
changeset 500423 87a982cbe3319558d1c54d1b448316bd300411d5
parent 500422 1d7feb40277692c23edf72c421558d0177480256
child 500424 6d6b5c10bba56bc286ae66cf9d72948a6a03d200
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, bgrins
bugs1499704
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1499704 - Use html:progress for downloads. r=dao,bgrins Differential Revision: https://phabricator.services.mozilla.com/D8973
browser/components/downloads/DownloadsViewUI.jsm
browser/components/downloads/content/downloadsPanel.inc.xul
browser/themes/osx/downloads/allDownloadsView.css
browser/themes/osx/downloads/downloads.css
browser/themes/shared/downloads/progressmeter.inc.css
browser/themes/windows/downloads/allDownloadsView.css
browser/themes/windows/downloads/downloads.css
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -9,27 +9,28 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = [
   "DownloadsViewUI",
 ];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
   Downloads: "resource://gre/modules/Downloads.jsm",
   DownloadUtils: "resource://gre/modules/DownloadUtils.jsm",
   DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",
   FileUtils: "resource://gre/modules/FileUtils.jsm",
   OS: "resource://gre/modules/osfile.jsm",
 });
 
+const HTML_NS = "http://www.w3.org/1999/xhtml";
+
 var gDownloadElementButtons = {
   cancel: {
     commandName: "downloadsCmd_cancel",
     l10nId: "download-cancel",
     descriptionL10nId: "download-cancel-description",
     iconClass: "downloadIconCancel",
   },
   retry: {
@@ -172,17 +173,16 @@ this.DownloadsViewUI.DownloadElementShel
       downloadListItemFragment = MozXULElement.parseXULToFragment(`
         <hbox class="downloadMainArea" flex="1" align="center">
           <stack>
             <image class="downloadTypeIcon" validate="always"/>
             <image class="downloadBlockedBadge" />
           </stack>
           <vbox class="downloadContainer" flex="1" pack="center">
             <description class="downloadTarget" crop="center"/>
-            <progressmeter class="downloadProgress" min="0" max="100"/>
             <description class="downloadDetails downloadDetailsNormal"
                          crop="end"/>
             <description class="downloadDetails downloadDetailsHover"
                          crop="end"/>
             <description class="downloadDetails downloadDetailsButtonHover"
                          crop="end"/>
           </vbox>
         </hbox>
@@ -196,24 +196,30 @@ this.DownloadsViewUI.DownloadElementShel
     this.element.setAttribute("orient", "horizontal");
     this.element.setAttribute("onclick",
                               "DownloadsView.onDownloadClick(event);");
     this.element.appendChild(document.importNode(downloadListItemFragment,
                                                  true));
     for (let [propertyName, selector] of [
       ["_downloadTypeIcon", ".downloadTypeIcon"],
       ["_downloadTarget", ".downloadTarget"],
-      ["_downloadProgress", ".downloadProgress"],
       ["_downloadDetailsNormal", ".downloadDetailsNormal"],
       ["_downloadDetailsHover", ".downloadDetailsHover"],
       ["_downloadDetailsButtonHover", ".downloadDetailsButtonHover"],
       ["_downloadButton", ".downloadButton"],
     ]) {
       this[propertyName] = this.element.querySelector(selector);
     }
+
+    // HTML elements can be created directly without using parseXULToFragment.
+    let progress = this._downloadProgress =
+                   document.createElementNS(HTML_NS, "progress");
+    progress.className = "downloadProgress";
+    progress.setAttribute("max", "100");
+    this._downloadTarget.insertAdjacentElement("afterend", progress);
   },
 
   /**
    * Returns a string from the downloads stringbundleset, which contains legacy
    * strings that are loaded from DTD files instead of properties files. This
    * won't be necessary once localization is converted to Fluent (bug 1452637).
    */
   string(l10nId) {
@@ -265,38 +271,22 @@ this.DownloadsViewUI.DownloadElementShel
    * @param mode
    *        Either "normal" or "undetermined".
    * @param value
    *        Percentage of the progress bar to display, from 0 to 100.
    * @param paused
    *        True to display the progress bar style for paused downloads.
    */
   showProgress(mode, value, paused) {
-    // The "undetermined" mode of the progressmeter is implemented with a
-    // different element structure, and with support from platform code as well.
-    // On Linux only, this mode isn't compatible with the custom styling that we
-    // apply separately with the "progress-undetermined" attribute.
-    this._downloadProgress.setAttribute("mode",
-      AppConstants.platform == "linux" ? "normal" : mode);
     if (mode == "undetermined") {
-      this._downloadProgress.setAttribute("progress-undetermined", "true");
+      this._downloadProgress.removeAttribute("value");
     } else {
-      this._downloadProgress.removeAttribute("progress-undetermined");
+      this._downloadProgress.setAttribute("value", value);
     }
-    this._downloadProgress.setAttribute("value", value);
-    if (paused) {
-      this._downloadProgress.setAttribute("paused", "true");
-    } else {
-      this._downloadProgress.removeAttribute("paused");
-    }
-
-    // Dispatch the ValueChange event for accessibility.
-    let event = this.element.ownerDocument.createEvent("Events");
-    event.initEvent("ValueChange", true, true);
-    this._downloadProgress.dispatchEvent(event);
+    this._downloadProgress.toggleAttribute("paused", !!paused);
   },
 
   /**
    * Updates the full status line.
    *
    * @param status
    *        Status line of the Downloads Panel or the Downloads View.
    * @param hoverStatus
--- a/browser/components/downloads/content/downloadsPanel.inc.xul
+++ b/browser/components/downloads/content/downloadsPanel.inc.xul
@@ -123,21 +123,19 @@
                 orient="horizontal"
                 onkeydown="DownloadsSummary.onKeyDown(event);"
                 onclick="DownloadsSummary.onClick(event);">
             <image class="downloadTypeIcon" />
             <vbox pack="center"
                   flex="1"
                   class="downloadContainer">
               <description id="downloadsSummaryDescription"/>
-              <progressmeter id="downloadsSummaryProgress"
+              <html:progress id="downloadsSummaryProgress"
                              class="downloadProgress"
-                             min="0"
-                             max="100"
-                             mode="normal" />
+                             max="100"/>
               <description id="downloadsSummaryDetails"
                            crop="end"/>
             </vbox>
           </hbox>
           <hbox id="downloadsFooterButtons">
             <button id="downloadsHistory"
                     class="downloadsPanelFooterButton"
                     label="&downloadsHistory.label;"
--- a/browser/themes/osx/downloads/allDownloadsView.css
+++ b/browser/themes/osx/downloads/allDownloadsView.css
@@ -5,15 +5,15 @@
 %include ../../shared/downloads/allDownloadsView.inc.css
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 6em;
 }
 
-.downloadProgress > .progress-bar {
+.downloadProgress::-moz-progress-bar {
   background-color: #3c9af8;
 }
 
-.downloadProgress[paused="true"] > .progress-bar {
+.downloadProgress[paused]::-moz-progress-bar {
   background-color: #a6a6a6;
 }
--- a/browser/themes/osx/downloads/downloads.css
+++ b/browser/themes/osx/downloads/downloads.css
@@ -28,21 +28,21 @@
 @item@[verdict="Malware"]:not(:hover) {
   color: #aa1b08;
 }
 
 :root[lwt-popup-brighttext] @item@[verdict="Malware"]:not(:hover) {
   color: #ff0039;
 }
 
-.downloadProgress > .progress-bar {
+.downloadProgress::-moz-progress-bar {
   background-color: #3c9af8;
 }
 
-.downloadProgress[paused="true"] > .progress-bar {
+.downloadProgress[paused]::-moz-progress-bar {
   background-color: #a6a6a6;
 }
 
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@ {
   outline: 2px -moz-mac-focusring solid;
   outline-offset: -2px;
--- a/browser/themes/shared/downloads/progressmeter.inc.css
+++ b/browser/themes/shared/downloads/progressmeter.inc.css
@@ -1,65 +1,58 @@
 /*** Common-styled progressmeter ***/
+
+/*
+ * Styling "html:progress" is limited by the fact that a number of properties
+ * are intentionally locked at the UA stylesheet level. We have to use a border
+ * instead of an outline because the latter would be drawn over the progress
+ * bar and we cannot change its z-index. This means we have to use a negative
+ * margin, except when the value is zero, and adjust the width calculation for
+ * the indeterminate state.
+ */
+
 .downloadProgress {
-  height: 8px;
-  border-radius: 1px;
+  -moz-appearance: none;
+  display: -moz-box;
   margin: 4px 0 0;
   margin-inline-end: 12px;
-
-  /* for overriding rules in progressmeter.css */
-  -moz-appearance: none;
-  border-style: none;
-  background-color: transparent;
-  min-width: initial;
-  min-height: initial;
+  border: 1px solid ButtonShadow;
+  height: 6px;
+  background-color: ButtonFace;
 }
 
-.downloadProgress > .progress-bar {
+.downloadProgress::-moz-progress-bar {
+  -moz-appearance: none;
   background-color: Highlight;
-
-  /* for overriding rules in progressmeter.css */
-  -moz-appearance: none;
 }
 
-.downloadProgress[paused="true"] > .progress-bar {
+.downloadProgress[paused]::-moz-progress-bar {
   background-color: GrayText;
 }
 
-.downloadProgress[progress-undetermined] > .progress-bar {
+.downloadProgress:not([value="0"])::-moz-progress-bar {
+  margin: -1px;
+  height: 8px;
+}
+
+.downloadProgress:indeterminate::-moz-progress-bar {
+  width: calc(100% + 2px);
   /* Make a white reflecting animation.
      Create a gradient with 2 identical pattern, and enlarge the size to 200%.
      This allows us to animate background-position with percentage. */
   background-image: linear-gradient(90deg, transparent 0%,
                                            rgba(255,255,255,0.5) 25%,
                                            transparent 50%,
                                            rgba(255,255,255,0.5) 75%,
                                            transparent 100%);
   background-blend-mode: lighten;
   background-size: 200% 100%;
   animation: downloadProgressSlideX 1.5s linear infinite;
 }
 
-.downloadProgress > .progress-remainder {
-  border: solid ButtonShadow;
-  border-block-start-width: 1px;
-  border-block-end-width: 1px;
-  border-inline-start-width: 0;
-  border-inline-end-width: 1px;
-  background-color: ButtonFace;
-}
-
-.downloadProgress[value="0"] > .progress-remainder {
-  border-width: 1px;
-}
-
-.downloadProgress[progress-undetermined] > .progress-remainder {
-  border: none;
-}
-
 @keyframes downloadProgressSlideX {
   0% {
     background-position: 0 0;
   }
   100% {
     background-position: -100% 0;
   }
 }
--- a/browser/themes/windows/downloads/allDownloadsView.css
+++ b/browser/themes/windows/downloads/allDownloadsView.css
@@ -6,19 +6,23 @@
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 6em;
 }
 
 @media (-moz-windows-default-theme) {
-  .downloadProgress > .progress-bar {
+  .downloadProgress::-moz-progress-bar {
     background-color: #3c9af8;
   }
+
+  .downloadProgress[paused]::-moz-progress-bar {
+    background-color: #a6a6a6;
+  }
 }
 
 /*** Highlighted list items ***/
 
 @media (-moz-windows-default-theme) {
   /*
   -moz-appearance: menuitem is almost right, but the hover effect is not
   transparent and is lighter than desired.
--- a/browser/themes/windows/downloads/downloads.css
+++ b/browser/themes/windows/downloads/downloads.css
@@ -32,24 +32,23 @@
     color: #aa1b08;
   }
 
   :root[lwt-popup-brighttext] @item@[verdict="Malware"]:not(:hover) {
     color: #ff0039;
   }
 
   /* Use unified color for the progressbar on default theme */
-  .downloadProgress > .progress-bar {
+  .downloadProgress::-moz-progress-bar {
     background-color: #3c9af8;
   }
 
-  .downloadProgress[paused="true"] > .progress-bar {
+  .downloadProgress[paused]::-moz-progress-bar {
     background-color: #a6a6a6;
   }
-
 }
 
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@ {
   outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
 }