1

In content script in Firefox addon SDK I'm loading image like this way:

var img = new Image();
img.crossOrigin = "Anonymous";
img.src = URL;
img.onload = function (data) {
    var canvas = document.createElement("canvas");
    canvas.width =this.width;
    canvas.height =this.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(this, 0, 0);
    var dataURL = canvas.toDataURL("image/jpeg");
    callback.call(this,dataURL);
}

The request has been done but the response header is empty body, I think the problem in cross origin because it loaded successfully from page allow cross origin.

How can I solve this inside content script? I need the image data to store it in local storage.

Regards, Mohammad.

Noitidart
  • 35,443
  • 37
  • 154
  • 323
Mohammed AlBanna
  • 2,350
  • 22
  • 25

2 Answers2

2

First you should actually check if this is a cross-origin problem. The HTTP response might be blank due to referrer restrictions for example. Although the server should return some kind of error or redirect in that case.

Secondly, just setting the CORS flag on the image itself won't do anything if the server doesn't send the necessary headers.

If this is limited to a specific domain you can use cross-domain content scripts via page-mod or tab.attach by declaring the necessary permissions in the package.json. Then you can fetch the image files with a privileged XHR, turn the received data into a blob url and set that as image source.

If you need to access arbitrary domains then this can't be done with the addon-sdk since it only provides scripts with restricted privileges. There is a lower level API that is similar to sdk content scripts but runs with system privileges: frame scripts. Although you will have to import the XHR constructor into the frame script environment first before you can apply the same approach as above.

the8472
  • 40,999
  • 5
  • 70
  • 122
  • The problem now solved, I don't know what was the problem, I've checked if the server allowed cross origin and it is, it works fine in Chrome. The problem was in "onload" event, but now it works for unknown reaosn! I've also tried to download lowser images sizes and it didn't work, just worked once I used image in my server with cross origin applied in server side. – Mohammed AlBanna Feb 07 '15 at 23:42
  • Yes, as I expected...the problem in the event onload, it works fine in chrome but I don't know what is the problem of it in Firefox :\ – Mohammed AlBanna Feb 08 '15 at 00:07
  • @Mohammad when you find out can you please share what the root cause was, it's nice to know for ourselves and as we help others :) – Noitidart Feb 08 '15 at 04:34
  • @Noitidart Sure, and I respect that :). – Mohammed AlBanna Feb 09 '15 at 13:48
  • @the8472 The problem still there, I think I'll move to request this image from XHR, but I don't see how to convert the response text to base64 image data to store these data into local storage, I'll add this as an answer after testing it very well. [This is the response header](http://i.imgur.com/9v4NwLz.jpg). As I see it works in some images and others no. – Mohammed AlBanna Feb 09 '15 at 13:50
  • 2
    `Access-Control-Allow-Origin: *, *` seems incorrect, if it's supposed to be a wildcard it should be a single `*` – the8472 Feb 09 '15 at 14:20
  • @the8472 Thank you for your time. Why it works fine in the same way on Chrome? I think the only answer is Firefox SDK applies more restrictions here...So, what's your suggestions? And could you please tell me the meaning of wildcard? Regards. – Mohammed AlBanna Feb 09 '15 at 15:44
  • If you want to XHR and download image there are multiple ways, this way doesnt require you converting to base64: [StackOverflow :: How to download image to desktop with OS.File](http://stackoverflow.com/questions/25492225/how-to-download-image-to-desktop-with-os-file) however if you want to convert to base64 then heres the way: [StackOverflow :: Write a data URI to a file in a Firefox extension](http://stackoverflow.com/questions/25145792/write-a-data-uri-to-a-file-in-a-firefox-extension/25148685#25148685). By the way, did changing the `access-control-allow-origin` to single `*` fix it? – Noitidart Feb 09 '15 at 15:46
  • 1
    @Noitidart Thank you for your time and informations. What I'm doing here is downloading the images from `staticflickr.com` and convert it to data and save it to storage. When I suspected on cross origin I've requested image from my server and set allowed origin to * and it works fine. For now, I'll see if the problem is server side I can change the images...I don't know why it works fine in Chrome :\ – Mohammed AlBanna Feb 09 '15 at 15:58
  • Google chrome is like IE for some dev stuff, they automatically fix stuff and deliever what you expect even though the code is broken, this may be one of those times, but I'm no expert especialy on this access-control-allow-origin header thing. – Noitidart Feb 09 '15 at 16:02
0

Finally the problem has been solved, thank you guys for a great discussion. How I solved it:

The problem was a cross origin problem as @the8472 mentioned, so what I did is making the request using SDK for the image and convert its data to base64 based on this answer.

The request usign SDK like this:

var Request = require("sdk/request").Request;
Request({
            url: imageURL,
            overrideMimeType:"text/plain; charset=x-user-defined",
            onComplete: function(imageData) {
                  var imageData = "data:image/jpeg;base64,"+base64Encode(imageData.text);
                  console.log(imageData);
            }
        }).get();

The function of base64Encode which I used from the previous answer is:

function base64Encode(str) {
var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out = "", i = 0, len = str.length, c1, c2, c3;
while (i < len) {
    c1 = str.charCodeAt(i++) & 0xff;
    if (i == len) {
        out += CHARS.charAt(c1 >> 2);
        out += CHARS.charAt((c1 & 0x3) << 4);
        out += "==";
        break;
    }
    c2 = str.charCodeAt(i++);
    if (i == len) {
        out += CHARS.charAt(c1 >> 2);
        out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
        out += CHARS.charAt((c2 & 0xF) << 2);
        out += "=";
        break;
    }
    c3 = str.charCodeAt(i++);
    out += CHARS.charAt(c1 >> 2);
    out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
    out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
    out += CHARS.charAt(c3 & 0x3F);
}
return out;
}

Then I save the result in local storage.

Thank you all :)

Community
  • 1
  • 1
Mohammed AlBanna
  • 2,350
  • 22
  • 25