Search code examples
htmlcanvassame-origin-policygetimagedatafile-uri

Canvas getImageData() after drawing image from file:// URI - need workaround for all browsers


I'm developer of Construct 2, a HTML5 game editor for Windows. It's at http://www.scirra.com.

Recently I've been trying to add a feature that will modify an image by transforming it on a canvas. It's pretty straightforward - draw an Image to the canvas and call getImageData() to get the pixels.

When the user clicks 'preview' in our application, all the files are dumped to a temp file on disk and a browser launched to show it. Uploading to a server is not an option for previewing - some games are megabytes big.

However most browsers block you using getImageData() to get the pixels of any image loaded from disk at all. I've tried putting all the necessary image files in subdirectories as MDN suggests in its description of file:// access policies. That doesn't work either!

Chrome's --allow-file-access-from-files flag fixes it. However, I need to support all major browsers. Is there a similar workaround for at least Internet Explorer and Firefox? I have no idea about Internet Explorer, and I really wish there's something which doesn't involve manually going to about:config in Firefox, otherwise we will be deluged in support requests asking "why doesn't it work in Firefox?!".

Also, why on earth is this security policy necessary?!? It seems way over the top and makes applications like ours really difficult to write.

Any help appreciated.


Solution

  • Your name sounds familiar from HN.

    This is pretty laid out in stone in the spec by now, though this upsets an awful lot of people. http:// and file:// are different origins, and anything that tries to put one on the other will dirty the origin. As you noted file uri's themselves have their own set of rules that make things even trickier.

    Drawing something to a canvas whose origin is not the same? Too bad, the origin-clean flag henceforth is false, which then disallows you from doing various things.

    A complete list of those things is located in the spec here.

    But I'm sure you know all this by now. You want to get around it.

    I'd suggest ins instead of trying to strong-arm the browsers around it, you bundle in some kind of lightweight web service so that things are all appearing from the same origin. It will cause a lot fewer headaches in the future.

    You'll probably want something like the Python SimpleHTTPServer. But that decision really depends on what you've already got included in your product already at this point.