SECURITY_ERR: DOM Exception 18 on using getImageData in a Chrome Extension

Matt Gibson picture Matt Gibson · Apr 1, 2011 · Viewed 17.8k times · Source

I'm writing my first Chrome extension. I'm trying to use jQuery and the jQuery Image Desaturate plugin to desaturate an image on a page on http://www.flickr.com.

I'm loading my script (and jQuery and the plugin) programatically in my background.html:

  // On browser action click, we load jQuery and the desaturate plugin, then 
  // call our own flickrnoir.js to desaturate the photo.
  chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.executeScript(null, { file: "jquery.js" }, function() {
      chrome.tabs.executeScript(null, {file: "jQuery.desaturate.js" }, function() {
        chrome.tabs.executeScript(null, { file: "flickrnoir.js" });
      })
    });
  });

I've specified permissions for Flickr pages in my manifest.json:

"permissions": [
  "tabs", "http://www.flickr.com/", "http://*.static.flickr.com/"
]

That appears to be working fine, and I can, for example, turn the background of all divs on a Flickr photo page red by adding this to flickrnoir.js, and then opening up a Flickr page and clicking on my extension's button:

$("div").css("background-color", "#ff0000");

...so, I successfully have jQuery loaded and it can successfully access and change DOM elements of a http://*.flickr.com/* page.

However, when I try to use the desaturate plugin to desaturate an image (or all images, in fact) I run across a security error. My code:

$("img").desaturate();

...eventually ends up in the jQuery.desaturate plugin's code running this line:

var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);

At that point, Chrome throws a security exception:

Uncaught Error: SECURITY_ERR: DOM Exception 18

...and this stops me in my tracks.

EDIT: Okay, so I'm guessing this is because the page is at www.flickr.com, whereas the image I'm copying to the canvas is at farm6.static.flickr.com? Is that violating the cross-domain policy?

I'm really not familiar yet with the Chrome extension security model, or cross-domain restrictions on canvas, or how the two interact, so I could use any help you can give me in understanding this, but of course, my fundamental question is -- how do I get past this security exception and get my code working?

Answer

serg picture serg · Apr 1, 2011

Yep, this is a security limitation. As it says in the specs:

Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.

Whenever the getImageData() method of the 2D context of a canvas element whose origin-clean flag is set to false is called with otherwise correct arguments, the method must raise a SECURITY_ERR exception.

Whenever the measureText() method of the 2D context of a canvas element ends up using a font that has an origin that is not the same as that of the Document object that owns the canvas element, the method must raise a SECURITY_ERR exception.

When I was working on a similar extension what I did was I passed an image url from a content script to a background page and did all canvas manipulations there, then converted canvas to data url and send it back to a content script:

//background.html:
function adjustImage(src, tab) {
    var img = new Image();
    img.onload = function() {
            var canvas = Pixastic.process(img);
            
            chrome.tabs.sendRequest(tab.id, {cmd: "replace", data: canvas.toDataURL()});
    };
    img.src = src;
}