Search code examples
firefoxfirefox-addon

Accessing global variables in Firefox extensions


I'm writing a Firefox extension which takes a custom switch from the command line and sets a variable inside my cmdline.js in the components directory, we'll call the variable switchDetected which is a boolean. Now based upon this variable I want actions to be carried out in my overlay.js file in the chrome/content directory. The problem I'm having is I can't seem to be able to access the variable switchDetected that is declared in components/cmdline.js from within chrome/contents/overlay.js.

I've tried numerous ways of doing this but nothing seems to work. So I'm just wondering if anyone knows how this can be achieved.


Solution

  • A script loaded in an overlay runs in the context of the browser window - its global variables are stored as properties of the window object corresponding with the browser. If you open a second browser window the same script will load a second time and run in the context of the new browser window - it will have different global variables. The scripts containing XPCOM components on the other hand only load once and they have their independent context that isn't bound to a window. So their global variables cannot be accessed from a browser window directly, just like two browser windows cannot access each others global variables directly.

    Instead the browser window should communicate with the XPCOM component using the usual approach: get a component instance and call its method. If you don't want to define your own interface for that (you probably don't) you can use a trick, something like this:

    CommandLineHandler.prototype = {
      handle: function(commandLine) {...},
      get helpInfo() {...},
      isSwitchDetected: function()
      {
        return switchDetected;
      },
      get wrappedJSObject()
      {
        return this;
      },
      QueryInterface: XPCOMUtils.generateQI(["nsICommandLineHandler"]);
    };
    

    The wrappedJSObject property makes sure that your component can be unwrapped - all its methods and properties will become accessible then and not just the ones defined in the interface. So your overlay script needs to do the following:

    var cmdLineHandler = Components.classes["@myself.com/my-command-line-handler;1"]
                                   .getService()
                                   .wrappedJSObject;
    var switchDetected = cmdLineHandler.isSwitchDetected();