See:
- http://en.wikipedia.org/wiki/Same_origin_policy
- http://www.w3.org/TR/cors/
- http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/

Basically, this is the problem: when loading JS via

tags, there is no problem, since tags don't need to honor the same origin policy. When you load JS dynamically (e.g. TinyMCE, Panels, etc.), you're violating the same origin policy. The only way around that in older browsers is by using JSONP. Newer browsers support the CORS specification, which allows you to safely load resources from other origins. See http://www.metaltoad.com/blog/using-jsonp-safely for a nice explanation. Browser support (source: http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing):
CORS is supported by all browsers based on the following layout engines: - Gecko 1.9.1 (Firefox 3.5[3], SeaMonkey 2.0[4]) and above - WebKit (Initial revision uncertain, Safari 4 and above[5], Google Chrome 3 and above... possibly earlier[6]) - MSHTML/Trident 4.0 (Internet Explorer 8) provides partial support via the XDomainRequest object.[5] The following browsers are also noteworthy in their lack of CORS support: - Opera does not implement CORS as of version 10.61[7]. - Camino does not implement CORS in the 2.0.x release series as these versions are based on Gecko 1.9.0.[8] - As of version 0.10.2, Arora exposes WebKit's CORS-related APIs, but attempted cross-origin requests will fail. [9]
So, unfortunately, we'll still have to use JSONP maintain a blacklist of files (specifically JS files) until all browsers (or at least the majority of all internet visits) support CORS. That's at least a few years away. So there's no real rush to support CORS in the CDN module. However, there is one already fairly common case: the loading of web fonts in Firefox >= 3.5. Web fonts are only supported in recent browsers, and recent browsers support CORS. Hence it makes sense to add CORS support for those files (also see #895064: @font-face doesn't work in firefox). See http://openfontlibrary.org/wiki/Blocking_font_linking_from_other_websites for an example. So at least this subset of CORS should be supported by the CDN module. It should at least be documented, but preferably, the CDN module would update the .htaccess file. This does not block the release of version 2.0, it can easily be added later on.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tombigel’s picture

You have one mistake:
Web Fonts (the EOT format) is supported since IE 4, and SVG fonts are also supported in fairly older browsers.
See here: http://webfonts.info/wiki/index.php?title=@font-face_browser_support

Wim Leers’s picture

You're absolutely right. I should have worded that better. But the only combination for which CORS support makes sense today, are today's web font standards in Firefox.

mr.baileys’s picture

Version: 6.x-2.0-rc6 » 7.x-2.x-dev
Status: Active » Needs review
FileSize
835 bytes

I had filed #1427178: Firefox, CDN, fonts and the W3C Access Control Specification. before finding this issue, so I've marked that one as duplicate of this. Text from that issue copied below:

Firefox 3.5 and above implement the W3C Access Control specification. This causes Firefox to reject requests to cross-domain resources when the request is initiated by XHttpRequest or when requesting fonts, unless the server serving those requests specifically allows cross-domain usage of the resource, for example by using the Access-Control-Allow-Origin header.

We discovered this while troubleshooting missing/incorrect fonts on our site when viewing it with Firefox. The fonts were served by CloudFront based off a CDN far-future URL. All other browsers succesfully rendered the font.

Attached is a patch that we have currently implemented to circumvent the problem. It could be improved by specifying the actual domains in the access control directive (although I don't know how to reliably get a list of possible domain names for a site), and maybe by only setting the Access Control directive for those files where it is needed.

References:

Wim Leers’s picture

Status: Needs review » Needs work

This would work for your case, but:
- it would not work when the Far Future expiration setting is not enabled; we'll need to document that
- it could be more specific (as you already indicate): it could list only the allowed domains, which would prevent other domains from hotlinking — though this would probably also break pages served from Google's cache, for example. So I'm not sure adding this specificity is a good idea in the first place

We could hardcode a check that only adds this header for font files. But OTOH, it doesn't hurt to have this enabled for other resources.

Thoughts?

Wim Leers’s picture

Wim Leers’s picture

Also, this won't work on Amazon Cloudfront (which I know you're using) or even S3. See https://forums.aws.amazon.com/thread.jspa?threadID=34281 and https://forums.aws.amazon.com/thread.jspa?threadID=84659.
Solution: store the font as a data URI in a CSS file.

mr.baileys’s picture

Don't know about S3, but it does seem to work for Amazon Cloudfront:

curl http://<amazon-cloudfront-domain>/cdn/farfuture/cache:lyte5d/sites/default/themes/wpp/fonts/akkstdrg-webfont.woff --head
HTTP/1.0 200 OK
Date: Sat, 04 Feb 2012 15:53:11 GMT
Server: Apache
X-Drupal-Cache: MISS
Expires: Tue, 20 Jan 2037 04:20:42 GMT
Last-Modified: Wed, 20 Jan 1988 04:20:42 GMT
X-Powered-By: Drupal CDN module
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: max-age=290304000, no-transform, public
Content-Length: 31296
Content-Type: application/octet-stream
Age: 105
Vary: Accept-Encoding
X-Cache: Hit from cloudfront
X-Amz-Cf-Id: HeTLL1Us2emhbN3RdS0LGBxAbLsvbPUf3UYLcIWZQnmg0_MSG-iP3w==,XuiRlwX6TDbTVhg1EA7nYep4MioUW7kG-d5y1TiyzVRur7x_n8dr1Q==
Via: 1.0 d9552fc5d203b7c80e0dc882434351b8.cloudfront.net:11180 (CloudFront), 1.0 9a2c78ff08ad47db2bb61d22094add8a.cloudfront.net:11180 (CloudFront)
Connection: close
Wim Leers’s picture

I see. Hurray, then! :)

Wim Leers’s picture

Also: thoughts regarding #4?

mr.baileys’s picture

Status: Needs work » Needs review
FileSize
1.34 KB

While the patch in #3 fixed the issue for us, I agree with you that it only works when using the far-future option, might not work with different CDN providers and the "*" could be considered to broad.

Hence it's probably best not to add the header via code, but rather document the issue and tell people how to fix it (and tailor the solution to their specific set-up). Here's a draft blurb, might need some polishing... (Let me know if you think there should be a similar text for the Advanced Help).

mr.baileys’s picture

(Note that the "exclude files from being served by CDN" in the patch might not work yet due to #1428530: Override CSS aggregation to ensure correct file URL altering for files referenced by CSS files)

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

I'm going to a combination of #3 and #10. I think it makes sense to support the 90% use case of allowing all origins to load all "farfutured" files. The documentation you've provided helps in understanding all aspects of the problem.

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
Status: Reviewed & tested by the community » Fixed

With only minor changes, plus an entry in the Advanced Help and a (trivial) backport to D6, I've committed #3 and #10. Of course, I've credited you :) Keep the patches coming!

D7: http://drupalcode.org/project/cdn.git/commit/bb99307
D6: http://drupalcode.org/project/cdn.git/commit/6d42fe8

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.