Bug 1573728 - Port Bug 460146 "CSS3 border-image images should appear in Page Info -> Media" and Bug 377364 "Page Info: Suppress the jumping in the bottom half of the Media tab" to SeaMonkey. r=frg a=frg
authorIan Neal <iann_cvs@blueyonder.co.uk>
Fri, 23 Aug 2019 01:16:05 +0200
changeset 32281 e7a66da1bb691167abcda43af1d35ad75796541b
parent 32280 1719d53875e21a68c0f5c7bb9fea3cc9156f2aad
child 32282 4c7254e896da4a576e86382325eb5e58f897ce00
push id211
push userfrgrahl@gmx.net
push dateThu, 22 Aug 2019 23:17:49 +0000
treeherdercomm-esr60@75fdb3e8faed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrg, frg
bugs1573728, 460146, 377364
Bug 1573728 - Port Bug 460146 "CSS3 border-image images should appear in Page Info -> Media" and Bug 377364 "Page Info: Suppress the jumping in the bottom half of the Media tab" to SeaMonkey. r=frg a=frg
suite/browser/pageinfo/pageInfo.js
suite/browser/pageinfo/pageInfo.xul
suite/locales/en-US/chrome/browser/pageInfo.dtd
suite/locales/en-US/chrome/browser/pageInfo.properties
suite/themes/classic/mac/navigator/pageInfo.css
suite/themes/classic/navigator/pageInfo.css
suite/themes/modern/navigator/pageInfo.css
--- a/suite/browser/pageinfo/pageInfo.js
+++ b/suite/browser/pageinfo/pageInfo.js
@@ -285,16 +285,17 @@ var onImagePreviewShown = [ ];
  *                         - doc: (optional) document to use for source. if not provided,
  *                                the calling window's document will be used
  *                         - initialTab: (optional) id of the inital tab to display
  */
 function onLoadPageInfo()
 {
   gBundle = document.getElementById("pageinfobundle");
   var strNames = ["unknown", "notSet", "mediaImg", "mediaBGImg",
+                  "mediaBorderImg", "mediaListImg", "mediaCursor",
                   "mediaObject", "mediaEmbed", "mediaLink", "mediaInput",
                   "mediaVideo", "mediaAudio",
                   "formTitle", "formUntitled", "formDefaultTarget",
                   "formChecked", "formUnchecked", "formPassword", "linkAnchor",
                   "linkArea", "linkSubmission", "linkSubmit", "linkRel",
                   "linkStylesheet", "linkRev", "linkX", "linkScript",
                   "linkScriptInline", "yes"];
   strNames.forEach(function(n) { gStrings[n] = gBundle.getString(n); });
@@ -618,23 +619,45 @@ function addImage(url, type, alt, elem, 
     gImageView.data[i][COL_IMAGE_COUNT]++;
     if (elem == gImageElement)
       gImageView.data[i][COL_IMAGE_NODE] = elem;
   }
 }
 
 function grabAll(elem)
 {
-  // check for background images, any node may have multiple
+  // Check for images defined in CSS (e.g. background, borders),
+  // any node may have multiple.
   var computedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, "");
+
   if (computedStyle) {
-    Array.from(computedStyle.getPropertyCSSValue("background-image")).forEach(function (url) {
-      if (url.primitiveType == CSSPrimitiveValue.CSS_URI)
-        addImage(url.getStringValue(), gStrings.mediaBGImg, gStrings.notSet, elem, true);
-    });
+    var addImgFunc = function (label, val) {
+      if (val.primitiveType == CSSPrimitiveValue.CSS_URI) {
+        addImage(val.getStringValue(), label, gStrings.notSet, elem, true);
+      }
+      else if (val.primitiveType == CSSPrimitiveValue.CSS_STRING) {
+        // This is for -moz-image-rect.
+        // TODO: Reimplement once bug 714757 is fixed
+        var strVal = val.getStringValue();
+        if (strVal.search(/^.*url\(\"?/) > -1) {
+          url = strVal.replace(/^.*url\(\"?/,"").replace(/\"?\).*$/,"");
+          addImage(url, label, gStrings.notSet, elem, true);
+        }
+      }
+      else if (val.cssValueType == CSSValue.CSS_VALUE_LIST) {
+        // recursively resolve multiple nested CSS value lists
+        for (var i = 0; i < val.length; i++)
+          addImgFunc(label, val.item(i));
+      }
+    };
+
+    addImgFunc(gStrings.mediaBGImg, computedStyle.getPropertyCSSValue("background-image"));
+    addImgFunc(gStrings.mediaBorderImg, computedStyle.getPropertyCSSValue("border-image-source"));
+    addImgFunc(gStrings.mediaListImg, computedStyle.getPropertyCSSValue("list-style-image"));
+    addImgFunc(gStrings.mediaCursor, computedStyle.getPropertyCSSValue("cursor"));
   }
 
   // one swi^H^H^Hif-else to rule them all
   if (elem instanceof HTMLAnchorElement)
     gLinkView.addRow([getValueText(elem), elem.href, gStrings.linkAnchor, elem.target, elem.accessKey]);
   else if (elem instanceof HTMLImageElement)
     addImage(elem.src, gStrings.mediaImg,
              (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false);
@@ -983,41 +1006,33 @@ function onImageSelect()
     splitter.collapsed       = false;
     tree.flex = 0;
     makePreview(tree.view.selection.currentIndex);
   }
 }
 
 function makePreview(row)
 {
-  var [url, type, sizeText, alt, count, item, isBG, pageSize, persistent, cachedType] = gImageView.data[row];
+  var [url, type, sizeText, alt, count, item, isBG, imageSize, persistent, cachedType] = gImageView.data[row];
   var isAudio = false;
 
   setItemValue("imageurltext", url);
 
-  if (item.hasAttribute("title") &&
-      !(item instanceof SVGImageElement))
-    setItemValue("imagetitletext", item.title);
-  else
-    setItemValue("imagetitletext", null);
+  var imageText;
+  if (!isBG &&
+      !(item instanceof SVGImageElement) &&
+      !(gDocument instanceof ImageDocument)) {
+    imageText = item.title || item.alt;
 
-  if (item.hasAttribute("longDesc") &&
-      !(item instanceof SVGImageElement))
-    setItemValue("imagelongdesctext", item.longDesc);
-  else
-    setItemValue("imagelongdesctext", null);
+    if (!imageText && !(item instanceof HTMLImageElement))
+      imageText = getValueText(item);
+  }
+  setItemValue("imagetext", imageText);
 
-  if (item instanceof SVGImageElement)
-    setItemValue("imagealttext", null);
-  else if (item.hasAttribute("alt"))
-    setItemValue("imagealttext", item.alt);
-  else if (item instanceof HTMLImageElement || isBG)
-    setItemValue("imagealttext", null);
-  else
-    setItemValue("imagealttext", getValueText(item));
+  setItemValue("imagelongdesctext", item.longDesc);
 
   // get cache info
   var sourceText;
   switch (persistent) {
     case true:
       sourceText = gBundle.getString("generalDiskCache");
       break;
     case false:
@@ -1025,68 +1040,74 @@ function makePreview(row)
       break;
     default:
       sourceText = gBundle.getString("generalNotCached");
       break;
   }
   setItemValue("imagesourcetext", sourceText);
 
   // find out the file size
-  if (pageSize) {
-    var kbSize = Math.round(pageSize / 1024 * 100) / 100;
+  var sizeText;
+  if (imageSize && imageSize != -1) {
+    var kbSize = Math.round(imageSize / 1024 * 100) / 100;
     sizeText = gBundle.getFormattedString("generalSize",
                                           [formatNumber(kbSize),
-                                           formatNumber(pageSize)]);
+                                           formatNumber(imageSize)]);
   }
+  else
+    sizeText = gBundle.getString("mediaUnknownNotCached");
   setItemValue("imagesizetext", sizeText);
 
   var mimeType;
-  var typeString = "mediaImageType";
-  if (!isBG) {
-    if (item instanceof nsIImageLoadingContent) {
-      var imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
-      if (imageRequest) {
-        mimeType = imageRequest.mimeType;
-        if (imageRequest.imageStatus & imageRequest.STATUS_DECODE_COMPLETE &&
-            imageRequest.image.animated)
-          typeString = "mediaAnimatedType";
-      }
+  var numFrames = 1;
+  if (item instanceof HTMLObjectElement ||
+      item instanceof HTMLEmbedElement ||
+      item instanceof HTMLLinkElement)
+    mimeType = item.type;
+
+  if (!mimeType && !isBG && item instanceof nsIImageLoadingContent) {
+    var imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
+    if (imageRequest) {
+      mimeType = imageRequest.mimeType;
+      var image = imageRequest.image;
+      if (image)
+        numFrames = image.numFrames;
     }
-    if (!mimeType &&
-        (item instanceof HTMLObjectElement ||
-         item instanceof HTMLEmbedElement ||
-         item instanceof HTMLLinkElement))
-      mimeType = item.type;
   }
+
   if (!mimeType)
     mimeType = cachedType;
 
   // if we have a data url, get the MIME type from the url
-  if (!mimeType) {
+  if (!mimeType && url.startsWith("data:")) {
     var dataMimeType = /^data:(image\/.*?)[;,]/i.exec(url);
     if (dataMimeType)
       mimeType = dataMimeType[1].toLowerCase();
   }
 
   var imageType;
   if (mimeType) {
     // We found the type, try to display it nicely
-    let imageMimeType = /^image\/(.*)/.exec(mimeType);
+    let imageMimeType = /^image\/(.*)/i.exec(mimeType);
     if (imageMimeType) {
       imageType = imageMimeType[1].toUpperCase();
-      imageType = gBundle.getFormattedString(typeString, [imageType]);
+      if (numFrames > 1)
+        imageType = gBundle.getFormattedString("mediaAnimatedImageType",
+                                               [imageType, numFrames]);
+      else
+        imageType = gBundle.getFormattedString("mediaImageType", [imageType]);
     }
     else {
       // the MIME type doesn't begin with image/, display the raw type
       imageType = mimeType;
     }
   }
   else {
     // We couldn't find the type, fall back to the value in the treeview
-    imageType = gImageView.data[row][COL_IMAGE_TYPE];
+    imageType = type;
   }
 
   setItemValue("imagetypetext", imageType);
 
   var imageContainer = document.getElementById("theimagecontainer");
   var oldImage = document.getElementById("thepreviewimage");
 
   var isProtocolAllowed = checkProtocol(gImageView.data[row]);
@@ -1157,28 +1178,31 @@ function makePreview(row)
   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)
-    imageSize = gBundle.getFormattedString("mediaSize",
-                                           [formatNumber(width),
-                                            formatNumber(height)]);
-  setItemValue("imageSize", imageSize);
-
-  var physSize = "";
-  if (width != physWidth || height != physHeight)
-    physSize = gBundle.getFormattedString("mediaSize",
-                                          [formatNumber(physWidth),
-                                           formatNumber(physHeight)]);
-  setItemValue("physSize", physSize);
+  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);
 
   oldImage.remove();
   imageContainer.appendChild(newImage);
 
   onImagePreviewShown.forEach(function(func) { func(); });
 }
--- a/suite/browser/pageinfo/pageInfo.xul
+++ b/suite/browser/pageinfo/pageInfo.xul
@@ -226,67 +226,57 @@
             <splitter class="tree-splitter"/>
             <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="1"
                      width="1"  id="image-count"    label="&mediaCount;"/>
           </treecols>
           <treechildren flex="1"/>
         </tree>
         <splitter orient="vertical" id="mediaSplitter"/>
         <vbox flex="1" id="mediaPreviewBox">
-          <grid>
+          <grid id="mediaGrid">
             <columns>
-              <column/>
+              <column id="mediaLabelColumn"/>
               <column class="gridSeparator"/>
               <column flex="1"/>
             </columns>
             <rows>
               <row>
-                <label control="imageurltext" value="&mediaURL;"/>
+                <label control="imageurltext" value="&mediaLocation;"/>
                 <separator/>
                 <textbox readonly="true" id="imageurltext" class="urltext"/>
               </row>
               <row>
-                <label control="imagetitletext" value="&mediaTitle;"/>
-                <separator/>
-                <textbox readonly="true" id="imagetitletext"/>
-              </row>
-              <row>
-                <label control="imagealttext" value="&mediaAlt;"/>
-                <separator/>
-                <textbox readonly="true" id="imagealttext"/>
-              </row>
-              <row>
-                <label control="imagelongdesctext" value="&mediaLongdesc;"/>
-                <separator/>
-                <textbox readonly="true" id="imagelongdesctext"/>
-              </row>
-              <row>
                 <label control="imagetypetext" value="&generalType;"/>
                 <separator/>
                 <textbox readonly="true" id="imagetypetext"/>
               </row>
               <row>
                 <label control="imagesourcetext" value="&generalSource;"/>
                 <separator/>
                 <textbox readonly="true" id="imagesourcetext"/>
               </row>
               <row>
                 <label control="imagesizetext" value="&generalSize;"/>
                 <separator/>
                 <textbox readonly="true" id="imagesizetext"/>
               </row>
               <row>
-                <label control="imageSize" value="&mediaDimensions;"/>
+                <label control="imagedimensiontext" value="&mediaDimension;"/>
                 <separator/>
-                <textbox readonly="true" id="imageSize"/>
+                <textbox readonly="true" id="imagedimensiontext"/>
               </row>
               <row>
-                <label control="physSize" value="&mediaPhysDimensions;"/>
+                <label control="imagetext" value="&mediaText;"/>
                 <separator/>
-                <textbox readonly="true" id="physSize"/>
+                <textbox readonly="true" id="imagetext"/>
+              </row>
+              <row>
+                <label control="imagelongdesctext" value="&mediaLongdesc;"/>
+                <separator/>
+                <textbox readonly="true" id="imagelongdesctext"/>
               </row>
             </rows>
           </grid>
           <hbox align="end">
             <vbox>
               <checkbox id="blockImage"
                         hidden="true"
                         oncommand="onBlockImage(this.checked);"
--- a/suite/locales/en-US/chrome/browser/pageInfo.dtd
+++ b/suite/locales/en-US/chrome/browser/pageInfo.dtd
@@ -55,26 +55,24 @@
 <!ENTITY  linkName              "Name">
 <!ENTITY  linkAddress           "Address">
 <!ENTITY  linkType              "Type">
 <!ENTITY  linkTarget            "Target">
 <!ENTITY  linkAccessKey         "Access Key">
 
 <!ENTITY  mediaTab              "Media">
 <!ENTITY  mediaTab.accesskey    "M">
-<!ENTITY  mediaURL              "Address:">
-<!ENTITY  mediaAlt              "Alternate Text:">
+<!ENTITY  mediaLocation         "Location:">
+<!ENTITY  mediaText             "Associated Text:">
 <!ENTITY  mediaAltHeader        "Alternate Text">
 <!ENTITY  mediaAddress          "Address">
 <!ENTITY  mediaType             "Type">
 <!ENTITY  mediaSize             "Size">
 <!ENTITY  mediaCount            "Count">
-<!ENTITY  mediaDimensions       "Specified Dimensions:">
-<!ENTITY  mediaPhysDimensions   "Actual Dimensions:">
-<!ENTITY  mediaTitle            "Title:">
+<!ENTITY  mediaDimension        "Dimensions:">
 <!ENTITY  mediaLongdesc         "Long Description:">
 <!ENTITY  mediaBlockImage.accesskey "B">
 <!ENTITY  mediaSaveAs           "Save As…">
 <!ENTITY  mediaSaveAs.accesskey "A">
 <!ENTITY  mediaSaveAs2.accesskey "e">
 <!ENTITY  mediaPreview          "Media Preview:">
 
 <!ENTITY  feedTab               "Feeds">
--- a/suite/locales/en-US/chrome/browser/pageInfo.properties
+++ b/suite/locales/en-US/chrome/browser/pageInfo.properties
@@ -12,26 +12,32 @@ default=Default
 notSet=Not specified
 yes=Yes
 no=No
 
 mediaImg=Image
 mediaVideo=Video
 mediaAudio=Audio
 mediaBGImg=Background
+mediaBorderImg=Border
+mediaListImg=Bullet
+mediaCursor=Cursor
 mediaObject=Object
 mediaEmbed=Embed
 mediaLink=Icon
 mediaInput=Input
 mediaFileSize=%S KB
 mediaSize=%Spx \u00D7 %Spx
 mediaSelectFolder=Select a Folder to Save the Images
 mediaBlockImage=Block Images from %S
+mediaUnknownNotCached=Unknown (not cached)
 mediaImageType=%S Image
-mediaAnimatedType=Animated %S Image
+mediaAnimatedImageType=%S Image (animated, %S frames)
+mediaDimensions=%Spx \u00D7 %Spx
+mediaDimensionsScaled=%Spx \u00D7 %Spx (scaled to %Spx \u00D7 %Spx)
 
 generalQuirksMode=Quirks mode
 generalStrictMode=Standards compliance mode
 generalNotCached=Not cached
 generalDiskCache=Disk cache
 generalMemoryCache=Memory cache
 generalSize=%S KB (%S bytes)
 generalMetaTag=Meta (1 tag)
--- a/suite/themes/classic/mac/navigator/pageInfo.css
+++ b/suite/themes/classic/mac/navigator/pageInfo.css
@@ -101,16 +101,24 @@ textbox[disabled] {
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
 }
 
+#mediaGrid {
+  min-height: 9em;
+}
+
+#mediaLabelColumn {
+  min-width: 10em;
+}
+
 #thepreviewimage {
   margin: 1em;
 }
 
 treechildren::-moz-tree-cell-text(broken) {
   font-style: italic;
   color: graytext;
 }
--- a/suite/themes/classic/navigator/pageInfo.css
+++ b/suite/themes/classic/navigator/pageInfo.css
@@ -49,16 +49,24 @@ textbox[disabled] {
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
 }
 
+#mediaGrid {
+  min-height: 9em;
+}
+
+#mediaLabelColumn {
+  min-width: 10em;
+}
+
 #thepreviewimage {
   margin: 1em;
 }
 
 treechildren::-moz-tree-cell-text(broken) {
   font-style: italic;
   color: graytext;
 }
--- a/suite/themes/modern/navigator/pageInfo.css
+++ b/suite/themes/modern/navigator/pageInfo.css
@@ -48,16 +48,24 @@ textbox[disabled] {
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
 }
 
+#mediaGrid {
+  min-height: 9em;
+}
+
+#mediaLabelColumn {
+  min-width: 10em;
+}
+
 #thepreviewimage {
   margin: 1em;
 }
 
 treechildren::-moz-tree-cell-text(broken) {
   font-style: italic;
   color: #999999;
 }