mozilla
Los resultados de tu búsqueda

    Cómo crear un componente XPCOM en JavaScript

     

    Introducción

    Éste es un tutorial del tipo "Hola Mundo" para crear un componente XPCOM en JavaScript. No se describe cómo funciona XPCOM ni se explica lo que hace cada línea de código. Todo ello se detalla en otras páginas.

    En este tutorial mostraremos qué es lo que debes hacer para conseguir un componente funcional en pocos pasos y de forma sencilla.

    Advertencia: lo expuesto aquí ha sido desarrollado en un Mac. El comportamiento puede variar en otros sistemas operativos.

    Implementación

    Éste es un componente de ejemplo, con un único método que devuelve la cadena "Hola MozDev!".

    Definir la interfaz

    Si quieres usar tu componente desde JavaScript, o en otros componentes XPCOM, debes definir las interfaces que quieres mostrar (si quieres usar tu componente sólo desde Javascript, puedes usar el truco wrappedJSObject para que no necesites definir interfaces como se explica aquí. Mira un ejemplo aquí (en)).

    Hay muchas interfaces ya definidas en las aplicaciones Mozilla, así que tal vez no necesites definir una nueva. Puedes mirar las interfaces XPCOM existentes de varias formas, en el código fuente Mozilla, o usando XPCOMViewer, un GUI para ver los componentes e interfaces registradas. Puedes descargar una versión que trabaje con Firefox 2 desde MozDev.

    Si existe una interfaz que cumpla tus necesidades, no necesitas escribir un IDL, o compilar un typelib, y puedes saltar a la siguiente sección.

    Si no encuentras una interfaz pre-existente que te satisfaga, debes definirla. XPCOM usa un dialecto de IDL para definir interfaces, llamado XPIDL. A continuación tienes la definición XPIDL para nuestro componente HolaMozDev:

    HolaMozDev.idl

    #include "nsISupports.idl"
    
    [scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx)]
    interface nsIHolaMozDev : nsISupports
    {
      string hola();
    };  
    

    Ten en cuenta que tienes que generar un UUID para cada componente XPCOM que crees. Mira Generating GUIDs para más información.

    Los UUID no pueden ser escritos puesto que se debe garantizar su unicidad. Deben ser generados empleando un algoritmo que la garantice.

    Compilar la biblioteca de tipos

    La definición de tu interfaz debe compilarse a forma binaria (XPT) para poder ser registrada y usada dentro de las aplicaciones Mozilla. La compilación puede hacerse usando el SDK de Gecko. Puedes averiguar cómo obtener versiones Mac, Linux, y Windows del SDK de Gecko leyendo el artículo Gecko SDK.

    Nota: la versión Mac del SDK proporcionado para su descarga es sólo para PowerPC. Si necesitas una versión Intel, tendrás que compilarlo tú mismo como se describe en esa página.

    Ejecuta esta orden para compilar la biblioteca de tipos. Aquí, {sdk_dir} es el directorio del SDK de Gecko descomprimido.

    {sdk_dir}/bin/xpidl -m typelib -w -v -I {sdk_dir}/idl -e HolaMozDev.xpt HolaMozDev.idl
    

    (El modificador -I es una i mayúscula, no una L minúscula) Esta orden creará el archivo de la bilioteca de tipos HelloWorld.xpt en el directorio de trabajo actual.

    Crear el componente

    HolaMozDev.js

    /***********************************************************
    constantes
    ***********************************************************/
    
    // referencia a la interfaz definida en nsIHolaMozDev.idl
    const nsIHolaMozDev = Components.interfaces.nsIHolaMozDev;
    
    // referencia requerida a la interfaz base que todos los componentes deben implementar
    const nsISupports = Components.interfaces.nsISupports;
    
    // UUID único identificando nuestro componente
    // puedes obtener el tuyo desde : http://kruithof.xs4all.nl/uuid/uuidgen
    const CLASS_ID = Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}");
    
    // descripción
    const CLASS_NAME = "Un Componente XPCOM de muestra";
    
    // identificador único textual
    const CONTRACT_ID = "@ejemplo.evelio.net/holamozdev;1";
    
    /***********************************************************
    definición de la clase
    ***********************************************************/
    
    // el constructor de clase
    function HolaMozDev() {
    };
    
    // definición de la clase
    HolaMozDev.prototype = {
    
      // define la función que declaramos en la interfaz
      hola: function() {
          return "Hola MozDev!";
      },
      //Desde nsISupports
      QueryInterface: function(aIID)
      {
        if (!aIID.equals(nsIHolaMozDev) &&    
            !aIID.equals(nsISupports))
          throw Components.results.NS_ERROR_NO_INTERFACE;
        return this;
      }
    };
    
    /***********************************************************
    la factoría de la clase
    
    Este objeto es miembro del objeto global Components.classes.
    Se deriva del ID de contrato, p.e.:
    
    miHolaMozDev = Components.classes["@ejemplo.evelio.net/holamozdev;1"].
                              createInstance(Components.interfaces.nsIHolaMozDev);
    
    ***********************************************************/
    var FabricaHolaMozDev = {
      createInstance: function (aOuter, aIID)
      {
        if (aOuter != null)
          throw Components.results.NS_ERROR_NO_AGGREGATION;
        return (new HolaMozDev()).QueryInterface(aIID);
      }
    };
    
    /***********************************************************
    definición del módulo (registro xpcom)
    ***********************************************************/
    var HolaMozDevModulo = {
      _firstTime: true,
      registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
      {
        aCompMgr = aCompMgr.
            QueryInterface(Components.interfaces.nsIComponentRegistrar);
        aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, 
            CONTRACT_ID, aFileSpec, aLocation, aType);
      },
    
      unregisterSelf: function(aCompMgr, aLocation, aType)
      {
        aCompMgr = aCompMgr.
            QueryInterface(Components.interfaces.nsIComponentRegistrar);
        aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        
      },
      
      getClassObject: function(aCompMgr, aCID, aIID)
      {
        if (!aIID.equals(Components.interfaces.nsIFactory))
          throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
    
        if (aCID.equals(CLASS_ID))
          return FabricaHolaMozDev;
    
        throw Components.results.NS_ERROR_NO_INTERFACE;
      },
    
      canUnload: function(aCompMgr) { return true; }
    };
    
    /***********************************************************
    Inicialización del módulo
    
    Cuando la aplicación registra el componente, se llama a esta función.
    
    ***********************************************************/
    function NSGetModule(aCompMgr, aFileSpec) { return HolaMozDevModulo; }
    
    

    Instalación

    Para extensiones:

    1. Copia HolaMozDev.js y HolaMozDev.xpt al directorio {extensiondir}/components/.
    2. Elimina compreg.dat y xpti.dat del directorio de tu perfil de usuario.
    3. Reinicia la aplicación.

    Para Firefox:

    1. Copia HolaMozDev.js y HolaMozDev.xpt al directorio {objdir}/dist/bin/components, si está corriendo desde el código fuente.
    2. Elimina compreg.dat y xpti.dat del directorio components.
    3. Elimina compreg.dat y xpti.dat del directorio de tu perfil de usuario.
    4. Reinicia la aplicación.

    Usar tu componente

    try {
            // Esto es necesario para permitir el uso generalizado de componentes en JavaScript
            netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    
            var miComponente = Components.classes['@ejemplo.evelio.net/holamozdev;1']
                                        .createInstance(Components.interfaces.nsIHolaMozDev);
    
            alert(miComponente.hola());
    } catch (unError) {
            alert("ERROR: " + unError);
    }
    

    Otros recursos

    Etiquetas y colaboradores del documento

    Contributors to this page: ibnkhaldun, Fenomeno, Evelio, Neoser, Jorolo, teoli, RickieesES
    Última actualización por: teoli,