Looking for alternative to Application.storage

Talk about add-ons and extension development.
Post Reply
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Looking for alternative to Application.storage

Post by Lemon Juice »

Now that Firefox removed FUEL my extension is broken because I use Application.storage in several places to store some values globally. How can I replicate that in new Firefox versions? This is a XUL extension so converting it to SDK is not an option.

What I need is a mechanism to store values in a global variable that is accessible and shared across all browser windows and it doesn't need to persist across browser restarts. If possible, I would like the storage to be able to hold not only simple data but window objects, too (because I use it to store a reference to the window object in one place). Application.storage fulfilled the requirements perfectly.

The closest thing I could find is this: https://discourse.mozilla-community.org ... orage/3198 - the workaround by Chuck Baker uses the most recent window object to store the values so I presume the problem is the storage will be cleared if the window gets closed while others remain open. I need something better than that. Any ideas?
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
Noitidart
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Re: Looking for alternative to Application.storage

Post by Noitidart »

Are you using addon SDK? In which case you can use simple-storage. I don't use SDK but I do same as simple-storage by in an async manner. All they do is store a json file on disk. You can do the same with OS.File, thats what I do - https://discourse.mozilla-community.org ... =noitidart
Noitidart
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Re: Looking for alternative to Application.storage

Post by Noitidart »

I do everything from ChromeWorkers so this is the function I use to write to the same directory that simple-storage uses - https://gist.github.com/Noitidart/78101 ... 936a7952da

What the function does is syncrhonously (as its in a worker) it tries to write to that location, if it finds that the parent folders dont exist, then it creats the dirs to that location then writes.
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Re: Looking for alternative to Application.storage

Post by Lemon Juice »

Thanks, to me writing to files for such simple things seems a bit too much... but I might do it if there is no other way. What concerns me more is that OS.File is supposed to be used in an asynchronous way, which introduces complexity in my code for the most trivial use cases - and if I use it synchronously then I'd have to deal with AMO reviewer complaints... I don't use workers and I don't use SDK. Is there some simple global storage that I can use in a simple and synchronous way? I might even use simple-storage if I knew how to invoke it from a XUL extension.
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
Noitidart
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Re: Looking for alternative to Application.storage

Post by Noitidart »

Lemon Juice wrote:Thanks, to me writing to files for such simple things seems a bit too much... but I might do it if there is no other way. What concerns me more is that OS.File is supposed to be used in an asynchronous way, which introduces complexity in my code for the most trivial use cases - and if I use it synchronously then I'd have to deal with AMO reviewer complaints... I don't use workers and I don't use SDK. Is there some simple global storage that I can use in a simple and synchronous way? I might even use simple-storage if I knew how to invoke it from a XUL extension.
The only sync storage that is safe is for small data and its the pref system. Access time is 1ms which is really fast.

All these storage APIs rely on file system behind the scenes I'm afraid theres no other way :( Workers are awesome you should look into it. Sync behavior in workers is not a bad thing for reviewers. Even sync XHR in workers is a non-issue.
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Re: Looking for alternative to Application.storage

Post by Lemon Juice »

Noitidart wrote:Workers are awesome you should look into it.
I'm sure they are but it's like using a truck to fetch a few grocery items for my dinner! I just want to store and access a few simple numbers in a global variable, do I really need to refactor my code to use workers or other asynchronous stuff? I know it's Mozilla's fault, they are gradually removing features that were available for XUL addons therefore beginning to slowly kill them...
Noitidart wrote:All these storage APIs rely on file system behind the scenes I'm afraid theres no other way :( Workers are awesome you should look into it.
Actually, I've found a way :!: After searching high and low I've found someone who mentioned that you can use localStorage from an extension and attach is to the URL of the XUL overlay - and it works:

Code: Select all

/**
 * Module for storing current extension data (instead of the removed Application.storage in Fx 47).
 * It uses localStorage of the add-on's XUL window
 */
var MyStorage = {
  loadStorage: function() {
    if (this.storage) return;
    
    if (typeof Services == 'undefined') {
      Components.utils.import("resource://gre/modules/Services.jsm");
    }
    
    var url = "chrome://myaddon/content/myOverlay.xul";
    var uri = Services.io.newURI(url, null, null);
    
    let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
      getService(Components.interfaces.nsIScriptSecurityManager).
      getNoAppCodebasePrincipal(uri);
    let dsm = Components.classes["@mozilla.org/dom/localStorage-manager;1"].
      getService(Components.interfaces.nsIDOMStorageManager);
    this.storage = dsm.createStorage(null, principal, "");
  },
  
  get: function(key) {
    this.loadStorage();
    return this.storage.getItem(key);
  },
  
  set: function (key, val) {
    this.loadStorage();
    this.storage.setItem(key, val);
  }
}
The only problem remained how to store a ChromeWindow object in localStorage. I have found no direct way so I used a workaround - I used window.addEventListener("activate") event to attach my custom ID to a new property of the window object so that each window should have its ID and I stored the ID in localStorage. Then in order to get reference to that window by ID I use wm.getEnumerator("navigator:browser") to loop through all open windows and return the one with the given ID. Too convoluted but what can I do when Mozilla is removing stuff?
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Looking for alternative to Application.storage

Post by lithopsian »

You can certainly use local storage from an addon. It is synchronous (which means it isn't entirely loved by Mozilla), shared across most scopes, and persisted between sessions, but it has a number of problems for use in addons. It is intended primarily as a web storage area. Local storage is intimately associated with an "origin", which is a combination of a host, scheme (eg. http), and port. The key/value pairs for a particular local storage origin are only accessible to web content from that origin. Addon scripts can get to any local storage area in the way you describe, but it is a bit of a pain.

Another method for storing a single (small!) piece of information in this way is a preference. Preferences are not accessible to web content, but if that isn't a problem then it should be preferred. Preference access is "instant". Preferences are all stored in memory and synchronised to disk at various times, not necessarily right at time you change them. Performance is not an issue, but storing large (eg. kilo-bytes) values is not considered acceptable. Very large values (is it 100kB now?) will fail, and smaller values will be rejected in the future to minimise overall memory use and the impact of syncing prefs.

Note that local storage is subject to being erased, manually or automatically, although usually only at the end of a session. This is less of a risk with preferences, which can be erased, but never accidentally and only after bypassing a warning that tells the user they could brwak stuff. Depending on user configuration, local storage may break and refuse to store information for a given origin or for all origins.

With what you're looking for, a non-persistent (memory-only) storage would be best. A javascript variable would be ideal. There are any number of ways of having a single system-wide singleton javascript value (eg. javascript code module or just the top level scope of a bootstrap script), but this is now complicated by the split into chrome and content processes. If you need to share values between chrome and content then you will need to synchronise them explicitly. The various message managers have message sending and receiving methods explicitly intended for this. This approach is a little more work for you, but it is far better than synchronously storing persistent data which slows everybody down.
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Looking for alternative to Application.storage

Post by lithopsian »

I was just looking at Application.storage, since I've never used that part of FUEL. It isn't session storage as in DOM storage, but is just a wrapper for a singleton javascript object with some getter and setter functions. There is no associated interprocess communication, so really nothing that you couldn't write for yourself. In fact the existing implementation is still there (until someone spots it!), just not registered so not easy to get at from javascript. Really if that's what you had before, you should just create your own singleton, probably a javascript code module, but an XPCOM component will do if you happen to have one lying around. Then define one or more variables in the singleton, that will be your own personal "storage".

Did you use the change event? That's the only fancy thing really.
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Re: Looking for alternative to Application.storage

Post by Lemon Juice »

lithopsian wrote:I was just looking at Application.storage, since I've never used that part of FUEL. It isn't session storage as in DOM storage, but is just a wrapper for a singleton javascript object with some getter and setter functions. There is no associated interprocess communication, so really nothing that you couldn't write for yourself. In fact the existing implementation is still there (until someone spots it!), just not registered so not easy to get at from javascript. Really if that's what you had before, you should just create your own singleton, probably a javascript code module, but an XPCOM component will do if you happen to have one lying around. Then define one or more variables in the singleton, that will be your own personal "storage".
This is interesting what you write - yes, my needs are very simple, I just need a global variable that will be accessible in all open browser windows, only from chrome scripts, no need to access them from content scripts, no need for change events and can be cleared on closing the browser. I store there a few temporary values like an ID of a last opened preference tab, scroll position of a select box, or IDs of two last focused windows.

Now the crucial part is how do I create a global variable or a singleton like that? A have a script in a xul overlay and I can store values in the window object but that object is separate for each browser window. How to create an object that will be above xul windows and shared among all of them? I don't think I've ever used javascript modules if that is what is needed here.
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
Brummelchen
Posts: 4480
Joined: March 19th, 2005, 10:51 am

Re: Looking for alternative to Application.storage

Post by Brummelchen »

not sure if it helps you, symlinks in windows can create shared data.
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Re: Looking for alternative to Application.storage

Post by Lemon Juice »

lithopsian wrote:Really if that's what you had before, you should just create your own singleton, probably a javascript code module
That was it! I've found a page on javascript modules and they seem to do exactly what I need. I don't know why I missed that part of technology for so long, this seems to elegantly solve many problems where global scope is needed. I created a most simple storage object with get and set methods, put it in a module, imported the module in my scripts and now it's working exactly as intended. Thanks for pointing me in the right direction 8-)
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Looking for alternative to Application.storage

Post by lithopsian »

Congratulations, you have pretty much reproduced Application.storage :) Now if you can just sneak a patch into Firefox ...
Lemon Juice
Posts: 788
Joined: June 1st, 2006, 9:41 am

Re: Looking for alternative to Application.storage

Post by Lemon Juice »

lithopsian wrote:Now if you can just sneak a patch into Firefox ...
I'm afraid I might get caught :mrgreen:
*** SeaMonkey — weird name, sane interface, modern bowels ***
Mouse Gestures for SeaMonkey/Firefox
Convert Fx and TB extensions to SeaMonkey
Post Reply