Bug 1397486 - Update controlBar width according to videocontrols which really grows along <audio> width. r=jaws draft
authorRay Lin <ralin@mozilla.com>
Thu, 14 Sep 2017 17:37:47 +0800
changeset 670877 02ad5cd0906da81569bba74e29b899478ebd19c0
parent 670875 70158e4e215d784d1391db5e517b18727f4b3683
child 733340 f80349bcf43f58498bb57a934b227d6d52e79fdb
push id81743
push userbmo:ralin@mozilla.com
push dateWed, 27 Sep 2017 00:28:57 +0000
reviewersjaws
bugs1397486
milestone58.0a1
Bug 1397486 - Update controlBar width according to videocontrols which really grows along <audio> width. r=jaws MozReview-Commit-ID: LpxH7Pnu7tQ
toolkit/content/tests/widgets/head.js
toolkit/content/tests/widgets/test_audiocontrols_dimensions.html
toolkit/content/widgets/videocontrols.xml
--- a/toolkit/content/tests/widgets/head.js
+++ b/toolkit/content/tests/widgets/head.js
@@ -22,17 +22,20 @@ function waitForCondition(condition, nex
     tries++;
   }, 100);
   var moveOn = function() { clearInterval(interval); nextTest(); };
 }
 
 function getAnonElementWithinVideoByAttribute(video, aName, aValue) {
   const domUtils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"].
     getService(SpecialPowers.Ci.inIDOMUtils);
-  const videoControl = domUtils.getChildrenForNode(video, true)[1];
+  // <videocontrols> is the second anonymous child node of <video>, but
+  // the first child node of <audio>.
+  const videoControlIndex = video.nodeName == "VIDEO" ? 1 : 0;
+  const videoControl = domUtils.getChildrenForNode(video, true)[videoControlIndex];
 
   return SpecialPowers.wrap(videoControl.ownerDocument)
     .getAnonymousElementByAttribute(videoControl, aName, aValue);
 }
 
 function executeTests() {
   return tests
     .map(fn => () => new Promise(fn))
--- a/toolkit/content/tests/widgets/test_audiocontrols_dimensions.html
+++ b/toolkit/content/tests/widgets/test_audiocontrols_dimensions.html
@@ -1,38 +1,48 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Audio controls test</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="head.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 
 <div id="content">
   <audio id="audio" controls preload="auto"></audio>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-  function loadedmetadata(event) {
-    is(event.type, "loadedmetadata", "checking event type");
-    is(audio.clientHeight, 40, "checking height of audio element");
+  const audio = document.getElementById("audio");
+  const controlBar = getAnonElementWithinVideoByAttribute(audio, "anonid", "controlBar");
 
-    SimpleTest.finish();
-  }
-
-  var audio = document.getElementById("audio");
+  add_task(async function setup() {
+    await SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]});
+    await new Promise(resolve => {
+      audio.addEventListener("loadedmetadata", resolve, {once: true});
+      audio.src = "audio.wav";
+    })
+  });
 
-  SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, startTest);
-  function startTest() {
-    // Kick off test once audio has loaded.
-    audio.addEventListener("loadedmetadata", loadedmetadata);
-    audio.src = "audio.wav";
-  }
+  add_task(async function check_audio_height() {
+    is(audio.clientHeight, 40, "checking height of audio element");
+  });
+
+  add_task(async function check_controlbar_width() {
+    const originalControlBarWidth = controlBar.clientWidth;
 
-  SimpleTest.waitForExplicitFinish();
+    isnot(originalControlBarWidth, 400, "the default audio width is not 400px");
+
+    audio.style.width = "400px";
+    audio.offsetWidth; // force reflow
+
+    isnot(controlBar.clientWidth, originalControlBarWidth, "new width should differ from the origianl width");
+    is(controlBar.clientWidth, 400, "controlbar's width should grow with audio width");
+  });
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -1665,19 +1665,20 @@
           .reduce((accWidth, cc) => accWidth + cc.minWidth, minControlBarPaddingWidth);
         // Skip the adjustment in case the stylesheets haven't been loaded yet.
         if (!minRequiredWidth) {
           return;
         }
 
         let givenHeight = this.video.clientHeight;
         let videoWidth = (this.isAudioOnly ?
-                          this.controlBar.clientWidth :
+                          this.videocontrols.clientWidth :
                           this.video.clientWidth) || minRequiredWidth;
         let videoHeight = this.isAudioOnly ? this.controlBarMinHeight : givenHeight;
+        let videocontrolsWidth = this.videocontrols.clientWidth;
 
         let widthUsed = minControlBarPaddingWidth;
         let preventAppendControl = false;
 
         for (let control of this.prioritizedControls) {
           if (!control.isWanted) {
             control.hideByAdjustment = true;
             continue;
@@ -1702,17 +1703,24 @@
         // should fix the dimensions in order not to recursively trigger reflow afterwards.
         if (this.video instanceof HTMLAudioElement) {
           if (givenHeight) {
             // The height of controlBar should be capped with the bounds between controlBarMinHeight
             // and controlBarMinVisibleHeight.
             let controlBarHeight = Math.max(Math.min(givenHeight, this.controlBarMinHeight), this.controlBarMinVisibleHeight);
             this.controlBar.style.height = `${controlBarHeight}px`;
           }
-          this.controlBar.style.width = `${videoWidth}px`;
+          // Bug 1367875: Set minimum required width to controlBar if the given size is smaller than padding.
+          // This can help us expand the control and restore to the default size the next time we need
+          // to adjust the sizing.
+          if (videocontrolsWidth <= minControlBarPaddingWidth) {
+            this.controlBar.style.width = `${minRequiredWidth}px`;
+          } else {
+            this.controlBar.style.width = `${videoWidth}px`;
+          }
           return;
         }
 
         if (videoHeight < this.controlBarMinHeight ||
             widthUsed === minControlBarPaddingWidth) {
           this.controlBar.setAttribute("size", "hidden");
           this.controlBar.hideByAdjustment = true;
         } else {