mozilla
Your Search Results

    XPCOMUtils.jsm

    This article is in need of a technical review.

    The XPCOMUtils.jsm JavaScript code module offers utility routines for JavaScript components loaded by the JavaScript component loader.

    To use this, you first need to import the code module into your JavaScript scope:

    Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
    

    Using XPCOMUtils

    Exposing a JavaScript class as a component using these utility methods requires four key steps:

    1. Import XPCOMUtils.jsm, as explained previously.
    2. Declare the class (or multiple classes) implementing the component(s).
    3. Create an array of component constructors.
    4. Define the NSGetFactory() or NSGetModule() entry point.

    Pseudocode

    This section provides some pseudocode that demonstrates how to put together a JavaScript class based on the steps listed above.

    Constructor

    The constructor is a simple method that handles any required initialization tasks.

    function MyComponent() {
      // initialize the component here
    } 
    

    Class declaration

    Declare the class prototype, using a form similar to this.

    MyComponent.prototype = {
      // properties required for XPCOM registration:
      classDescription: "unique text description",
      classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
      contractID:       "@example.com/xxx;1",
    
      // [optional] custom factory (an object implementing nsIFactory). If not
      // provided, the default factory is used, which returns
      // |(new MyComponent()).QueryInterface(iid)| in its createInstance().
      _xpcom_factory: { ... },
    
      // [optional] an array of categories to register this component in.
      _xpcom_categories: [{
        // Each object in the array specifies the parameters to pass to
        // nsICategoryManager.addCategoryEntry(). 'true' is passed for
        // both aPersist and aReplace params.
        category: "some-category",
        // optional, defaults to the object's classDescription
        entry: "entry name",
        // optional, defaults to the object's contractID (unless
        // 'service' is specified)
        value: "...",
        // optional, defaults to false. When set to true, and only if 'value'
        // is not specified, the concatenation of the string "service," and the
        // object's contractID is passed as aValue parameter of addCategoryEntry.
        service: true,
        // optional array of applications' IDs in the form:
        // [ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}", ... ]
        // If this is defined, the component is registered in this
        // category only on the specified applications.
        apps: [ ... ]
      }],
    
      // QueryInterface implementation, e.g. using the generateQI helper
      QueryInterface: XPCOMUtils.generateQI(
        [Components.interfaces.nsIObserver,
         Components.interfaces.nsIMyInterface,
         "nsIFoo",
         "nsIBar" ]),
    
      // [optional] classInfo implementation, e.g. using the generateCI helper.
      // Will be automatically returned from QueryInterface if that was
      // generated with the generateQI helper.
      classInfo: XPCOMUtils.generateCI(
        {classID: Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
         contractID: "@example.com/xxx;1",
         classDescription: "unique text description",
         interfaces: [Components.interfaces.nsIObserver,
                      Components.interfaces.nsIMyInterface,
                      "nsIFoo",
                      "nsIBar"],
         flags: Ci.nsIClassInfo.SINGLETON}),
    
      // ...component implementation...
    };
    

    Note: The ability to register the component in a category only on specific applications by adding the apps field to a category entry was added in Gecko 2.0.

    Notice that the QueryInterface() method implemented by the component simply calls the generateQI() method provided by the XPCOMUtils code module.

    Create an array of component constructors

    You need to create an array that lists the constructors for each component. This array can of course have just one entry:

    var components = [MyComponent];
    

    Here, we're calling the array components.

    Create the NSGetFactory() or NSGetModule() entry point

    Finally, you need to implement the NSGetModule() entry point so Gecko can start up your component:

    // "components" is the array created in the previous section
    if ("generateNSGetFactory" in XPCOMUtils)
      var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);  // Gecko 2.0+
    else
      var NSGetModule = XPCOMUtils.generateNSGetModule(components);    // Gecko 1.9.x

    Method overview

    function defineLazyGetter(aObject, aName, aLambda);
    function defineLazyModuleGetter(aObject, aName, aResource, [optional] aSymbol);
    function defineLazyServiceGetter(aObject, aName, aContract, aInterfaceName);
    nsIModule generateModule(componentsArray, postRegister, preUnregister); Obsolete since Gecko 2.0
    function generateNSGetFactory(componentsArray);
    function generateNSGetModule(componentsArray, postRegister, preUnregister); Obsolete since Gecko 2.0
    function generateCI(classInfo);
    function generateQI(interfaces);
    void importRelative(that, path, scope);
    generator IterSimpleEnumerator(enumerator, interface);
    generator IterStringEnumerator(enumerator);

    Attributes

    Attribute Type Description
    categoryManager nsICategoryManager Returns a reference to nsICategoryManager.

    Methods

    defineLazyGetter()

    Requires Gecko 1.9.2 (Firefox 3.6 / Thunderbird 3.1 / Fennec 1.0)

    Getter functions in JavaScript give you a way to define a property of an object, but not calculate the property's value until it is accessed. A getter defers the cost of calculating the value until the value is needed, and if it is never needed, you never pay the cost.

    A "lazy getter" provides an additional optimization: the value is calculated the first time the getter is called, and is then cached (or memoized), so subsequent accesses return the cached value without recalculating it.

    This means that you shouldn't use a lazy getter for a property whose value you expect to change, because the getter will not recalculate the value.

    defineLazyGetter takes three arguments:

    • the object to define the property on
    • the name of the property defined
    • the getter function itself, which returns the value and which will be called just once, the first time code tries to access the property.

    Example for this is seen at bottom of this page here.

    function defineLazyGetter(
      aObject,
      aName,
      aLambda
    ); 
    Parameters
    aObject
    The object into which to add the new lazy getter function.
    aName
    The name of the getter function to create.
    aLambda
    A function that returns the value the getter should return. This function is called exactly once.  this will reference aObject during execution of the function.

    defineLazyModuleGetter()

    Requires Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

    Defines a getter on a specified object for a module. The module will not be imported until first use.

    function defineLazyModuleGetter(
      aObject,
      aName,
      aResource,
      aSymbol
    ); 
    Parameters
    aObject
    The object to define the lazy getter on.
    aName
    The name of the getter to define on aObject for the module.
    aResource
    The URL used to obtain the module.
    aSymbol
    The name of the symbol exported by the module. This parameter is optional and defaults to aName.

    defineLazyServiceGetter()

    Requires Gecko 1.9.2 (Firefox 3.6 / Thunderbird 3.1 / Fennec 1.0)

    Defines a function on a specified object which acts as a getter for a service. The service isn't obtained until the first time it's used.

    function defineLazyServiceGetter(
      aObject,
      aName,
      aContract,
      aInterfaceName
    );
    
    Parameters
    aObject
    The object into which to add the new lazy service getter function.
    aName
    The name of the getter function to create.
    aContract
    The contract to use to obtain the service.
    aInterfaceName
    The name of the interface to query the service to.

    generateModule()

    Obsolete since Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Generates a module implementation.

    nsIModule generateModule(
      componentsArray,
      postRegister,
      preUnregister
    ); 
    
    Parameters
    componentsArray
    An array of component constructors.
    postRegister
    An optional function that is called after the module is registered. See Post-registration callback.
    preUnregister
    An optional function that's called before the module is unregistered. See Pre-unregistration callback.
    Return value

    An nsIModule that implements the module.

    generateNSGetFactory()

    Requires Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Generates the NSGetFactory() function along with the factory definition.

    Function generateNSGetFactory(
      componentsArray
    ); 
    
    Parameters
    componentsArray
    An array of component constructors.
    Return value

    A function that will return the factory for the components and can be assigned to NSGetFactory global variable.

    generateNSGetModule()

    Obsolete since Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Generates the NSGetModule() function along with the module definition. You can use this instead of generateModule() to create both the module and the NSGetModule() function at the same time.

    nsIModule generateNSGetModule(
      componentsArray,
      postRegister,
      preUnregister
    ); 
    
    Parameters
    componentsArray
    An array of component constructors.
    postRegister
    An optional function that is called after the module is registered. See Post-registration callback.
    preUnregister
    An optional function that's called before the module is unregistered. See Pre-unregistration callback.
    Return value

    An nsIModule that implements the module.

    generateCI()

    Requires Gecko 7.0 (Firefox 7.0 / Thunderbird 7.0 / SeaMonkey 2.4)

    Generates an nsIClassInfo implementation for a component. The returned object should be assigned to the classInfo property of a JS object, the QueryInterface() function generated by generateQI will return it automatically then.

    function generateCI(
      classInfo
    ); 
    
    Parameters
    classInfo
    An object containing the optional properties interfaces, contractID, classDescription, classID, flags. This parameter should not be the component itself because that would cause a memory leak.
    Return value

    An nsIClassInfo implementation returning the values of the properties from the classInfo parameter in its various properties.

    Exceptions thrown

    This method throws an exception with the message "In generateCI, don't use a component for generating classInfo" if classInfo parameter is an XPCOM component.

    generateQI()

    Generates a QueryInterface() function implementation. You need to assign the returned function to the QueryInterface property of a JavaScript object.

    When the generated method is invoked on that object, it checks to see if the specified IID is listed in the array specified by the interfaces parameter; if it is, this (that is, the object itself) is returned. Otherwise, null is returned.

    function generateQI(
      interfaces
    ); 
    
    Parameters
    interfaces
    An array of interfaces implemented by the component.
    Return value

    A QueryInterface() function implementation.

    Remarks

    When you implement an interface that inherits from another one, you should generally list all the base interfaces explicitly, except for nsISupports. For example, if your component implements nsIStreamConverter:

    MyComponent.prototype = {
      QueryInterface: XPCOMUtils.generateQI([
        Components.interfaces.nsIRequestObserver,
        Components.interfaces.nsIStreamListener,
        Components.interfaces.nsIStreamConverter,
      ]),
    
      // ...methods...
    }
    

    importRelative()

    Requires Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)

    Imports a JavaScript code module given the calling JavaScript code module's global object (you should specify this) and a path relative to that module. This lets modules bundled in a package load one another without having to hard-code full paths.

    void importRelative(
      that,
      path,
      scope
    ); 
    
    Parameters
    that
    The JavaScript Object of the calling JavaScript code module's global scope. You should simply pass this.
    path
    The relative path of the JavaScript code module to import.
    scope
    An optional object to import into; if omitted, the object passed in for the that parameter is used.
    Remarks

    This lets an extension bundle its own JavaScript code modules within itself and have them load one another. For example, if an extension named "MyExtension" bundles foo.jsm and bar.jsm, and foo.jsm needs to load bar.jsm, it can do so like this:

    Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
    XPCOMUtils.importRelative(this, "bar.jsm"); 

    In other words: importRelative will only work from other code modules (such as JSM files). It will NOT work from overlay scripts or bootstrap.js or etc. Details can be found here: bug 628669

    IterSimpleEnumerator()

    Requires Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Wraps an nsISimpleEnumerator instance into a JavaScript generator that can be easily iterated over.

    generator IterSimpleEnumerator(
      enumerator,
      interface
    ); 
    
    Parameters
    enumerator
    The nsISimpleEnumerator instance to iterate over.
    interface
    The expected interface for each element.
    Return value

    A generator yielding enumerated objects.

    Example
    const nsIFile = Components.interfaces.nsIFile;
    for (var file in XPCOMUtils.IterSimpleEnumerator(dir.directoryEntries, nsIFile))
      console.log(file.path);
    

    IterStringEnumerator()

    Requires Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Wraps an nsIStringEnumerator or nsIUTF8StringEnumerator instance into a JavaScript generator that can be easily iterated over.

    generator IterStringEnumerator(
      enumerator
    ); 
    
    Parameters
    enumerator
    The nsIStringEnumerator or nsIUTF8StringEnumerator instance to iterate over.
    Return value

    A generator yielding enumerated strings.

    Example
    for (var section in XPCOMUtils.IterStringEnumerator(iniParser.getSections()))
      console.log(section);
    

    Post-registration callback

    The post-registration callback called by generateModule() should have the following signature:

    postRegister(
      nsIComponentManager compMgr,
      nsIFile fileSpec,
      componentsArray
    );
    
    Parameters
    compMgr
    An nsIComponentManager instance to use for managing the component.
    fileSpec
    An nsIFile instance for... what?
    componentsArray
    An array of the components, as passed to generateModule().

    The function doesn't need to return a value.

    Pre-unregistration callback

    The pre-unregistration callback passed to generateModule() should have the following signature:

    preUnregister(
      nsIComponentManager compMgr,
      nsIFile fileSpec,
      componentsArray
    ); 
    
    Parameters
    compMgr
    The nsIComponentManager instance to use for managing the component.
    fileSpec
    An nsIFile instance for... what?
    componentsArray
    The array of components passed to generateModule().

    This function doesn't need to return a value.

    Examples

    defineLazyGetter

    var myServices = {};
    Cu.import('resource://gre/modules/XPCOMUtils.jsm');
    
    //set it up
    XPCOMUtils.defineLazyGetter(myServices, 'as', function () { return Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService) });
    
    //when you need to use it
    myServices.as.showAlertNotification('chrome://branding/content/icon64.png', 'this was lazyloaded', 'this is a notification from myServices.as', null, null);

    See also

    Document Tags and Contributors

    Last updated by: Noitidart,