Casi todos usamos desde hace tiempo extensiones/add-ons/complementos en los navegadores web, que nos ayudan en el día a día, ya sean para asuntos de productividad, ocio, personalización, etc., extendiendo o ampliando las funciones y capacidades del navegador.

Desde el inicio de los navegadores que hoy en día conocemos, cada uno ha ido admitiendo sus propias extensiones, siendo el pionero Internet Explorer 5 allá por el año 99.

Al principio, las extensiones eran creadas usando los lenguajes propios de cada uno, para usar sus propias APIs, como NPAPI, PPAPI… algo que está tendiendo a desaparecer. De hecho, Chrome ya ha dado el primer paso, empezando a utilizar tecnologías abiertas como HTML, Javascript y CSS.

Actualmente hay un borrador que intenta estandarizar todo este proceso de cambio y lo cierto es que los navegadores se están actualizando rápidamente, por lo que ya se podría decir que es posible crear extensiones multi-navegador en la mayoría de los navegadores más utilizados.

En este post vamos a ver cómo crear una sencilla extensión, aprovechando la API WebExtension, la cual está soportada por Google Chrome/Chromium y Opera y sigue el estándar del borrador Browser Extensions del W3C.

Esta API, a día de hoy, está también soportada por Mozilla Firefox y Microsoft Edge, con ciertas diferencias, sobre todo cuando se usan funciones que atacan a APIs propias de cada navegador.

En este caso, vamos a explicar cómo crear una extensión compatible con Chrome/Chromium y Firefox.

Una extensión, básicamente, se compone de elementos HTML, JavaScript y CSS, y un archivo de manifiesto.

El árbol de carpetas/archivos puede variar en función de lo que necesites que haga la extensión, ya que podría ser una extensión que muestre una simple página estática, que muestre información externa, que interactúe con las páginas que tengas abiertas, entre otras muchas posibilidades.

Mi recomendación es ordenar los mismos en carpetas por tipología. También es posible declarar el js/css en el mismo html, pero igualmente, es mejor tenerlo todo ordenado.

Si necesitas librerías/frameworks de terceros, las puedes agregar igualmente al repositorio de la extensión o enlazarlos en el html, por si prefieres apuntar a una CDN.

Hay que tener en cuenta que todo lo que enlaces o declares en el html, va a servir únicamente para su ejecución dentro de la popup de la propia extensión.

Si queremos inyectar css/js dentro de la página en la que nos encontremos, hay que separar dicho contenido en archivos llamarlos mediante el API tabs.executeScript(), que comento más adelante.

A continuación vemos un ejemplo básico de lo que serían el árbol de archivos y carpetas del repositorio de una sencilla extensión.

Manifiesto

El archivo de manifiesto manifest.json, obligatorio, es necesario ubicarlo en la raíz. Aquí es donde se declaran propiedades como el nombre de la extensión, su versión, las rutas de los iconos, los permisos a los que debe acceder, etc.

Aunque hay cierta estandarización en cuanto a las propiedades, cada navegador puede tener las suyas propias, o incluso, que alguna de ellas sea obligatoria, como ocurre en el caso de Microsoft Edge, el cual necesita que esté declarada la propiedad “author” para poder ejecutarla.

En la propiedad “content_scripts” se indican los archivos que se ejecutarán dentro del contexto de la pestaña activa, y puede acceder a las APIS propias de cada navegador. Aquí indicaremos el contenido a inyectar en la pestaña activa que tengamos abierta, por ejemplo, el CSS que tenemos definido en la ruta de la propiedad “css” o los js.

En este caso, el js lo estamos inyectando por código, como veremos más adelante. Es interesante conocer todo lo que rodea a esta propiedad, para eso te recomiendo revisar la documentación que puedes encontrar en este apartado.

Destacamos la propiedad “default_popup”, que es la que va a indicar el html a mostrar al clicar el icono de la extensión (se le podría llamar la home).

La propiedad “permissions” es donde podemos indicar qué tipo de acceso tendrá la extensión sobre tu navegador, la cual te será informada a la hora de instalarla en el navegador.

Sobre esto también puedes encontrar mucha documentación al respecto, pero básicamente hemos indicado, en el ejemplo de más abajo, que queremos permisos para todo tipo de urls externas y para archivos locales.

Para este último, dependiendo del navegador, debemos acceder a las preferencias de la extensión y permitir el acceso a archivos locales.

Finalmente, “browser_action” básicamente indica cuál es el archivo a abrir cuando ejecutemos la extensión y la ruta de su icono a mostrar.

A continuación podemos ver un ejemplo de archivo de manifiesto, usando el ejemplo que está al final del artículo. Con este contenido, ya tendríamos un archivo de manifiesto válido.


{
 "manifest_version": 2,
 "name": "Extension Name",
 "description": "Extension functionality ...",
 "version": "2.3",
 "icons": {
   "32": "images/icon_32.png",
   "128": "images/icon_128.png"
 },
 "permissions": [
   "",
   "file:///*/*"
 ],
 "browser_action": {
   "default_icon": "images/icon_32.png",
   "default_popup": "popup/popup.html"
 },
 "content_scripts": [
   {
     "matches": [ "http://*/*", "https://*/*", "file:///*/*"],
     "all_frames": true,
     "css": ["styles/tab/styles.css"]
   }
 ]
}

Si necesitas profundizar sobre este archivo, puedes echarle un ojo a la documentación de Google Chrome y a la de Firefox.

Esqueleto

En cuanto al HTML, no tiene mayor misterio. Es un html estándar, donde definiremos el contenido de la popup, las llamadas a las CSS y a los archivos Javascript que se van a ejecutar dentro de la popup. Puedes añadir cualquier librería js, webfonts, etc.

Funcionalidad

En el archivo popup.js es donde se encuentra toda la funcionalidad que queremos aplicar tanto a la popup como a la pestaña activa. Además, también podemos definir funciones que se ejecutan en la pestaña activa y nos devuelvan datos que nos llevaremos a la popup.

Para ello usaremos el API “tabs.executeScript”() para inyectar código js a la pestaña del navegador que tengamos activa y realizar ahí las funciones que queramos.

Esta API tiene actualmente diferencias respecto a cada navegador (se está trabajando en estandarizar estos pasos), pero ya hay mucho conseguido al respecto.

Es muy recomendable echarle un vistazo a la documentación para Chrome y Firefox del Api Tabs.


...
   //Current tab functions
   browser.tabs.executeScript(null, {
       //Adding extension content in DOM
       file: '/js/tab_functions.js'
   });
...

Y ahora qué, ¿cómo pruebo mi extensión?

En Chrome

¡Muy fácil! Nos vamos al apartado extensiones, o ponemos en la barra de dirección chrome://extensions/ y en el lado superior derecho activamos el modo desarrollador. A continuación pulsamos el botón de cargar descomprimida y seleccionamos la carpeta donde tengamos nuestros archivos.

En Firefox

Abrimos about:debugging y pulsamos Cargar complemento temporal. En este caso, debemos seleccionar cualquier archivo de nuestra carpeta donde tengamos los archivos.

¿Y si quiero subirlo a la Chrome Web Store/Firefox Add-ons?

Chrome Web Store

Deberás acceder con una cuenta de Google a chrome store developer dashboard. Para publicar la extensión de forma pública y aparecer en las búsquedas de la tienda, debes abonar una cuota única de 5$, que según indican, es solamente para prevenir la creación masiva de cuentas.

También puedes publicar en la tienda sin pagar cuota alguna pudiendo compartir el link, pero sin aparecer en el listado, o también publicar permitiendo el acceso solamente a todos los usuarios del dominio de una cuenta de G Suite. Aquí tienes más información sobre cómo realizar la publicación.

Firefox Add-ons

Tendrás que crearte una cuenta Firefox (si no la tienes) y acceder a su Developer Hub. En este último, existe incluso un servicio para portar extensiones de Chrome.

¿Dónde está el ejemplo? ¡Que yo lo vea!

Este post ha surgido de mi experiencia creando una extensión de navegador para facilitar las tareas de QA, debido a la sugerencia de un compañero, por lo que aprovecho la ocasión para compartir los enlaces de los mismos y su código fuente, por si alguien quisiera mejorarlo o adaptarlo a sus necesidades.

Se trata de una extensión que resalta y visualiza en pantalla los elementos html que llevan el atributo data-qa/data-test junto con su valor.

Es una extensión bastante simple, pero que facilita bastante la realización de pruebas a los compañeros de QA como a los front, que tenemos que añadir dichos atributos en cada elemento susceptible de ser añadido a las pruebas.

Enlaces de interés

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.