21 February 2008

Cross Browser Cookies with Flash

Is it possible to have cross browser cookies, in JavaScript? Unfortunately each browser stores this in their own cookie data.

Problem with regular cookies is that it's specific to a browser, so if save cookies in Firefox (my browser of choice), when I go to Safari non of my preferences are available.

demo

launch this web page in two seperate browsers, and keep them side by side. Next just playing around with the cookie values, and go back and forth between browsers to see that it has the new values. You see if you set the cookie to a value, and click the other browser window you can access the values immediately. Cool !!


how is it done?

So it dawned on me that Flash stores cookies in a totally different format. It's a local file on your hard drive that is independent of the browser, which means, no matter what the browser ... it accesses the same cookie. I also know that Flash can talk to JavaScript. So why not merge the two???

I quickly whipped up a Flash cookie file with getters and setters. That was a whopping 500 bytes. That's not too shabby. Then a nice JavaScript file that 1.7kilo bytes uncompressed. So approximately to 2kb will give you cross browser cookies.

code break down: actionscript

I created a small 10x10 Flash file and wrote Flash cookie functions.

import flash.external.*;

var so:SharedObject = SharedObject.getLocal("cookies","/");
var oo:Object = new Object;
oo['is_capable'] = true;

if (so.data.is_capable == null)
{
	so.data.is_capable = true;
	so.data.oo = oo;
	so.flush();	
}
else
{
	oo = so.data.oo;
}

This sets up a Flash cookie called "cookies", and Object "oo" for storing all the cookie values. I had to use an object to store cookie values as I couldn't set values with so.data['cookie_key']=cookie_value, but I could do this oo['cookie_key']= cookie_value. The Flash cookie can store Objects fine. Next was a basic test to see if cookie was already set, if not ... then create one set the variables and write to the file immediately with flush() ... otherwise retrieve Object from cookie.

var getFunction:String    		= "f_get_cookie";
var getRealFunction:Function	= get_flash_cookie;

ExternalInterface.addCallback(getFunction, null, getRealFunction);

Next I set up Function name, and a JavaScript function name variables. The Flash function is made available to JavaScript by use of the ExternalInterface.addCallback.

function save_flash_cookie():Void
{
	so.data.oo = oo;
	so.flush();	
}

function delete_flash_cookie(cookie_key:String):Void
{
	if(!cookie_able()) return;
	
	oo[cookie_key] = null;
	delete oo[cookie_key];
	
	save_flash_cookie();
}

function get_flash_cookie(cookie_key):String
{
	if(!cookie_able()) return '';
	
	delete so;
	so = SharedObject.getLocal("cookies","/");
	oo = so.data.oo;

	if (oo[cookie_key] && oo[cookie_key] != undefined) 
	{		
		return oo[cookie_key];
	}

	return '';
}

function set_flash_cookie(cookie_key:String,cookie_val:String):Void
{
	if(!cookie_able()) return;	
	
	delete so;
	so = SharedObject.getLocal("cookies","/");
	oo = so.data.oo;
	
	oo[cookie_key] = cookie_val; 	
	save_flash_cookie();
}

ExternalInterface.call('flash_ready',null);  

I then wrote a getter, a setter, and a delete. To set the value, I used the Object to store data oo[cookie_key] = cookie_val; and write it to the cookie file so.data.oo = oo; so.flush();. Before I get OR set you notice that I deleted the cookie and regot it. Basically when browsers were side by side, I couldn't force it to reread the cookie to see if value was different.

As a final step I call a Javascript function via ExternalInterface.call to tell JavaScript the flash file is ready. I tried using DOM and onload, but none of those seem to be reliable and were very buggy.

code break down: javascript

I only going to explain this briefly. I suggest you download the source to see all the functions.


var cookie_id  = 'CBCookie';

get_movie: function()
{
	if (navigator.appName.indexOf("Microsoft") != -1)
	{
		this.flash_cookie = window[this.cookie_id];
	}
	else
	{
		this.flash_cookie =  document[this.cookie_id];
	}

	return ((this.flash_cookie) ? true : false);
}

This method to grab a reference to the movie I cribbed from the genius moock. Maybe you can use getDocumentById

set: function(key,val)
{
	this.flash_cookie.f_set_cookie(key,val);
}

Lastly, we call the the Flash function using the name we specified in ActionScript using ExternalInterface.addCallback.

code break down: html

You have a basic object/embed, but to test locally and I pulled a few hairs on this one is to use allowScriptAccess and set the value to always

final notes

This was done very quickly and there is room for improvement. I am curious what real world application there are. Is it a viable thing to worry about cookies cross browser. Here are some things that I would add to it if I get time:

I am uncertain what the real world use of this, seems like there could be quite a few.

source

CB_Cookie.zip
 

comment

We call this as isolated storage in Silverlight. :)

2008-02-22
Michael Sync

Michael thanks for writing in. I have been meaning to look into Silverlight. Seems very cool and powerful.

2008-02-22
Daniel Bulli2

Excellent article again. I wonder if this actually could be a viable solution for the problem which occurred in the 4.0.6 release over here .

regards, marios

2008-03-06
Marios

This only applies to browsers on windows using the ActiveX flash player as far as I can tell

2008-04-18
Thom Shannon

Thanks for your great tutorial Michael!
I did exactly the same as you wrote but I always get null value when I do the f_get_cookie in Javascript. Do you have any idea?

2008-04-22
Justin

Justin who is Michael ;)?

Justin + Thom:
Can you point me somewhere … I have tested in all combinations and it seems to be working as expected.

2008-04-22
Daniel Bulli2

it doesnt work with subdomeins

2008-05-07
Kees

Danny B, this Cross browser implementation works in Internet explorer? I’ve been having trouble in internet explorer, I always get the following error: CB_Cookie is undefined. Any idea why this fail in IE. You online examples work perfect, but when I dowload them they fail.

thanks

2008-09-20
juan Lozano

Juan … I don’t see this error, do you have an example somewhere?

2008-09-22
Daniel Bulli2

Juan, replace “application/javascript” with “text/javascript” in the script tag for CB_Cookie_Compressed.js.

2008-10-08
Tom M

I have found a problem with local apps (not served by a http server). The function

flash_ready()

never gets called. I am not sure why. Of course in consequence CB_Cookie stuff is not initialized and does not work. To duplicate the problem extract contents of the zip file from this page to a folder and double click on index.htm to launch the demo app. Click on ‘alert(CB_Cookie.get(‘kookie’))’ link. You will get the message

CB_Cookie not initialized correctly

I use IE7 under Windows 2003. Maybe a security setting or something …Any ideas?

2008-11-22
LukeB

I am uncertain what the real world use of this, seems like there could be quite a few. *****************************************
oh no worries, there’s pretty plenty of good reason to make use of a cross browser cookie.
For instance I’ve a Desktop app that display a web browser within( by default will use IE DLLs as my app was written in C#)
Some users might come to my web site through FF so HTTP_REFERER info would get lost.
This way I can store my info and play around within my desktop application without caring of the browser users used to get on my web site.
Hope makes sense.
Regards
Alex

2008-11-27
Alex B

Great article DannyB. I was very much in need of this. But i was not able to run the sample directly. I was getting the error CB_Cookie is undefined. I just changed window to document in
get_movie: function() { this.flash_cookie = document[this.cookie_id]; } }
and its started working on IE..:). But yet i am not able to run it on Mozilla..:( Please help me..

2010-01-12
vivekbhat

Thanks for the nice article. Is there a windows version of the .zip file? It looks like a mac version.

2010-01-13
I.Adam

great article. i was wondering if there was a way to set the cookie on page load, instead of clicking on the link to set the cookie.

2010-07-20
jordan

nice, thank you! how to set the cookie on page load? if I call the set func on onLoad it alerts: CB_Cookie not initialized correctly

2010-09-06
daniel


note: you can only submit after you hit preview


nuff-respec is a weblog written by daniel bulli a senior web programmer in boston, ma.
more >

contact | resume | profile | twitter

recently :::