There is only XUL (X)

Ahora que hemos visto un poco por encima como funciona XUL vamos a ponernos un poco mas serios y vamos a crear una pequeña extensión para nuestro navegador. Por ahora algo sencillo como añadir una nueva entrada de menú al menú de herramientas de Firefox, que nos muestre un alert con la hora del sistema cada vez que se haga click sobre él. El proceso para Mozilla sería un proceso bastante parecido. Para ello tenemos que ver que son los overlays, cuya traducción al castellano sería algo asi como superposiciones.

Lo primero vamos a recordar que toda la interfaz de Mozilla y Firefox esta hecha con XUL, por lo tanto será razonable suponer que en algún lugar tiene que haber un fichero xul que lo define. Y acertariais al hacer esta suposición. La interfaz del navegador esta definida en un archivo llamado browser.xul en el subdirectorio chrome dentro de la carpeta en la que esta instalado nuestro navegador, pero si entrais en esa carpeta para echar un vistazo al código no lo encontrareis. browser.xul esta empaquetado dentro de uno de esos archivos .jar que veis.

Un archivo jar es simplemente un archivo .zip con la extensión renombrada. Podemos descomprimirlo con winzip u otro programa de compresión de archivos. Si descomprimimos browser.jar tendremos una carpeta browser que alberga una carpeta content en la que tenemos a su vez las carpetas browser y browser-region. Dentro de la primera se encuentra además del browser.xul al que nos referíamos otros archivos .xul, archivos js con código javascript y archivos css, hojas de estilo.

Si abrimos el archivo browser.xul tendremos una ventana del navegador de Firefox pero con la peculiaridad de que no veremos las barras de herramientas, los botones u otros widgets de las extensiones que tengamos instaladas. Esto es así por que cuando abrimos una ventana del navegador estamos abriendo browser.xul, pero también otros archivos .xul que se superponen. Sería algo así como coger varios dibujos en papel cebolla y ponerlos uno encima de otro, algo así como las capas de Photoshop. Esto es lo que vamos a ver ahora, el overlay.

Lo primero que tenemos que hacer es crear una carpeta para nuestra aplicación, por ejemplo ‘hora’ completando una estructura de directorios hora/content/hora. Dentro del directorio mas profundo de esta jerarquía creamos un archivo hora.xul con el siguiente código:

<?xml version=”1.0″?>

<overlay xmlns=”http://www.mozilla.org/keymaster/gatekeeper/ there.is.only.xul” xmlns:nc=”http://home.netscape.com/NC-rdf#”>

<popup id=”menu_ToolsPopup”>

<menuitem
oncommand=”fecha=new Date(); hora=fecha.getHours(); minuto=fecha.getMinutes(); segundo=fecha.getSeconds(); alert(hora + ‘ : ‘ + minuto + ‘ : ‘ + segundo);” label=”Mostrar Hora;”/>

</popup>

</overlay>

Lo que estamos haciendo aquí es crear un documento XUL que solo contiene una entrada de menú dentro de un popup que queremos superponer sobre el navegador. La única diferencia con los ejemplos que hemos visto hasta ahora es que en lugar de definir una ventana definimos un overlay pero aparte del nombre no hay mucha diferencia. Simplemente indicamos a Mozilla que este no es un documento xul completo, si no que vamos a combinarlo con otro/s documentos xul.

Ahora veamos como funcionaría el overlay con un caso sencillo antes de pasar a mayores. Supongamos un archivo XUL que importa el overlay que acabamos de definir; para ello usaría algo parecido a este código:

<?xul-overlay href=”chrome://hora/content/hora.xul”?>

Lo que ocurriría entonces es que para cada elemento con un id definido en el archivo de overlay se buscaría el mismo elemento con el mismo id en el documento sobre el que queremos superponer. Antes de nada tendríamos que haber abierto el fichero browser.xul para ver donde se definen las entradas de menú del menú herramientas y cual es el ID de conjunto que las contiene. Ese trabajo ya esta hecho; como se puede ver en el código tenemos un elemento popup con id menu_ToolsPopup, aquí es donde está la clave.

En el caso de que no se encuentre una instancia de ese elemento con ese ID entonces este elemento no se tiene en cuenta al hacer el overlay. Si por el contrario si se encuentra, entonces el elemento y todo lo que se defina dentro de este en el overlay pasará a superponerse al documento raíz, lo cual quiere decir que el elemento del documento raíz adquirirá todos los atributos que se definan en el overlay además de todos sus subelementos.

En este ejemplo el documento raíz es el que se encargaba de añadir el overlay usando la etiqueta xul-overlay, sin embargo esto no nos es de utilidad en nuestro caso ya que no queremos tener que cambiar el código de browser.xul. La solución es hacer que sea el overlay el que diga a que documento se tiene que superponer. Esto podemos hacerlo añadiendo la información de los overlay a nuestro contents.rdf

<?xml version=”1.0″?>

<RDF:RDF xmlns:RDF=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:chrome=”http://www.mozilla.org/rdf/chrome#”>

<RDF:Seq about=”urn:mozilla:package:root”>
<RDF:li resource=”urn:mozilla:package:hora”/>
</RDF:Seq>

<RDF:Description about=”urn:mozilla:package:hora”
chrome:displayName=”Mostrar Hora 0.1″
chrome:author=”Zootropo”
chrome:authorURL=”http://mundogeek.net”
chrome:name=”hora”
chrome:extension=”true”
chrome:description=”Añade una opción al menú de herramientas para mostrar la hora actual.”>
</RDF:Description>

<RDF:Seq about=”urn:mozilla:overlays”>
<RDF:li resource=”chrome://browser/content/browser.xul”/>
</RDF:Seq>

<RDF:Seq about=”chrome://browser/content/browser.xul”>
<RDF:li>chrome://hora/content/hora.xul</RDF:li>
</RDF:Seq>

</RDF:RDF>

Vemos que tenemos un par de listas nuevas, una referida a urn:mozilla:overlays en el que los elementos de la secuencia son los documentos sobre los que se va a hacer el overlay (en este caso el browser.xul para superponer a nuestro navegador) y otra secuencia con el archivo xul sobre el que hacemos el overlay como sujeto y como entradas de la secuencia los archivos xul a superponer.

Borramos overlay.rdf como en el post anterior, añadimos una entrada nueva a installed-chrome.txt para el content de nuestra aplicación (no tendremos locale porque la única función javascript que utilizamos esta embebida en el archivo xul ni skin ya que no utilizamos ningún css) y reiniciamos nuestro navegador, tras lo cual tendremos una nueva entrada al final del menú de herramientas que nos permitirá ver la hora del sistema.

Comentarios
  1. Enrique

    Me parece que el artivulo esta muy bueno, estuve realizando paso a paso, pero no me salio, te podrias expresar o explicarme de mejor manera porque no entiendo la parte que dice:

    “< ?xml version="1.0″?>




    en esta parte no se si es que te falta la parte que dice






    ya que en tu articulo no aparece esta parte sino que solo aparece la de la hora.

    Y con respecto a otra duda que tengo es la parte que dice:

    “Borramos overlay.rdf como en el post anterior, añadimos una entrada nueva a installed-chrome.txt para el content de nuestra aplicación ”

    mi pregunta es que nueva entrada añadimos..?

    Agradeciendote de antemano un colega que esta aprendiendo ha realizar extensiones.

    QUike:OO

    Responder

  2. Si te falla es linea:

    cambia las comillas del “1.0” porque a mi me daba error ay.
    Saludos!

    Responder

  3. javi

    Algunos caracteres como las comillas o el ? hay que cambiarlos escribiendolos de nuevo, si lo que hacemos es copiar y pegar al notepad.

    Responder

  4. José

    AL prinicipio muy bueno, pero despues no aclaras como trabajar el RDF, en q carpeta; falta.

    Responder

  5. Interesante post!
    La pregunta es: ¿sera posible crear un especie de ActiveX para IE, pero para firefox capaz de manejar impresoras fiscales?
    Es decir desde una funcion o algo parecido enviar una cadena de texto (String) a la extension y ésta lo envíe a la impresora fiscal (Epson LX, FX / a puntos / o ticketeras) que generalmente esta conectado por USB o LPT1 o paralelo.
    ¿ Sera posible ?

    Responder

  6. Seria bueno, cualquier idea o con cualquier navegador que no sea IE.
    Lo necesito para una aplicación web en JSP/Struts2/Hibernate.

    🙁

    Responder

  7. Lorena

    Hola, quisiera saber la manera te poner la hora en un label, como le hago?

    Responder

Deja un comentario