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

2

10

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?

Flocculus answered 1/4, 2011 at 9:15 Comment(0)
G
13

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;
}
Groundhog answered 1/4, 2011 at 15:33 Comment(1)
Fantastic, just the information I needed. My extension is now working and happily desaturating photos. (And I got unicorns!)Flocculus
N
1

So I too was working on an extension where I wanted to use image data from cross-domain acquired images and I found that IT IS POSSIBLE! (without any funky background page message passing)

@Serg, As it turns out, in web pages you can't do cross-domain stuff, however, after some further digging however, I found that in chrome extensions, you can!

The jist of it is, all you have to do is request permissions for Cross-Origin XMLHttpRequests in your manifest.

{
  "name": "My extension",
  ...
  "permissions": [
    "http://www.google.com/"
  ],
  ...
}

For more info (especially about how to remain secure) read this.

Nicky answered 22/8, 2011 at 13:16 Comment(3)
As you can see in my original question, I had already granted those permissions. Perhaps something has changed in the last four or five months? Because it always seemed sensible that the permissions should affect image data as well as XMLHttpRequests...Flocculus
Did you try it? I believe i was successful.Nicky
It looks like this approach might work in Chrome 13 (which was released several months after I asked the original question) and onwards. From that page: "Version note: As of Chrome 13, content scripts can make cross-origin requests to the same servers as the rest of the extension. Before Chrome 13, a content script couldn't directly make requests; instead, it had to send a message to its parent extension asking the extension to make a cross-origin request. "I've not had time to go back and re-try my original code, though.Flocculus

© 2022 - 2024 — McMap. All rights reserved.