Mauvis Ledford
Mauvis Ledford

Reputation: 42374

Solution for Firefox user disabling cookies and thus localStorage - polyfill not possible

After a complaint from one of our users and running some tests it appears Firefox 15 and 16 (and probably older version) make it so if you disable cookies you also disable localStorage. You can't even create a polyfill for it as whenever you try to access window.localStorage you get Error: The operation is insecure.

Throwing a try catch will let you check to see if it's disabled but won't let you replace the variable with your own solution. The following quick polyfill will not work because FF ignores setting the variable and will throw the same error when trying to access it:

try{
       window.localStorage;
}catch(err){
        window.localStorage = {
              getItem: function(k){
                   return this.k;
              },
              setItem: function(k,v){
                   this.k = v;
              }
        };
}

The only solution seems to be move the "fake" localStorage to another variable but this would be annoying as we have lots of code and a js lib that rely on accessing this variable. Any solutions?

Edit: It is not optimal to just pop up an alert to tell the users that cookies are required. If visitors just want to view the site and not signup then they truly don't need cookies. But being a backbone.js application and passing around a lot of data, we do store stuff in localStorage quite a bit.

Upvotes: 10

Views: 3016

Answers (3)

Nick Sharp
Nick Sharp

Reputation: 1891

You have two options:

1) Take advantage of lexical scoping and how lookups work... for example, if your code is running in a closure, then inside that closure you can run the following:

var localStorage = window.localStorage || {... polyfill here...};

Then within your code just use localStorage instead of the fully qualified window.localStorage. The advantage here is just the way lexical variable lookups work it will find your more "closely" scoped version rather than the global. PS... you should probably be running in a closure anyways so this should be possible.

2) just variable rename, similar to the inverse of what people do to remove vendor prefixes.

window.pLocalStorage = window.localStorage || {... polyfill here...};

Then just change your code to use pLocalStorage instead of localStorage... if their browser supports it, then it will use the native, otherwise the polyfill.

Upvotes: 1

Ast Derek
Ast Derek

Reputation: 2729

Since localStorage is a reserved variable, you have no other sane option than using a wrapper with a different name. Wrap your own code and the real localStorage under this variable and replace localStorage with the name of your wrapper. Annoying, but less annoying than losing changes.

Upvotes: 1

DeMeNteD
DeMeNteD

Reputation: 385

We use this as our lib for Local storage.

(function (window, $, undefined) {
    var store = window.store = {};

    function deserialize(val) {
        if (!val) return null;
        var obj = $.parseJSON(val);
        return obj;
    };

    function processRequest(loc, key, value) {
        var obj;
        // if value is not specified at all assume we are doing a get.
        if (value === undefined) {
            // GET
            obj = loc.getItem(key);
            return deserialize(value);
        } else {
            // SET
            loc.setItem(key, JSON.stringify(value));
        }
    }

    store.Local = function(key, value) {
        return processRequest(window.localStorage, key, value);
    };

    store.Session = function(key, value) {
        return processRequest(window.sessionStorage, key, value);
    };
} (window, jQuery));

You could easily add some testing code to fallback on a non-persistent array.

Upvotes: 0

Related Questions