Attention : Le contenu de ces pages n'a pas été mis à jour depuis longtemps. Il est probablement obsolète pour Firefox 4.0/Gecko 4.0 et supérieur. Pour du contenu plus récent, allez consulter developer.mozilla.org.

Xpcom startup

Il peut être utile d'executer du code lors du démarrage de Firefox ou de l'application XulRunner, avant même que la fenêtre principale apparaisse. Par exemple, pour initialiser un composant de type service pour qu'il soit prêt lors de l'execution des scripts js du chrome, ou encore déclarer des observers.

Pour cela, il faut créer le composant XPCOM en l'enregistrant dans le Category Manager lors de l'enregistrement du composant dans XPCOM (via le module donc). La catégorie concernée est soit xpcom-startup, soit app-startup. xpcom-startup est la catégorie qui contient les composants qui seront instancié juste après la déclaration de tout les XPCOM (si je ne me trompe pas). app-startup est la catégorie qui contient les composants qui seront instanciés juste avant la création de la fenêtre principale. En général, on s'enregistrera dans la catégorie app-startup. Dans ces 2 catégories, il y a donc la liste des contract id des composants à instancier.

Voici l'exemple d'un composant JS qui se déclare dans app-startup. La partie interressante du code se trouve dans la méthode registerSelf, avec l'éxecution de addCategoryEntry. Le reste est du code classique de base pour un composant XPCOM en javascript

 const myCID = Components.ID("{11111111-2222-3333-4444-5555555555}"); // à remplacer par votre propre UUID !!
 const myContractID = "@my.company.com/my-component;1";  // à remplacer par votre propre ContractID !!
 var myComponent = {
   observe: function(aSubject, aTopic, aData) {
        if (aTopic == "app-startup") {
            var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                            .getService(Components.interfaces.nsIObserverService);
            observerService.addObserver(this, "final-ui-startup", false);
            // other registration
        }
        else if (aTopic == "final-ui-startup") {
            //...
        }
    },
    QueryInterface: function(aIID) {
        if (aIID.equals(Components.interfaces.nsIObserver) ||
            aIID.equals(Components.interfaces.nsISupports))
            return this;
        throw Components.results.NS_ERROR_NO_INTERFACE;
    }
 }
 var myFactory = {
    createInstance: function (outer, iid) {
        if (outer != null)
            throw Components.results.NS_ERROR_NO_AGGREGATION;
        return myComponent.QueryInterface(iid);
    }
 }
 var myModule = {
     registerSelf: function (compMgr, fileSpec, location, type) {
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
         compMgr.registerFactoryLocation(myCID,
                                         "my component",
                                         myContractID,
                                         fileSpec,
                                         location,
                                         type);
         var catman = Components.classes["@mozilla.org/categorymanager;1"]
             .getService(Components.interfaces.nsICategoryManager);
         catman.addCategoryEntry("app-startup", "mycomponent", myContractID, true, true);
     },
     getClassObject: function (compMgr, cid, iid) {
         if (!cid.equals(myContractID))
             throw Components.results.NS_ERROR_NO_INTERFACE;
        if (!iid.equals(Components.interfaces.nsIFactory))
            throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         return myFactory;
     },
     canUnload: function(compMgr) {
        return true;
     }
 };
 function NSGetModule(compMgr, fileSpec) {
     return myFactory;
 }

Rien qu'en faisant le addCategoryEntry dans la catégorie app-startup, la factory sera appelée au moment du app-startup, et donc votre composant myComponent sera instancié, et si il implemente l'interface nsIObserver, la méthode observe avec le topic "app-startup" sera appellée. C'est alors le moment de réaliser les traitements que vous voulez, comme par exemple déclarer des observers.

À addCategoryEntry, vous voyez qu'il faut donner le contract id du composant. Ainsi gecko sait quel composant il faut instancié. Mais en principe, ce composant sera détruit une fois l'appel à la méthode observe effectué. Si votre composant est un service, et donc qui restera en vie durant tout la vie de l'application, il faut indiquer plutôt

   "service,"+myContractID

Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.