Jump to content

CrossOrigin issue using data URIs


ianmcgregor
 Share

Recommended Posts

Hi,
 
I'm trying to load some images as data URIs (data:image/jpeg;base64,/9j/4AAQSk...) from the browser's localStorage for offline play (my game makes use of dynamic images loaded through a web api).
 
 
The issue is that the Phaser.Loader.loadFile method always adds a crossOrigin attribute to the image object, which breaks loading data images.
 
If I modify the method as below it fixes it:
if(file.url !== null && file.url.indexOf('data:image/') === 0) {    file.data.src = file.url;}else {    file.data.crossOrigin = this.crossOrigin;    file.data.src = this.baseURL + file.url;}

Has anyone else come up against this issue and found a way to work around it without modifying the Phaser source code?

 

Ian

 
 
Link to comment
Share on other sites

  • 1 year later...

 

Thanks, I didn't know that was possible. It's working great:

var data = new Image();data.src = assets[i].url; // 'data:image/...'game.cache.addImage(assets[i].key, assets[i].url, data);

 

This works great in Chrome, but it doesn't work at all in Safari. 

 

If you check for the image in game.cache._images, the frame object doesn't have the expected width/height (I'm not sure if that causes the problem, or is an effect of the problem, as I don't entirely understand what that property does).

 

At any rate, if you try to create a Phaser.Image with it, the image won't draw to the canvas in Safari. 

Link to comment
Share on other sites

  • 5 months later...

Yeah, 1 year later and I'm still having the issue. Neither this:

var data = new Image();data.src = assets[i].url; // 'data:image/...'game.cache.addImage(assets[i].key, assets[i].url, data);

Nor this:

var data = new Image();data.crossOrigin = 'anonymous';data.src = assets[i].url; // 'data:image/...'game.cache.addImage(assets[i].key, assets[i].url, data);

Nor this:

​var data = new Image();data.crossOrigin = 'anonymous';data.src = assets[i].url; // 'data:image/...'data.onload = function () {game.cache.addImage(assets[i].key, assets[i].url, data);}

Nor this:

game.load.image(assets[i].key, assets[i].url); 

Will work when assets[i].url is an image data URL (base64). I simply can't figure out a way to get an image into the cache this way. Only having this problem in Safari, Chrome is fine.

Link to comment
Share on other sites

Try adding an "onload" handler to that image. Inside the onload handler, add the image to the cache. That guarantees that the image is ready and parsed... it has the unfortunate side-effect of making your load async but hopefully that won't be a problem.

Link to comment
Share on other sites

Try adding an "onload" handler to that image. Inside the onload handler, add the image to the cache. That guarantees that the image is ready and parsed... it has the unfortunate side-effect of making your load async but hopefully that won't be a problem.

So I go through each and every instance of where I load images and do it with onload. I even needed to do it on images loaded the normal way (not as strings but URLs) because those were throwing cross origin errors in safari as well, for whatever reason. It manages to get rid of all the errors in Safari for each image load and leaving me with one simple error: the canvas is tainted, DOM security breach, etc. 

 

IF, I don't set crossOrigin to true before adding the src ... all of the images fail to load and throw security errors in Chrome. 

 

I've been plagued with these crossOrigin errors since day one. It's like swatting flies. Fix 1 in one browser, 5 more pop up in another. Fix those, and the original fix in the other browser breaks. Finally fix them all and end up with one generic untraceable error... Seriously, this crossOrigin thing makes no sense. I've been studying it and troubleshooting it for over a year now and it still makes no sense. I spend about half of my dev time these days on crossOrigin errors. I'm almost tempted to say "fuck it, I'm supporting Chrome and nothing else." 

 

apO97QC.png

Link to comment
Share on other sites

Hi, 

 

in my mobile apps (Cordova / Javascript / Phaser), i use this CORS policy and i can load / save data image (from a canvas element) without error.

<meta http-equiv="Content-Security-Policy" content="default-src 'self' https: http: data: gap: ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src *; connect-src 'self' http://<localip>:<localport>/ http://www.mysite.ch">

You can either remove or modify websites http://<localip>:<localport>/ and http://www.mysite.ch

Link to comment
Share on other sites

Hi, 

 

in my mobile apps (Cordova / Javascript / Phaser), i use this CORS policy and i can load / save data image (from a canvas element) without error.

<meta http-equiv="Content-Security-Policy" content="default-src 'self' https: http: data: gap: ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src *; connect-src 'self' http://<localip>:<localport>/ http://www.mysite.ch">

You can either remove or modify websites http://<localip>:<localport>/ and http://www.mysite.ch

Sorry, that doesn't do anything. 

Link to comment
Share on other sites

I've resorted to adding a random number as a URL parameter to each image phaser loads. Basically, I am tricking the browser into thinking that each image it requests is a new image and is not in cache. 

 

It's seriously fucked up that I have to do this because it means no browser cache (i.e. longer load time). I am on a very unusual build with AWS S3 and cloudfront - somewhere along the way the images aren't getting the proper cross origin headers.

 

Anyway, safari has a completely different issue. It throws cross origin security errors no matter what I do when the image is a data URI string. Guess I'm not supporting Safari then!

Link to comment
Share on other sites

  • 3 months later...
On 8 January 2016 at 6:53 AM, Gob0 said:

Finally got a result with your codepen example  :D

 

Try this:


game.cache.addImage('image-data', data.src, data);

Tried this with

 

let im = new Image();
			im.crossOrigin = 'anonymous';
			im.onload = function(data){
				game.cache.addImage('qr', im.src, im);
				let qr = game.add.image(game.world.centerX, game.world.centerY, 'qr', 1);
				qr.anchor.set(0.5);
			};
			im.src = 'https://api.qrserver.com/v1/create-qr-code/?data=' +
		encodeURIComponent( 'http://' + window.location.hostname + ':3000/mobile.html#' + game.uniqid) +
		'&amp;size=100x100','QR CODE ' + game.uniqid;

 

 

but doesn't work.....How did you get it to work?

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...