Como hacer un plugin para Firefox

15 may

Estos últimos días estuvimos desarrollando desde Comunidad Fusa un primer plugin para Firefox. El objetivo era tanto aprender como crear alguna utilidad que le sirva a los usuarios del sitio. Les contamos entonces el paso a paso.

El proyecto

El plugin que desarrollamos consiste en un contador de votos que muestre en la barra del navegador los votos disponibles para utilizar en Comunidad Fusa de un usuario. Te contamos paso a paso como lo hicimos, pero para ir empezando, te invitamos a descargar la primer versión del plugin y probarlo funcionando.

Creando el proyecto

Para empezar tenemos que registrarnos en el centro de desarrolladores de Firefox. Desde Firefox nos proponen dos maneras de realizarlo: Utilizar el Add-on Builder (entorno de desarrollo basado en la web que proporciona funcionalidad adicional para trabajar con el SDK de complemento) o directamente la SDK de complementos (conjunto de API junto con una utilidad de la línea de órdenes que te permite desarrollar complementos con tu propio conjunto de herramientas). Elijan el camino que quieran, nosotros fuimos por el Builder de Mozilla.

Antes de empezar les recomendamos pegarle una leída a la documentación del SDK, para entender a gran modo la funcionalidad que nos brinda. Una vez hecho esto,  comenzamos: click en “Create an Add-on Now” y proyecto creado.

El entorno del Add-on Builder

ScreenHunter_01 May. 15 16.01

El Add-on Builder es un IDE que nos permite desarrollar en la web misma. Nos propone 3 directorios:

  • Lib: En principio contiene el main.js, el script principal de nuestro plugin.
  • Data: En este directorio colocaremos los recursos que vamos a utilizar.
  • Libraries: Supuestamente para importar librerías. Nosotros no lo usamos.

Luego, en la parte superior tenemos una botonera. Los más importantes:

  • Test: Nos permite probar el plugin en el momento. Lo mejor del IDE sin dudas
  • Download: Para descargar tanto el código como el plugin.
  • Save: Para guardar el proyecto. Si esta en modo test, lo guarda y actualiza el plugin funcionando.
  • Error Console: Consola para ver errores, advertencias y mensajes. Fundamental para obtener data de que está pasando mientras lo desarrollamos.

Nuestro main.js


var widgets = require("sdk/widget");
var tabs = require('tabs');
var data = require("sdk/self").data;

/* Obtención del parámetro de usuario de fusa */
var {Cc, Ci} = require("chrome");
var cookieSvc = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var uri = ios.newURI("http://www.comunidadfusa.com/", null, null);
var cookie = cookieSvc.getCookieString(uri, null);
var myCookie = cookie.replace(/(?:(?:^|.*;\s*)comunidadfusaLogeado\s*\=\s*((?:[^;](?!;))*[^;]?).*)|.*/, "$1");

exports.main = function() {
var player = widgets.Widget({
id: "comunidadfusa-widget-2",
label: "Contador de Votos de Comunidad Fusa",
width: 45,
label: "Votos Disponibles",
contentURL: data.url("index.html?parametro=" + myCookie),
onClick: function() {
tabs.open("http://www.comunidadfusa.com/");
}
});
};

El main.js es el archivo principal de un plugin.  En las primeras lineas importamos las librerías: widget (para el componente que va a ir en la barra), data (para acceder a la carpeta data del proyecto nuestro) y tabs (para abrir una pestaña al hacer click en el contenido del plugin).

Para identificar al usuario del que se van a contar los votos disponibles, necesitábamos tener acceso a una cookie creada por fusa. Esto lo resolvimos de las líneas 6 a la 11. Importamos la librería de chrome, única forma que encontramos para manipular las cookies del navegador. Utilizando el cookie service y  service io  obtenemos todas las cookies creadas por fusa. En la línea 11 obtenemos el valor de la cookie que buscamos utilizando expresiones regulares. Quizás estas 5 líneas fueron las que más investigación requirieron, ya que no dábamos con la respuesta (y la documentación del sitio está desactualizada). Así que si quieren manejar cookies desde un plugin, les va a servir de sobremanera esta solución.

A partir de la línea 13 creamos el Widget (que representa al plugin en si), al cuál le decimos que el contenido es el index.html y que en el onclick tiene que abrir un tab nuevo con el sitio de Comunidad Fusa. Es todo lo que hicimos del lado del SDK, a partir de acá es todo html + css + javascript.

Nuestro index.html


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="css/style.css" type="text/css" media="all" />
<script type="text/javascript" src="js/jquery-2.0.0"></script>
<script type="text/javascript" src="js/jquery.tmpl"></script>
</head>
<body>
<img src="images/votar.png" class="imagenBarra" />
<span id="cantidadVotos"></span>

<script id="imagenVotoTemplate" type="text/x-jquery-tmpl">
<img src="images/${votos}.png" class="imagenBarra"/>
</script>

<script id="imagenOfflineTemplate" type="text/x-jquery-tmpl">
<img src='images/offline.png' class='imagenBarra'>
</script>

<script type="text/javascript" src="js/votos.js"></script>

</body>
</html>

Como pueden apreciar, es un html común y corriente. Todos los recursos a los que hacemos referencia (js, css, images) deben subirlos a la carpeta data, incluso este html. Un par de consejos para esta parte: La gente de Firefox va a revisar nuestro plugin si queremos subirlo al repositorio de plugines. Por experiencia propia, les cuento que no quieren código javascript que cree contenido html (para esto recomendamos jquery template), tampoco quieren scripts minificados. Así que cuidado con estas dos reglas si utilizan alguna librería que hace uso de esto, porque les van a rebotar el plugin.

Nuestro votos.js


$(document).ready(function() {

var timerVotos = null;

function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}

var miParametro = getUrlVars()["parametro"];

function obtenerVotos() {
$.getJSON( "http://www.comunidadfusa.com/servicio/votos/disponibles/"+miParametro, function(data) {
$('#cantidadVotos img').remove();
$template = $("#imagenVotoTemplate");
$.tmpl( $template, data).appendTo( "#cantidadVotos" );
}).fail(function(data) {
$('#cantidadVotos img').remove();
$template = $("#imagenOfflineTemplate");
$.tmpl( $template, data).appendTo( "#cantidadVotos" );

});
}

obtenerVotos();
clearInterval(timerVotos);
timerVotos = setInterval(function () {
obtenerVotos()
},15000);

});

Otra vez, es un javascript común y corriente. Muy por arriba, obtengo el parámetro que le pasamos al index.html, y con el mismo hacemos un get a un servicio que exponemos desde comunidad fusa. En caso de éxito, usamos un template, en caso de error (por ejemplo, si el usuario esta deslogeado) usamos otro template. Y cada 15 segundos se ejecuta esta invocación al servicio.

Y esto es todo!

Algunos datos extras

  • A la gente que revisa los plugins no les gusta que por ejemplo la librería “jquery-2.0.0″ le falte la extensión js. Lo loco es que el mismo builder te saca las extensiones. Entonces, antes de mandar a revisar el plugin, bájense el xpi, cámbienle la extensión a .zip, descomprimanlo, corrijan los nombres de los scripts renombrados y sus invocaciones desde el html, compriman, vuelvan a colocar la extensión xpi y asunto resuelto.
  • Si quieren que el plugin tenga un icono, tienen que poner un archivo “icon.png” en la raíz del xpi (o sea el zip).
  • En una primer instancia quisimos hacer un plugin reproductor. Estuvimos bastante tiempo y concluimos que Firefox no soporta la reproducción de mp3s de manera nativa. Lo dejaremos para el próximo plugin de chrome.
  • Se puede validar el plugin antes de enviarlo a revisión desde el validador de plugines.
  • El plugin lo tenemos en etapa de revisión, si surgen nuevas validaciones se las comentamos.

Esto es todo por el momento. Cualquier duda comenten y espero que le sirva para crear nuevos plugins para Firefox!

Y los volvemos a invitar a descargar e instalar el plugin: Contador de votos fusa

Saludos

Uva

  • juanmaflow

    Muy bueno!

    • ComunidadFusa

      gracias juanma!