Using CORS to load WebGL textures from cross-domain images

In Firefox, as well as in Chrome, it is now possible to load cross-domain images into WebGL textures, if they have been approved by CORS.

Most prominently, this feature allows for impressive 3D mapping applications such as Google MapsGL and Nokia Maps 3D.

What happened

Earlier this year, the Editor’s Draft WebGL specification got updated in response to a security concern. The additions were:

  1. A mandatory clause disallowing usage of cross-domain elements as WebGL textures in the general case.
  2. A non-normative clause specifically allowing cross-domain elements that have CORS approval. For that occasion, the HTML specification on the <img> element got updated to add a new crossorigin attribute.

The first got implemented in Firefox 5, the second is now in Firefox 8.

How to use this feature

There are two CORS modes: “anonymous” and “use-credentials”. We’ll focus on “anonymous” as it’s the common case. A great example of images served with anonymous CORS is Google Maps imagery, such as:

http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0

In order to load it with CORS as a WebGL texture, we set the crossOrigin attribute on it:

var earthImage = new Image();
earthImage.crossOrigin = "anonymous";

Now we load it as usual:

    earthImage.onload = function() {
      // whatever you usually to do load WebGL textures
    };
    earthImage.src = "http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0";

That’s it! Aside from setting the crossOrigin attribute, we didn’t have to do anything. Here is the full self-contained example.

The HTTP headers

If we study the HTTP headers for this image (using, for example, Firefox’s Web Console), we find that the Request Headers contain

Origin: null

which is the effect of having set this crossOrigin attribute on the img element. And the Response Headers contain

Access-Control-Allow-Origin: null

which is the effect of the server supporting CORS for this file.

Doing this in HTML

Of course, one could also set this attribute in HTML, in which case it’s case-insensitive:

<img src="http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0" crossorigin="anonymous">

And since “anonymous” is both the missing-value-default and the invalid-value-default for the crossorigin attribute, we can pass any invalid value for it, or even just omit its value:

<img src="http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0" crossorigin>

Coming soon: CORS approval for Canvas 2D drawImage

What if you first draw a CORS-approved cross-domain image onto a 2D
canvas, and then use that canvas as the source of a WebGL texture? The
good news is that this will work in Firefox 9, which is hitting the Beta
channel soon. This fix means that demos like this will work really
nicely in Firefox 9.

About Benoit Jacob

I am a software engineer at Mozilla Corp., working on Gecko, specifically the Graphics and WebGL parts. I work from Mozilla's Toronto office.

More articles by Benoit Jacob…


6 comments

  1. Henri Astre

    In a very particular context, I’ve found a workaround that permit to bypass the sop restriction: http://www.visual-experiments.com/2011/10/03/how-to-bypass-webgl-sop-restriction/

    What do you think of this?

    November 8th, 2011 at 14:34

  2. Benoit Jacob

    @Henri: I think it’s smart! Hopefully though, we’ll manage to evangelize content providers to support CORS so that that won’t be needed in the future.

    November 8th, 2011 at 19:43

  3. Ben Adams

    This is fantastic news! Good job!

    November 10th, 2011 at 07:51

  4. Bill

    Is there any way to disable the CORS check for testing purposes? If your actual app and data normally are served from myhost.com but you want to try debugging your app locally with a server running off localhost, it’s handy to be able to turn off the security check temporarily. Chrome does that with a –disable-web-security flag on startup.

    December 15th, 2011 at 18:20

    1. Benoit Jacob

      I’m not aware of such a feature in Firefox. For local URIs there is security.fileuri.strict_origin_policy=false but I don’t know about remote ones. Would be worth filing a bug, i think (if you do, CC me please, :bjacob)

      December 15th, 2011 at 21:01

  5. Henri Astre

    @Bill: for local debugging I’m using a php proxy page using curl extension. I’ve also updated and released the source code of a workaround to bypass sop restriction (only working for chrome/firefox(?) extension). My new workaround is way much faster than the previous one which was doing jpeg decoding in js: http://www.visual-experiments.com/2011/12/05/how-to-bypass-webgl-sop-restriction-v2/

    December 17th, 2011 at 15:55

Comments are closed for this article.