Tutorial

Si ya ha visto el artículo tu primer WebExtension, ya posee una idea de como escribir una Web Extension. En este artículo se escribirá un complemento ligeramente más complejo para demostrar un par de cosas más de las APIs.

El complemento añade un nuevo botón a la barra de herramientas de Firefox. Cuando el usuario da clic sobre el botón, mostraremos una ventana emergente que permite escoger un animal. Una vez que un animal sea escogido, reemplazaremos todas las imágenes en la página actual con la imagen del animal seleccionado.

Para implementar esto, haremos lo siguiente:

  • Definir una acción del navegador, que será el botón añadido a la barra de herramientas de Firefox.
    Para el botón vamos a proporcionar:
    • un icono, llamado "beasts-32.png"
    • una ventana emergente para abrir cuando el botón sea presionado. La  ventana emergente incluye HTML, CSS y JavaScript.
  • Define un ícono para el complemento, llamado "beasts-48.png". Este será mostrado en el Administrador del Complemento.
  • Escribe un script de contenido, "beastify.js" que será inyectado dentro de las páginas web.
    Este es el código que modificará las páginas web.
  • Empaqueta algunas imágenes de animales, para reemplazar las imágnes de la página web.
    Nosotros haremos las imágenes "recursos web accesibles" para que la página web pueda referenciarlos.

Tu puedes notar que la estructura general de la extensión luce como esto:

Esta es un complemento simple, pero muestra muchos de los principales conceptos de la API WebExtensions:

  • Adicionando un botón a la barra de herramientas
  • Definiendo un panel emergente usando HTML, CSS y JavaScript
  • Inyectando scripts de contenido dentro de las páginas web
  • Comunicándonos entre los scripts de contenido y el resto de los complementos
  • Empaquetando recursos con tu extensión que pueden ser usados por las páginas web

Tu puedes encontrar el código fuente completo de la extensión en GitHub.

Para escribir este complemento, necesitará de Firefox 45 o más reciente.

Escribiendo la WebExtension

Crea una carpeta nueva y navega hacia ella:

mkdir beastify
cd beastify

manifest.json

Ahora crea un archivo llamado "manifest.json", y agrega el siguiente contenido:

{

  "manifest_version": 2,
  "name": "Beastify",
  "version": "1.0",

  "description": "Agrega un icono de acción navegación a la barra de herramientas. Haga clic en el botón para elegir una bestia. El contenido del cuerpo de la pestaña activa se sustituye por una imagen de la bestia elegida. Consulte https://developer.mozilla.org/es/Add-ons/WebExtensions/Examples#beastify",
  "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
  "icons": {
    "48": "icons/beasts-48.png"
  },

  "permissions": [
    "activeTab"
  ],

  "browser_action": {
    "default_icon": "icons/beasts-32.png",
    "default_title": "Bestificar",
    "default_popup": "popup/choose_beast.html"
  },

  "web_accessible_resources": [
    "beasts/frog.jpg",
    "beasts/turtle.jpg",
    "beasts/snake.jpg"
  ]

}
  • Las tres primeras llaves: manifest_version, name, y version, son obligatorias y contienen los metadatos básicos para la extensión.
  • description y homepage_url son opcionales, pero recomendadas: proporcionan información útil acerca del complemento.
  • icons es opcional, pero recomedada: permite la especificación de un ícono para el complemento, que será mostrada en el Administrador de Complementos.
  • permissions lista los permisos que la extensión necesita. Aquí solo se pide el permiso de activeTab.
  • browser_action especifica el botón de la barra de herramientas.  Nosotros proveemos tres piezas de información aquí:
    • default_icon es obligatorio y enlaza al icono para el botón
    • default_title es opcional y será mostrado como descripción
    • default_popup es usado su tu quieres una ventana emergente que será mostrada cuando el usuario de clic en el botón. Lo hacemos y hemos incluido esta llave que apunta a un archivo HTML de la extensión.
  • web_accessible_resources lista los archivos que queremos hacer accesibles a las páginas web. Como el complemento reemplaza imágenes en una página con imágenes que hemos empaquetado, necesitamos hacer estas imágenes accesibles a la página.

Nota que todas las rutas dadas son relativas a manifest.json.

El ícon

El complemento debería tener un íncono. Éste, será mostrado junto a la lista de complementos en el Administrador de Complementos (Pude abrirlo introduciendo en la URL "about:addons"). El manifest.json promete que se posee un ícono para la barra de herramientas en "icons/beasts-48.png".

Cree el directorio "icons" y guarde un ícono ahí y nómbrelo como "beasts-48.png".  Puede utilizar uno de nuestro ejemplo, el cual ha sido tomado del  conjuto de íconos Aha-Soft’s Free Retina, que es utilizado bajo el término de su propia licencia.

Si elige proporcionar su propio ícono, debería ser de 48x48 pixeles. También puede proporcionar un ícono de 96x96 pixeles, para pantallas de altas resoluciones y, si usted hace esto, deberá especificarlo como la propiedad 96 del objeto icons en el manifest.json:

"icons": {
  "48": "icons/beasts-48.png",
  "96": "icons/beasts-96.png"
}

El botón de la barra de herramientas

El botón de la barra de herramientas necesita un icono, y nuestro manifest.json promete eso y nos gustaría tener un icono para la barra de herramientas en "icons/beasts-32.png".

Guarde un ícono llamado "beasts-32.png" en el directorio "icons". Tu podrías usar uno de nuestros ejemplos, los cuales son tomados desde el sitio IconBeast y empleados bajo sus términos de licencia.

Si tu no provees una ventana emergente, entonces el evento clic es disparado hacia tu complemento cuando el usuario de clic sobre el botón. Si provees una ventana emergente entonces el evento clic no se disparará, pero en cambio, se muestra la ventana emergente. Nosotros queremos una ventana emergente, así que vamos a crearla.

La ventana emergente

La función de la ventana emergente es habilitada si el usuario escoge una de los tres animales.

Crea una nueva carpeta llamada "popup" bajo la carpeta raíz del complemento . Esta será donde pondremos el código para la ventana emergente. La carpeta "popup" contendrá estos tres archivos:

  • choose_beast.html define el contenido del panel
  • choose_beast.css los estilos CSS para el contenido
  • choose_beast.js maneja las opciones del usuario ejecutando un script de contenido en la pestaña activa

choose_beast.html

El archivo HTML luce como esto:

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="choose_beast.css"/>
  </head>

  <body>
    <div class="beast">Sapo</div>
    <div class="beast">Tortuga</div>
    <div class="beast">Serpiente</div>
    <div class="clear">Reiniciar</div>

    <script src="choose_beast.js"></script>
  </body>

</html>

Nosotros solo tenemos un elemento para cada elección de animal. Nota que hemos incluido CSS y JS desde este archivo, justo como una página web.

choose_beast.css

El CSS ajusta el tamaño de la ventana emergente, se asegura que las tres posibles opciones llenen el espacio y les da un poco de estilo básico:

html, body {
  width: 100px;
}

.button {
  margin: 3% auto;
  padding: 4px;
  text-align: center;
  font-size: 1.5em;
  cursor: pointer;
}

.beast:hover {
  background-color: #CFF2F2;
}

.beast {
 background-color: #E5F2F2;
}

.clear {
 background-color: #FBFBC9;
}

.clear:hover {
 background-color: #EAEAC9;
}

choose_beast.js

En el JavaScript para la ventana emergente, nosotros escuchamos los eventos clic. Si el clic es sobre alguno de los tres animales, inyectamos un script de contenido dentro de pestaña activa. Una vez que el script de contenido es cargado, enviamos a él un mensaje con el animal elegido:

/*
Given the name of a beast, get the URL to the corresponding image.
*/
function beastNameToURL(beastName) {
  switch (beastName) {
    case "Frog":
      return browser.extension.getURL("beasts/frog.jpg");
    case "Snake":
      return browser.extension.getURL("beasts/snake.jpg");
    case "Turtle":
      return browser.extension.getURL("beasts/turtle.jpg");
  }
}

/*
Listen for clicks in the popup.

If the click is on one of the beasts:
  Inject the "beastify.js" content script in the active tab.

  Then get the active tab and send "beastify.js" a message
  containing the URL to the chosen beast's image.

If it's on a button which contains class "clear":
  Reload the page.
  Close the popup. This is needed, as the content script malfunctions after page reloads.
*/

document.addEventListener("click", (e) => {
  if (e.target.classList.contains("beast")) {
    var chosenBeast = e.target.textContent;
    var chosenBeastURL = beastNameToURL(chosenBeast);

    browser.tabs.executeScript(null, { 
      file: "/content_scripts/beastify.js" 
    });

    var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
    gettingActiveTab.then((tabs) => {
      browser.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
    });
  }
  else if (e.target.classList.contains("clear")) {
    browser.tabs.reload();
    window.close();
  }
});

Este usa tres funciones de la API WebExtension API:

  • browser.tabs.executeScript para inyectar un script de contenido alojado en  "content_scripts/beastify.js" dentro de la pestaña activa
  • browser.tabs.query para obtener la pestaña activa
  • browser.tabs.sendMessage para enviar un mensaje al script de contenido ejecutado en la pestaña activa. El mensaje contiene el animal seleccionado en la propiedad beast.

El script de contenido

Crea una carpeta nueva bajo la raíz del complemento llamada "content_scripts" y crea un nuevo archivo en ella llamado "beastify.js", con el contenido siguiente:

/*
beastify():
* removes every node in the document.body,
* then inserts the chosen beast
* then removes itself as a listener
*/
function beastify(request, sender, sendResponse) {
  removeEverything();
  insertBeast(request.beastURL);
  browser.runtime.onMessage.removeListener(beastify);
}

/*
Remove every node under document.body
*/
function removeEverything() {
  while (document.body.firstChild) {
    document.body.firstChild.remove();
  }
}

/*
Given a URL to a beast image, create and style an IMG node pointing to
that image, then insert the node into the document.
*/
function insertBeast(beastURL) {
  var beastImage = document.createElement("img");
  beastImage.setAttribute("src", beastURL);
  beastImage.setAttribute("style", "width: 100vw");
  beastImage.setAttribute("style", "height: 100vh");
  document.body.appendChild(beastImage);
}

/*
Assign beastify() as a listener for messages from the extension.
*/
browser.runtime.onMessage.addListener(beastify);

El script de contenido añade un escuchador para mensajes desde el complemento (específicamente desde "choose_beast.js", arriba). En el escuchador:

  • remueve cada elemento en el document.body
  • crea un elemento <img> apuntando a la URL proporcionada, y la inserta en el DOM
  • elimina el escuchador de mensajes.

Las bestias

Finalmente, necesitamos incluir las imágenes de los animales.

Crea una carpeta nueva llamada "beasts", y adiciona tres imágenes en ella, con su nombre apropiado. Tu puedes obtener estas imágenes desde el repositorio en GitHub, o desde aquí:

Probándolo

Primero, comprueba nuevamente que tienes todos los archivos necesarios en el lugar adecuado:

beastify/

    beasts/
        frog.jpg
        snake.jpg
        turtle.jpg

    content_scripts/
        beastify.js

    icons/
        beasts-32.png
        beasts-48.png

    popup/
        choose_beast.css
        choose_beast.html
        choose_beast.js

    manifest.json

Comenzando con Firefox 45, pueden instalar temporalmente una WebExtensions desde el disco.

Abre "about:debugging" en Firefox, de clic en "Cargar complemento temporalmente", y seleccione el archivo manifest.json. Entonces, debería de ver el ícono de la extensión aparecer en la barra de herramientas de Firefox:

Abra una página web, luego haga clic sobre el ícono, seleccione una bestia, y vea cómo cambia la página web:

Desarrollo desde la línea de comandos

 

Puede automatizar el paso de instalación temporal mediante la herramienta web-ext. Pruebe esto:

cd beastify
web-ext run

 

Etiquetas y colaboradores del documento

Etiquetas: 
 Colaboradores en esta página: hecaxmmx, yuniers
 Última actualización por: hecaxmmx,