Comparar revisiones

Cómo crear un componente XPCOM en JavaScript

Change Revisions

Revisión 270392:

Revisión 270392 de ibnkhaldun el

Revisión 219966:

Revisión 219966 de ibnkhaldun el

Título:
Cómo crear un componente XPCOM en JavaScript
Cómo crear un componente XPCOM en JavaScript
Enlace amigable (slug):
Cómo_crear_un_componente_XPCOM_en_JavaScript
Cómo_crear_un_componente_XPCOM_en_JavaScript
Etiquetas:
XPCOM, Todas_las_Categorías, extensiones, Complementos
Contenido:

Revisión 270392
Revisión 219966
t7    <p>t
8      &nbsp;
9    </p>
10    <h2 id="Introducci.C3.B3n" name="Introducci.C3.B3n">
11      Introducción
12    </h2>
13    <p>
14      Éste es un tutorial del tipo "Hola Mundo" para crear un com
>ponente XPCOM en JavaScript. No se describe cómo funciona XPCOM n 
>i se explica lo que hace cada línea de código. Todo ello se detal 
>la en <a href="/es/XPCOM" title="es/XPCOM">otras páginas</a>. 
15    </p>
16    <p>
17      En este tutorial mostraremos qué es lo que debes hacer para
> conseguir un componente funcional en pocos pasos y de forma senc 
>illa. 
18    </p>
19    <p>
20      <strong>Advertencia</strong>: lo expuesto aquí ha sido desa
>rrollado en un Mac. El comportamiento puede variar en otros siste 
>mas operativos. 
21    </p>
22    <h2 id="Implementaci.C3.B3n" name="Implementaci.C3.B3n">
23      Implementación
24    </h2>
25    <p>
26      Éste es un componente de ejemplo, con un único método que d
>evuelve la cadena "Hola MozDev!". 
27    </p>
28    <h3 id="Definir_la_interfaz" name="Definir_la_interfaz">
29      Definir la interfaz
30    </h3>
31    <p>
32      Si quieres usar tu componente desde JavaScript, o en otros 
>componentes XPCOM, debes definir las interfaces que quieres mostr 
>ar (si quieres usar tu componente <em>sólo</em> desde Javascript, 
> puedes usar el truco <code>wrappedJSObject</code> para que no ne 
>cesites definir interfaces como se explica aquí. Mira un ejemplo  
><a class="external" href="http://kb.mozillazine.org/Dev_:_Extendi 
>ng_the_Chrome_Protocol">aquí (en)</a>). 
33    </p>
34    <p>
35      Hay muchas interfaces ya definidas en las aplicaciones Mozi
>lla, así que tal vez no necesites definir una nueva. Puedes mirar 
> las interfaces XPCOM existentes de varias formas, en el código f 
>uente Mozilla, o usando <a class="external" href="http://xpcomvie 
>wer.mozdev.org/">XPCOMViewer</a>, un GUI para ver los componentes 
> e interfaces registradas. Puedes descargar una versión que traba 
>je con Firefox 2 desde <a class="external" href="http://downloads 
>.mozdev.org/xpcomviewer/">MozDev</a>. 
36    </p>
37    <p>
38      Si existe una interfaz que cumpla tus necesidades, no neces
>itas escribir un IDL, o compilar un typelib, y puedes saltar a la 
> <a href="#Creating_the_Component">siguiente sección</a>. 
39    </p>
40    <p>
41      Si no encuentras una interfaz pre-existente que te satisfag
>a, debes definirla. XPCOM usa un dialecto de IDL para definir int 
>erfaces, llamado <a href="/es/XPIDL" title="es/XPIDL">XPIDL</a>.  
>A continuación tienes la definición XPIDL para nuestro componente 
> HolaMozDev: 
42    </p>
43    <p>
44      HolaMozDev.idl
45    </p>
46    <pre>
47#include "nsISupports.idl"
48 
49[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx)]
50interface nsIHolaMozDev : nsISupports
51{
52  string hola();
53};  
54</pre>
55    <p>
56      Ten en cuenta que tienes que generar un UUID para cada comp
>onente XPCOM que crees. Mira <a href="/es/Generating_GUIDs" title 
>="es/Generating_GUIDs">Generating GUIDs</a> para más información. 
57    </p>
58    <div class="note">
59      Los UUID no pueden ser escritos puesto que se debe garantiz
>ar su unicidad. <strong>Deben ser generados</strong> empleando un 
> algoritmo que la garantice. 
60    </div>
61    <h3 id="Compilar_la_biblioteca_de_tipos" name="Compilar_la_bi
>blioteca_de_tipos"> 
62      Compilar la biblioteca de tipos
63    </h3>
64    <p>
65      La definición de tu interfaz debe compilarse a forma binari
>a (XPT) para poder ser registrada y usada dentro de las aplicacio 
>nes Mozilla. La compilación puede hacerse usando el SDK de Gecko. 
> Puedes averiguar cómo obtener versiones Mac, Linux, y Windows de 
>l SDK de Gecko leyendo el artículo <a href="/es/Gecko_SDK" title= 
>"es/Gecko_SDK">Gecko SDK</a>. 
66    </p>
67    <div class="note">
68      <strong>Nota:</strong> 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. 
69    </div>
70    <p>
71      Ejecuta esta orden para compilar la biblioteca de tipos. Aq
>uí, <code>{sdk_dir}</code> es el directorio del SDK de Gecko desc 
>omprimido. 
72    </p>
73    <pre class="eval">
74{sdk_dir}/bin/xpidl -m typelib -w -v -I {sdk_dir}/idl -e HolaMozD
>ev.xpt HolaMozDev.idl 
75</pre>
76    <p>
77      (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. 
78    </p>
79    <h3 id="Crear_el_componente" name="Crear_el_componente">
80      Crear el componente
81    </h3>
82    <p>
83      HolaMozDev.js
84    </p>
85    <pre>
86/***********************************************************
87constantes
88***********************************************************/
89 
90// referencia a la interfaz definida en nsIHolaMozDev.idl
91const nsIHolaMozDev = Components.interfaces.nsIHolaMozDev;
92 
93// referencia requerida a la interfaz base que todos los componen
>tes deben implementar 
94const nsISupports = Components.interfaces.nsISupports;
95 
96// UUID único identificando nuestro componente
97// puedes obtener el tuyo desde : http://kruithof.xs4all.nl/uuid/
>uuidgen 
98const CLASS_ID = Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
>xxx}"); 
99 
100// descripción
101const CLASS_NAME = "Un Componente XPCOM de muestra";
102 
103// identificador único textual
104const CONTRACT_ID = "@ejemplo.evelio.net/holamozdev;1";
105 
106/***********************************************************
107definición de la clase
108***********************************************************/
109 
110// el constructor de clase
111function HolaMozDev() {
112};
113 
114// definición de la clase
115HolaMozDev.prototype = {
116 
117  // define la función que declaramos en la interfaz
118  hola: function() {
119      return "Hola MozDev!";
120  },
121  //Desde nsISupports
122  QueryInterface: function(aIID)
123  {
124    if (!aIID.equals(nsIHolaMozDev) &amp;&amp;    
125        !aIID.equals(nsISupports))
126      throw Components.results.NS_ERROR_NO_INTERFACE;
127    return this;
128  }
129};
130 
131/***********************************************************
132la factoría de la clase
133 
134Este objeto es miembro del objeto global Components.classes.
135Se deriva del ID de contrato, p.e.:
136 
137miHolaMozDev = Components.classes["@ejemplo.evelio.net/holamozdev
>;1"]. 
138                          createInstance(Components.interfaces.ns
>IHolaMozDev); 
139 
140***********************************************************/
141var FabricaHolaMozDev = {
142  createInstance: function (aOuter, aIID)
143  {
144    if (aOuter != null)
145      throw Components.results.NS_ERROR_NO_AGGREGATION;
146    return (new HolaMozDev()).QueryInterface(aIID);
147  }
148};
149 
150/***********************************************************
151definición del módulo (registro xpcom)
152***********************************************************/
153var HolaMozDevModulo = {
154  _firstTime: true,
155  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
156  {
157    aCompMgr = aCompMgr.
158        QueryInterface(Components.interfaces.nsIComponentRegistra
>r); 
159    aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, 
160        CONTRACT_ID, aFileSpec, aLocation, aType);
161  },
162 
163  unregisterSelf: function(aCompMgr, aLocation, aType)
164  {
165    aCompMgr = aCompMgr.
166        QueryInterface(Components.interfaces.nsIComponentRegistra
>r); 
167    aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);     
>    
168  },
169  
170  getClassObject: function(aCompMgr, aCID, aIID)
171  {
172    if (!aIID.equals(Components.interfaces.nsIFactory))
173      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
174 
175    if (aCID.equals(CLASS_ID))
176      return FabricaHolaMozDev;
177 
178    throw Components.results.NS_ERROR_NO_INTERFACE;
179  },
180 
181  canUnload: function(aCompMgr) { return true; }
182};
183 
184/***********************************************************
185Inicialización del módulo
186 
187Cuando la aplicación registra el componente, se llama a esta func
>ión. 
188 
189***********************************************************/
190function NSGetModule(aCompMgr, aFileSpec) { return HolaMozDevModu
>lo; } 
191 
192</pre>
193    <h2 id="Instalaci.C3.B3n" name="Instalaci.C3.B3n">
194      Instalación
195    </h2>
196    <h3 id="Para_extensiones:" name="Para_extensiones:">
197      Para extensiones:
198    </h3>
199    <ol>
200      <li>Copia HolaMozDev.js y HolaMozDev.xpt al directorio {ext
>ensiondir}/components/. 
201      </li>
202      <li>Elimina compreg.dat y xpti.dat del directorio de tu per
>fil de usuario. 
203      </li>
204      <li>Reinicia la aplicación.
205      </li>
206    </ol>
207    <h3 id="Para_Firefox:" name="Para_Firefox:">
208      Para Firefox:
209    </h3>
210    <ol>
211      <li>Copia HolaMozDev.js y HolaMozDev.xpt al directorio {obj
>dir}/dist/bin/components, si está corriendo desde el código fuent 
>e. 
212      </li>
213      <li>Elimina compreg.dat y xpti.dat del directorio component
>s. 
214      </li>
215      <li>Elimina compreg.dat y xpti.dat del directorio de tu per
>fil de usuario. 
216      </li>
217      <li>Reinicia la aplicación.
218      </li>
219    </ol>
220    <h2 id="Usar_tu_componente" name="Usar_tu_componente">
221      Usar tu componente
222    </h2>
223    <pre>
224try {
225        // Esto es necesario para permitir el uso generalizado de
> componentes en JavaScript 
226        netscape.security.PrivilegeManager.enablePrivilege("Unive
>rsalXPConnect"); 
227 
228        var miComponente = Components.classes['@ejemplo.evelio.ne
>t/holamozdev;1'] 
229                                    .createInstance(Components.in
>terfaces.nsIHolaMozDev); 
230 
231        alert(miComponente.hola());
232} catch (unError) {
233        alert("ERROR: " + unError);
234}
235</pre>
236    <h2 id="Otros_recursos" name="Otros_recursos">
237      Otros recursos
238    </h2>
239    <ul>
240      <li>Dos temas en los foros de mozillazine sobre la implemen
>tación de componentes XPCOM en JS con algunas explicaciones, códi 
>go de ejemplo, y trucos para resolver problemillas (en inglés): 
241        <ul>
242          <li>
243            <a class=" external" href="http://forums.mozillazine.
>org/viewtopic.php?t=308369" rel="freelink">http://forums.mozillaz 
>ine.org/viewtopic.php?t=308369</a> 
244          </li>
245          <li>
246            <a class=" external" href="http://forums.mozillazine.
>org/viewtopic.php?t=367298" rel="freelink">http://forums.mozillaz 
>ine.org/viewtopic.php?t=367298</a> 
247          </li>
248        </ul>
249      </li>
250      <li>
251        <a class="external" href="http://kb.mozillazine.org/Imple
>menting_XPCOM_components_in_JavaScript">Implementing XPCOM compon 
>ents in JavaScript</a> en kb.mozillazine.org 
252      </li>
253      <li>
254        <a class="external" href="http://www.mozilla.org/scriptab
>le/avoiding-leaks.html">Using XPCOM in JavaScript without leaking 
></a> - De lectura obligatoria. 
255      </li>
256      <li>
257        <a class="external" href="http://lxr.mozilla.org/seamonke
>y/source/xpcom/sample/nsSample.js">Un componente de ejemplo</a> 
258      </li>
259      <li>
260        <a class="external" href="http://www.mozilla.org/scriptab
>le/js-components-status.html">Older JS+XPCOM notes</a> - incluye  
>información acerca de wrappedJSObject. 
261      </li>
262    </ul>

Volver al historial