Bug 715075 - Page Info reads image width and height synchronously after setting src, leads to 0px x 0px if the image isn't in your cache (e.g. after clearing cache). r=mak
☠☠ backed out by 22f24157e6ea ☠ ☠
authorDario Bertero <anrvrx@gmail.com>
Thu, 15 Nov 2012 20:34:56 -0500
changeset 113448 ed72449453b499ffeb66bf4053d6faed65406fe1
parent 113447 b7c7be527638eb90e30e46f757582cb77924afbc
child 113449 cc2469a8b41ad3d3472f3cd691e25c4d9f50558b
push id23872
push useremorley@mozilla.com
push dateFri, 16 Nov 2012 17:06:27 +0000
treeherdermozilla-central@a7ed19f7d21a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs715075
milestone19.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 715075 - Page Info reads image width and height synchronously after setting src, leads to 0px x 0px if the image isn't in your cache (e.g. after clearing cache). r=mak
browser/base/content/pageinfo/pageInfo.js
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -811,31 +811,31 @@ function saveMedia()
     }
   } else {
     selectSaveFolder(function(aDirectory) {
       if (aDirectory) {
         var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
           internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
                        aChosenData, aBaseURI, gDocument);
         };
-      
+
         for (var i = 0; i < rowArray.length; i++) {
           var v = rowArray[i];
           var dir = aDirectory.clone();
           var item = gImageView.data[v][COL_IMAGE_NODE];
           var uriString = gImageView.data[v][COL_IMAGE_ADDRESS];
           var uri = makeURI(uriString);
-  
+
           try {
             uri.QueryInterface(Components.interfaces.nsIURL);
             dir.append(decodeURIComponent(uri.fileName));
           } catch(ex) {
             /* data: uris */
           }
-  
+
           if (i == 0) {
             saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI));
           } else {
             // This delay is a hack which prevents the download manager
             // from opening many times. See bug 377339.
             setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri),
                        makeURI(item.baseURI));
           }
@@ -935,17 +935,17 @@ function makePreview(row)
       var imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
       if (imageRequest) {
         mimeType = imageRequest.mimeType;
         var image = imageRequest.image;
         if (image)
           numFrames = image.numFrames;
       }
     }
-    
+
     if (!mimeType)
       mimeType = getContentTypeFromHeaders(cacheEntry);
 
     // if we have a data url, get the MIME type from the url
     if (!mimeType && url.startsWith("data:")) {
       let dataMimeType = /^data:(image\/[^;,]+)/i.exec(url);
       if (dataMimeType)
         mimeType = dataMimeType[1].toLowerCase();
@@ -974,28 +974,43 @@ function makePreview(row)
     }
     setItemValue("imagetypetext", imageType);
 
     var imageContainer = document.getElementById("theimagecontainer");
     var oldImage = document.getElementById("thepreviewimage");
 
     var isProtocolAllowed = checkProtocol(gImageView.data[row]);
 
+    function updateMediaDimensions(physWidth, physHeight, width, height) {
+      var imageSize = "";
+      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);
+    };
+
     var newImage = new Image;
     newImage.id = "thepreviewimage";
-    var physWidth = 0, physHeight = 0;
-    var width = 0, height = 0;
 
-    if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement ||
-         item instanceof HTMLImageElement ||
-         item instanceof SVGImageElement ||
-         (item instanceof HTMLObjectElement && mimeType.startsWith("image/")) || isBG) && isProtocolAllowed) {
-      newImage.setAttribute("src", url);
-      physWidth = newImage.width || 0;
-      physHeight = newImage.height || 0;
+    function readImageDimensions() {
+      // Check if another media has been loaded in the meanwhile.
+      if (newImage.getAttribute("src") != url)
+        return;
+
+      var physWidth = newImage.width || 0;
+      var 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.
       if (!isBG) {
         newImage.width = ("width" in item && item.width) || newImage.naturalWidth;
         newImage.height = ("height" in item && item.height) || newImage.naturalHeight;
       }
@@ -1006,69 +1021,71 @@ function makePreview(row)
         newImage.height = newImage.naturalHeight;
       }
 
       if (item instanceof SVGImageElement) {
         newImage.width = item.width.baseVal.value;
         newImage.height = item.height.baseVal.value;
       }
 
-      width = newImage.width;
-      height = newImage.height;
+      var width = newImage.width;
+      var height = newImage.height;
+
+      document.getElementById("theimagecontainer").collapsed = false;
+      document.getElementById("brokenimagecontainer").collapsed = true;
+
+      updateMediaDimensions(physWidth, physHeight, width, height);
+    };
 
-      document.getElementById("theimagecontainer").collapsed = false
-      document.getElementById("brokenimagecontainer").collapsed = true;
+    if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement ||
+         item instanceof HTMLImageElement ||
+         item instanceof SVGImageElement ||
+         (item instanceof HTMLObjectElement && mimeType.startsWith("image/")) || isBG) && isProtocolAllowed) {
+      newImage.setAttribute("src", url);
+      // Hide the field by default, so it's shown only when available.
+      setItemValue("imagedimensiontext", "");
+
+      // Wait for the image to be loaded before checking its
+      // dimensions, because it may not have been cached yet.
+      newImage.onload = readImageDimensions;
     }
 #ifdef MOZ_MEDIA
     else if (item instanceof HTMLVideoElement && isProtocolAllowed) {
       newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
       newImage.id = "thepreviewimage";
       newImage.mozLoadFrom(item);
       newImage.controls = true;
-      width = physWidth = item.videoWidth;
-      height = physHeight = item.videoHeight;
 
       document.getElementById("theimagecontainer").collapsed = false;
       document.getElementById("brokenimagecontainer").collapsed = true;
+
+      updateMediaDimensions(item.videoWidth, item.videoHeight, item.videoWidth, item.videoHeight);
     }
     else if (item instanceof HTMLAudioElement && isProtocolAllowed) {
       newImage = new Audio;
       newImage.id = "thepreviewimage";
       newImage.src = url;
       newImage.controls = true;
       isAudio = true;
 
       document.getElementById("theimagecontainer").collapsed = false;
       document.getElementById("brokenimagecontainer").collapsed = true;
+
+      setItemValue("imagedimensiontext", "");
     }
 #endif
     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;
+
+      setItemValue("imagedimensiontext", "");
     }
 
-    var imageSize = "";
-    if (url && !isAudio) {
-      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);
-
     makeBlockImage(url);
 
     imageContainer.removeChild(oldImage);
     imageContainer.appendChild(newImage);
 
     onImagePreviewShown.forEach(function(func) { func(); });
   });
 }