Cross-Domain LocalStorage

As you may know, LocalStorage is domain based. You can’t read or write from localstorage that’s on different domain, even if that’s subdomain. But there is iframe trick that you can use to store data from domain to it’s subdomain.

Basically to have Cross-Domain LocalStorage, you create an iframe that’s hosted on your other domain, then you send PostMessage to that iframe and inside iframe you set that value of localStorage.
Here is the code:

iFrame

window.onmessage = function(e) {
  if (e.origin !== "http://example.com") {
    return;
  }
  var payload = JSON.parse(e.data);
  localStorage.setItem(payload.key, JSON.stringify(payload.data));
};

main file

window.onload = function() {
    var win = document.getElementsByTagName('iframe')[0].contentWindow;
    var obj = {
       name: "Jack"
    };
    win.postMessage(JSON.stringify({key: 'storage', data: obj}), "*");
};

<a href="http://other.example.com/iframe.html">http://other.example.com/iframe.html</a>

If you want to save and load value from LocalStorage, you can PostMessage with method key that will indicate what action it need to take. You can also send message back from iframe to it’s parent with data read from localStorage.

iframe

document.domain = "example.com";
window.onmessage = function(e) {
    if (e.origin !== "http://example.com") {
        return;
    }
    var payload = JSON.parse(e.data);
    switch(payload.method) {
        case 'set':
            localStorage.setItem(payload.key, JSON.stringify(payload.data));
            break;
        case 'get':
            var parent = window.parent;
            var data = localStorage.getItem(payload.key);
            parent.postMessage(data, "*");
            break;
        case 'remove':
            localStorage.removeItem(payload.key);
            break;
    }
};

Your main page on example.com

window.onload = function() {
    var iframe = document.getElementsByTagName('iframe')[0];
    var win;
    // some browser (don't remember which one) throw exception when you try to access
    // contentWindow for the first time, it work when you do that second time
    try {
        win = iframe.contentWindow;
    } catch(e) {
        win = iframe.contentWindow;
    }
    var obj = {
       name: "Jack"
    };
    // save obj in subdomain localStorage
    win.postMessage(JSON.stringify({key: 'storage', method: "set", data: obj}), "*");
    window.onmessage = function(e) {
        if (e.origin != "http://other.example.com") {
            return;
        }
        // this will log "Jack"
        console.log(JSON.parse(e.data).name);
    };
    // load previously saved data
    win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
};

Here is a demo that use my sysend library to send messages to other tab in same browser (the library use localStorage for this). It use iframe proxy to send message from jcubic.pl to terminal.jcubic.pl and vice versa. Iframe is hosted on both domains. (everything is done by the library, you only need to include the file from repo on other.example.com domain and call sysend.proxy('http://other.example.com')).

The only caveat is that in Firefox, it seems that you need to enable CORS on Iframe. If you use apache server you can enable it in .htaccess file with this code:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods: "GET"

it will enable CORS for all files, if you want to enable CORS for a single file, this should work:

<Files "iframe.html">
  Header set Access-Control-Allow-Origin "*"
  Header set Access-Control-Allow-Methods: "GET"
</Files>

And that’s it you now can have Cross-Domain LocalStorage.