views:

157

answers:

2

I have an addon that every 5 minuets or so checks an rss feed for a new post, and if there is one, it displays an alert(). Problem is, I'm afraid that if the user opens multiple windows, that when there's a new post a millions of alerts will popup saying the same thing. Is there anyway to have just one "brain" running at a time?

Thanks in advance!

+3  A: 

Look up something called "Javascript shared code modules" or JSMs.

Primary docs are here:

https://developer.mozilla.org/En/Using_JavaScript_code_modules

Each .js file in your addon that needs shared memory will open with the following line:

Components.utils.import("resource://xxxxxxxx/modules/[yourFilenameHere].jsm", com.myFirefoxAddon.shared);

The above line opens [yourFilenameHere].jsm and loads its exported (see below) functions and variables into the com.myFirefoxAddon.shared object. Each instance of that object loaded will point to the same instance in memory.

Note that if you want to have any hope of you addon making it past moderation, you will need to write all your code in a com.myFirefoxAddon.* type object as the goons at AMO are preventing approval of addons that do not Respect the Global Namespace

The biggest caveat for JSM is that you need to manually export each function that you want to be available to the rest of your code... since JS doesn't support public/private type stuff this strikes me as a sort of poor-man's "public" support... in any case, you will need to create an EXPORTED_SYMBOLS array somewhere in your JSM file and name out each function or object that you want to export, like this:

var EXPORTED_SYMBOLS = [
    /* CONSTANTS */
    "SERVER_DEBUG",
    "SERVER_RELEASE",

    "LIST_COUNTRIES",
    "LIST_TERRITORIES_NOEX",

    /* GLOBAL VARIABLES */
    /* note: primitive type variables need to be stored in the globals object */
    "urlTable",
    "globals",

    /* INTERFACES */
    "iStrSet",

    /* FUNCTIONS */
    "globalStartup",

    /* OBJECTS */
    "thinger",
    "myObject"

]
Tom the Junglist
Wow...that sounds complicated, I'm guessing it's because I'm just starting out. Perhaps you could give me a scenario to help me understand..?
motionman95
Wait a sec. On second thought, couldn't I just launch a hidden dialog or something and leave my code running in it..?
motionman95
Instead of exporting lots of stuff, you could just export one object and assign it to com.myFirefoxAddon.shared.
Nickolay
Indeed you can, however I prefer this method as it's less typing when you're doing the other code.
Tom the Junglist
@motionman95 its actually quite simple once you get the hang of it. I had to learn this stuff when I was "just starting out"... so it's not impossible. You can do it! ...also, I would not advice doing hidden window stuff... it's...messy
Tom the Junglist
@Tom since I now agree JS modules can be used for this, I think it would be a good idea to provide an actual example of using JSM as a "brain" and not just a shared memory. The MDC docs unfortunately don't have such examples currently.
Nickolay
@Nickolay It's actually quite simple. Study the MDC docs closely... you can run whatever javascript you want inside the JSM as long as you don't need DOM access... DOM functions need to be replaced with their XPCOM equivalents. Otherwise it is fairly simple... the JSM acts as a static object class to all the code it is instantiated in.
Tom the Junglist
Also wanted to note that to use timers inside a JSM you need to use nsiTimers, as SetInterval() and SetTimeout() is part of DOM. I havent tried this but I think you can use your JSM timer to fire an event that invidivual windows can subscribe to
Tom the Junglist
+1  A: 

[edited] Modules are not the right solution to this problem, since the code will still be imported into every window and the whatever listeners/timers you set up will run in every window. You should be careful with using modules for this -- all the timers/callbacks must be set up in the module code (not just using the observer object defined in the module) and you shouldn't use any references to the window in the module.

The right way to do this is I would prefer to write an XPCOM component (in JS). It's somewhat complicated, yes and I don't have a handy link explaining how to do it. One thing: implementing it using XPCOMUtils is easier, older documentation will throw lots of boilerplate code on you.

Nickolay
I didn't check; won't the second import simply reuse the namespace without running code again?
Tobu
I beg to disagree. Code modules are loaded once across the entire Firefox process, don't require boilerplate COM instantiation, and require no more setup than what I mentioned. If you poke around the source code to a lot of 3.0+ addons this is how they used shared memory.
Tom the Junglist
As a matter of practice I stay the hell away from COM whenever possible. Probably want to take that into account
Tom the Junglist
I take the "not right solution" comment back, sorry. I still think it's harder to reason about modules than about XPCOM components, but maybe it's just because I spent a few years with the latter :)
Nickolay
FWIW, I also tend to prefer the XPCOM component solution, though the other is also valid.
Tobu