This post describes how to create a JavaScript XPCOM component on bootstrapped (restartless) addon.

On bootstrapped extension

  1. Define the component name such as @mozilla.org/foo/bar;1;
  2. Generate GUID for the component.
    • If you have Visual Studio, you may use guidgen.
    • On linux, you may use uuidgen(1).

      % uuidgen
      22e1de77-790a-4a78-9ed4-8a8fca8c9f0f
      % 
      
  3. Create the component code (in the bootstrap.js).

    const Cc = Components.classes;
    const Ci = Components.interfaces;
    const Cu = Components.utils;
    const Cr = Components.results;
        
    Cu.import("resource://gre/modules/XPCOMUtils.jsm");
        
    function ComponentFooBar() { }
    ComponentFooBar.prototype = {
      classDescription: "foobar class",
      contractID: "@mozilla.org/foo/bar;1",
      classID: Components.ID("{22e1de77-790a-4a78-9ed4-8a8fca8c9f0f}"),
      QueryInterface: XPCOMUtils.generateQI([]),
    
      // members to implement...
    };
    //
    const ComponentFooBarFactory = Object.freeze({
      createInstance: function(aOuter, aIID) {
        if (aOuter) { throw Cr.NS_ERROR_NO_AGGREGATION; }
        return new ComponentFooBar();
      },
      loadFactory: function (aLock) { /* unused */ },
      QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
    });
    
    • You may specify base interface to ComponentFooBar.prototype.QueryInterface and implement methods.
  4. To regist the component on startup, add the following codes to the startup() in bootstrap.js:

    function startup(params, aReason) {
      const registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
      registrar.registerFactory(ComponentFooBar.prototype.classID,
                                ComponentFooBar.prototype.classDescription,
                                ComponentFooBar.prototype.contractID,
                                ComponentFooBarFactory);
    }
    
  5. To release the component on shutdown, add the following codes to the shutdown() in bootstrap.js:

    function shutdown(params, aReason) {
      const registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
      registrar.unregisterFactory(ComponentFooBar.prototype.classID,
                                  ComponentFooBarFactory);
    }
    
    • Note: bootstrapped add-ons must take care to clean up any component registrations at shutdown. So you must not miss this clean-up code.

NOTE: On non-bootstrap extension

If not bootstrapped add-on, you can use chrome.manifest and do same thing without using nsIComponentRegistrar.

  1. Add following lines to chrome.manifest:

    component {22e1de77-790a-4a78-9ed4-8a8fca8c9f0f} components/FooBar.js
    contract @mozilla.org/foo/var;1 {22e1de77-790a-4a78-9ed4-8a8fca8c9f0f}
    
  2. Create the component code in components/FooBar.js

    const Cc = Components.classes;
    const Ci = Components.interfaces;
    const Cu = Components.utils;
    const Cr = Components.results;
        
    Cu.import("resource://gre/modules/XPCOMUtils.jsm");
        
    function ComponentFooBar() { }
    ComponentFooBar.prototype = {
      classDescription: "foobar class",
      contractID: "@mozilla.org/foo/bar;1",
      classID: Components.ID("{22e1de77-790a-4a78-9ed4-8a8fca8c9f0f}"),
      QueryInterface: XPCOMUtils.generateQI([]),
    
      // members to implement...
    };
    this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ComponentFooBar]);
    

Reference