Archives For May 2011

>I am on my third project where I need to create a custom property on every web page in Firefox. Creating custom properties used to be somewhat of a hack, with mixed results, but today it is trivial.

For the release of Firefox 4, the content team created a new component, nsIDOMGlobalPropertyInitializer, which is a mouthful, but is a tasty morsel, I promise!

The basic procedure is this:

1. Create a JS Constructor and prototype with *some* XPCOM gunk

2. Make sure the prototype has an init() method

3. The object returned from the init method is the object lazily added to each web page

4. The init() method accepts an nsIDOMWindow argument if you need access to the window in your property

5. Name the new window property in your .manifest file

Here is an example:

let Cu = Components.utils;let Ci = Components.interfaces;let Cc = Components.classes;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");Cu.import("resource://gre/modules/Services.jsm");

function DOMCryptAPI() {}

DOMCryptAPI.prototype = {

  classID: Components.ID("{3d92fb7f-be77-475c-992a-5235615f9189}"),

  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,                                         Ci.nsIObserver,]),

  init: function DA_init(aWindow) {

    let self = this;

    this.window = XPCNativeWrapper.unwrap(aWindow);

    let api = {

      // "pk": Public Key encryption namespace      pk: {        encrypt: self.encrypt.bind(self),        decrypt: self.promptDecrypt.bind(self),        sign: self.sign.bind(self),        verify: self.verify.bind(self),        generateKeypair: self.beginGenerateKeypair.bind(self),        getPublicKey: self.getPublicKey.bind(self)      },

      hash: {        SHA256: self.SHA256.bind(self)      },

      __exposedProps__: {        pk: "r",        hash: "r",      },    };

    return api;  },

  // Additional 'private' api methods  ...};

var NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMCryptAPI]);

And, the contents of the manifest file:

component {3d92fb7f-be77-475c-992a-5235615f9189} DOMCrypt.jscontract @mozilla.org/domcrypt-api;1 {3d92fb7f-be77-475c-992a-5235615f9189}category JavaScript-global-property mozCipher @mozilla.org/domcrypt-api;1

“window.mozCipher” is the window property being added to each window

This does not currently work for content windows on Fennec/Firefox mobile, but works like a charm on Firefox 4.

Let me know if you have any questions as I have used this interface extensively.

Here is an mxr link to the console, which was written this way:

http://mxr.mozilla.org/mozilla-central/source/dom/base/ConsoleAPI.js?force=1

and the manifest: http://mxr.mozilla.org/mozilla-central/source/dom/base/ConsoleAPI.manifest?force=1