Bug 1356306 - fix restoring large images from draft. r=aceman,jorgk a=jorgk
authorJorg K <jorgk@jorgk.com> and aceman <acelists@atlas.sk>
Sat, 15 Apr 2017 01:48:00 +0200
changeset 24466 b850fc61a632
parent 24465 509cbae906af
child 24467 d6ba4d8b1bcf
push id2059
push usermozilla@jorgk.com
push dateMon, 17 Apr 2017 06:53:03 +0000
treeherdercomm-aurora@9d19a9b732a0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaceman, jorgk, jorgk
bugs1356306
Bug 1356306 - fix restoring large images from draft. r=aceman,jorgk a=jorgk
mail/components/compose/content/MsgComposeCommands.js
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -5424,17 +5424,22 @@ function InitEditor()
         .messageServiceFromURI(gMsgCompose.originalMsgURI);
       let originalMsgNeckoURI = {};
       msgSvc.GetUrlForUri(gMsgCompose.originalMsgURI, originalMsgNeckoURI, null);
       if (src.startsWith(originalMsgNeckoURI.value.spec)) {
         // Reply/Forward/Edit Draft/Edit as New can contain references to
         // images in the original message. Load those and make them data: URLs
         // now.
         event.target.classList.add("loading-internal");
-        loadBlockedImage(src);
+        try {
+          loadBlockedImage(src);
+        } catch (e) {
+          // Couldn't load the referenced image.
+          Components.utils.reportError(e);
+        }
       }
       else {
         // Appears to reference a random message. Notify and keep blocking.
         gComposeNotificationBar.setBlockedContent(src);
       }
     }
     else {
       // For file:, and references to parts of random messages, show the
@@ -5626,16 +5631,19 @@ function onBlockedContentOptionsShowing(
  * Handle clicking the "Load <url>" in the blocked content notification bar.
  * @param {String} aURL - the URL that was unblocked
  * @param {Node} aNode  - the node holding as value the URLs of the blocked
  *                        resources in the message (space separated).
  */
 function onUnblockResource(aURL, aNode) {
   try {
     loadBlockedImage(aURL);
+  } catch (e) {
+    // Couldn't load the referenced image.
+    Components.utils.reportError(e);
   } finally {
     // Remove it from the list on success and failure.
     let urls = aNode.value.split(" ");
     for (let i = 0; i < urls.length; i++) {
       if (urls[i] == aURL) {
         urls.splice(i, 1);
         aNode.value = urls.join(" ");
         if (urls.length == 0) {
@@ -5645,17 +5653,20 @@ function onUnblockResource(aURL, aNode) 
       }
     }
   }
 }
 
 /**
  * Convert the blocked content to a data URL and swap the src to that for the
  * elements that were using it.
+ *
  * @param {String} aURL - (necko) URL to unblock
+ *
+ * @throw Error()  if reading the data failed
  */
 function loadBlockedImage(aURL) {
   let filename;
   if (/^file:/i.test(aURL)) {
     filename = aURL.substr(aURL.lastIndexOf("/") + 1);
   }
   else {
     let fnMatch = /[?&;]filename=([^?&]+)/.exec(aURL);
@@ -5683,18 +5694,27 @@ function loadBlockedImage(aURL) {
     Services.scriptSecurityManager.getSystemPrincipal(),
     null,
     Components.interfaces.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
     Components.interfaces.nsIContentPolicy.TYPE_OTHER);
   let inputStream = channel.open();
   let stream = Components.classes["@mozilla.org/binaryinputstream;1"]
     .createInstance(Components.interfaces.nsIBinaryInputStream);
   stream.setInputStream(inputStream);
-  let encoded = btoa(stream.readBytes(stream.available()));
+  let streamData = "";
+  try {
+    while (stream.available() > 0) {
+      streamData += stream.readBytes(stream.available());
+    }
+  } catch(e) {
+    stream.close();
+    throw new Error("Couln't read all data from URL=" + aURL + " (" + e +")");
+  }
   stream.close();
+  let encoded = btoa(streamData);
   let dataURL = "data:" + contentType +
     (filename ? ";filename=" + encodeURIComponent(filename) : "") +
     ";base64," + encoded;
 
   let editor = GetCurrentEditor();
   for (let img of editor.document.images) {
     if (img.src == aURL) {
       img.src = dataURL; // Swap to data URL.