Bug 1576411 - Port Bug 1326910 "wait for a loadend event before using the width and height of the Page Info media preview" to SeaMonkey. r=frg a=frg
authorIan Neal <iann_cvs@blueyonder.co.uk>
Sat, 28 Sep 2019 18:16:49 +0200
changeset 32315 5c0d3f86a9a60c6728bd856313572004ce0b8064
parent 32314 3f35f2caac8c39b0cf3b348660b9f4c8356fd642
child 32316 b61f35e0c01dada21bc6bc910de8f157b2024fb3
push id219
push userfrgrahl@gmx.net
push dateSat, 28 Sep 2019 16:19:15 +0000
treeherdercomm-esr60@5c0d3f86a9a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrg, frg
bugs1576411, 1326910
Bug 1576411 - Port Bug 1326910 "wait for a loadend event before using the width and height of the Page Info media preview" to SeaMonkey. r=frg a=frg
suite/browser/pageinfo/pageInfo.js
--- a/suite/browser/pageinfo/pageInfo.js
+++ b/suite/browser/pageinfo/pageInfo.js
@@ -581,22 +581,17 @@ function addImage(imageViewRow)
           var kbSize = Math.round(imageSize / 1024 * 100) / 100;
           row[2] = gBundle.getFormattedString("mediaFileSize",
                                               [formatNumber(kbSize)]);
           row[7] = imageSize;
         }
         row[8] = cacheEntry.persistent;
         row[9] = getContentTypeFromHeaders(cacheEntry);
         // Invalidate the row to trigger a repaint.
-        var currentIndex = gImageView.data.indexOf(row);
-        gImageView.tree.invalidateRow(currentIndex);
-        if (gImageView.selection.count == 1 &&
-            gImageView.selection.currentIndex == currentIndex) {
-          makePreview(currentIndex);
-        }
+        gImageView.tree.invalidateRow(gImageView.data.indexOf(row));
       }
     });
 
     // Add the observer, only once.
     if (gImageView.data.length == 1) {
       Services.obs.addObserver(imagePermissionObserver, "perm-changed");
     }
   }
@@ -902,99 +897,116 @@ function makePreview(row)
   var physWidth = 0, physHeight = 0;
   var width = 0, height = 0;
 
   if ((item.HTMLLinkElement || item.HTMLInputElement ||
        item.HTMLImageElement || item.SVGImageElement ||
       (item.HTMLObjectElement && isImageType) ||
       (item.HTMLEmbedElement && isImageType) ||
        isBG) && isProtocolAllowed) {
-    newImage.setAttribute("src", url);
-    physWidth = newImage.width || 0;
-    physHeight = newImage.height || 0;
+    // We need to wait for the image to finish loading before
+    // using width & height.
+    newImage.addEventListener("loadend", function() {
+      physWidth = newImage.width || 0;
+      physHeight = newImage.height || 0;
+
+      // "width" and "height" attributes must be set to newImage,
+      // even if there is no "width" or "height attribute in item;
+      // otherwise, the preview image cannot be displayed correctly.
+      // Since the image might have been loaded out-of-process, we expect
+      // the item to tell us its width / height dimensions. Failing that
+      // the item should tell us the natural dimensions of the image. Finally
+      // failing that, we'll assume that the image was never loaded in the
+      // other process (this can be true for favicons, for example), and so
+      // we'll assume that we can use the natural dimensions of the newImage
+      // we just created. If the natural dimensions of newImage are not known
+      // then the image is probably broken.
+      if (!isBG) {
+        newImage.width = ("width" in item && item.width) ||
+                         newImage.naturalWidth;
+        newImage.height = ("height" in item && item.height) ||
+                          newImage.naturalHeight;
+      }
+      else {
+        // The width and height of an HTML tag should not be used for its
+        // background image (for example, "table" can have "width" or "height"
+        // attributes).
+        newImage.width = item.naturalWidth || newImage.naturalWidth;
+        newImage.height = item.naturalHeight || newImage.naturalHeight;
+      }
+
+      if (item.SVGImageElement) {
+        newImage.width = item.SVGImageElementWidth;
+        newImage.height = item.SVGImageElementHeight;
+      }
+
+      width = newImage.width;
+      height = newImage.height;
+
+      document.getElementById("theimagecontainer").collapsed = false
+      document.getElementById("brokenimagecontainer").collapsed = true;
 
-    // "width" and "height" attributes must be set to newImage,
-    // even if there is no "width" or "height attribute in item;
-    // otherwise, the preview image cannot be displayed correctly.
-    // Since the image might have been loaded out-of-process, we expect
-    // the item to tell us its width / height dimensions. Failing that
-    // the item should tell us the natural dimensions of the image. Finally
-    // failing that, we'll assume that the image was never loaded in the
-    // other process (this can be true for favicons, for example), and so
-    // we'll assume that we can use the natural dimensions of the newImage
-    // we just created. If the natural dimensions of newImage are not known
-    // then the image is probably broken.
-    if (!isBG) {
-      newImage.width = ("width" in item && item.width) || newImage.naturalWidth;
-      newImage.height = ("height" in item && item.height) || newImage.naturalHeight;
+      let imageSize = "";
+      if (url) {
+        if (width != physWidth || height != physHeight) {
+          imageSize = gBundle.getFormattedString("mediaDimensionsScaled",
+                                                 [formatNumber(physWidth),
+                                                  formatNumber(physHeight),
+                                                  formatNumber(width),
+                                                  formatNumber(height)]);
+        } else {
+          imageSize = gBundle.getFormattedString("mediaDimensions",
+                                                 [formatNumber(width),
+                                                  formatNumber(height)]);
+        }
+      }
+      setItemValue("imagedimensiontext", imageSize);
+    }, {once: true});
+
+    newImage.setAttribute("src", url);
+  }
+  else {
+    // Handle the case where newImage is not used for width & height.
+    if (item.HTMLVideoElement && isProtocolAllowed) {
+      newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
+      newImage.id = "thepreviewimage";
+      newImage.src = url;
+      newImage.controls = true;
+      width = physWidth = item.videoWidth;
+      height = physHeight = item.videoHeight;
+
+      document.getElementById("theimagecontainer").collapsed = false
+      document.getElementById("brokenimagecontainer").collapsed = true;
+    }
+    else if (item.HTMLAudioElement && isProtocolAllowed) {
+      newImage = new Audio;
+      newImage.id = "thepreviewimage";
+      newImage.src = url;
+      newImage.controls = true;
+      newImage.preload = "metadata";
+      isAudio = true;
+
+      document.getElementById("theimagecontainer").collapsed = false
+      document.getElementById("brokenimagecontainer").collapsed = true;
     }
     else {
-      // The width and height of an HTML tag should not be used for its
-      // background image (for example, "table" can have "width" or "height"
-      // attributes).
-      newImage.width = item.naturalWidth || newImage.naturalWidth;
-      newImage.height = item.naturalHeight || newImage.naturalHeight;
-    }
-
-    if (item.SVGImageElement) {
-      newImage.width = item.SVGImageElementWidth;
-      newImage.height = item.SVGImageElementHeight;
+      // fallback image for protocols not allowed (e.g., javascript:)
+      // or elements not [yet] handled (e.g., object, embed).
+      document.getElementById("brokenimagecontainer").collapsed = false;
+      document.getElementById("theimagecontainer").collapsed = true;
     }
 
-    width = newImage.width;
-    height = newImage.height;
-
-    document.getElementById("theimagecontainer").collapsed = false
-    document.getElementById("brokenimagecontainer").collapsed = true;
-  }
-  else if (item.HTMLVideoElement && isProtocolAllowed) {
-    newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
-    newImage.id = "thepreviewimage";
-    newImage.src = url;
-    newImage.controls = true;
-    width = physWidth = item.videoWidth;
-    height = physHeight = item.videoHeight;
-
-    document.getElementById("theimagecontainer").collapsed = false
-    document.getElementById("brokenimagecontainer").collapsed = true;
-  }
-  else if (item.HTMLAudioElement && isProtocolAllowed) {
-    newImage = new Audio;
-    newImage.id = "thepreviewimage";
-    newImage.src = url;
-    newImage.controls = true;
-    newImage.preload = "metadata";
-    isAudio = true;
-
-    document.getElementById("theimagecontainer").collapsed = false
-    document.getElementById("brokenimagecontainer").collapsed = true;
-  }
-  else {
-    // fallback image for protocols not allowed (e.g., javascript:)
-    // or elements not [yet] handled (e.g., object, embed).
-    document.getElementById("brokenimagecontainer").collapsed = false;
-    document.getElementById("theimagecontainer").collapsed = true;
-  }
-
-  var imageSize = "";
-  if (url && !isAudio) {
-    if (width != physWidth || height != physHeight) {
-      imageSize = gBundle.getFormattedString("mediaDimensionsScaled",
-                                             [formatNumber(physWidth),
-                                              formatNumber(physHeight),
-                                              formatNumber(width),
-                                              formatNumber(height)]);
-    }
-    else {
+    let imageSize = "";
+    if (url && !isAudio) {
       imageSize = gBundle.getFormattedString("mediaDimensions",
                                              [formatNumber(width),
                                               formatNumber(height)]);
     }
+    setItemValue("imagedimensiontext", imageSize);
   }
-  setItemValue("imagedimensiontext", imageSize);
 
   makeBlockImage(url);
 
   oldImage.remove();
   imageContainer.appendChild(newImage);
 }
 
 function makeBlockImage(url)