Tutorial desarrollo de extensiones Chrome (1ª parte)

Tutorial desarrollo de extensiones Chrome (1ª parte)

En los últimos años las extensiones de navegador han ganado mucha popularidad, y  algunas incluso se han hecho imprescindibles en nuestro uso diario de internet. De echo a menudo nos hacen ser más fieles a un navegador por ser el que tiene las extensiones que más usamos.

Aunque todos los navegadores modernos tienen extensiones, el navegador que a mi parecer tiene más y mejores es Chrome.  De cara al desarrollo de extensiones no tengo ninguna duda que el mejor es Chrome, tiene la mejor API y el mejor sistema de permisos y de publicación en la Store. El desarrollo para Firefox puede llegar a ser bastante más complicado  y la publicación en su store es una auténtica pesadilla de varias semanas sólo comparable a la de publicar una app de iOs en Itunes.

 

Comienzo pues una serie de tutoriales para introducirse en el apasionante mundo del desarrollo de extensiones de Chrome. Quizás más adelante haga la misma extensión de ejemplo para Firefox y también alguna app de chrome que tienen bastantes similitudes con las extensiones.

Para hacer extensiones se usa la misma tecnologia que el frontend de cualquier web: HTML, CSS y javascript. Además tiene una gran ventaja que a mi personalmente me encanta: te olvidas totalmente del crossbrowsing, o sea que puedes concentrarte en programar para webkit  (además actualizado), y sobre todo ¡olvidarte del p%$& Explorer!. Olvidate de polyfills, modernizr y demás historias, aquí puedes usar todo lo que se te ocurra que te va a funcionar  (bueno o casi todo).

 

Y sobre todo, tienes la potente API de chrome que permite interactuar con el navegador para todo lo que se nos ocurra:

  • Inyectar código en las páginas que visita el usuario.
  • Obtener datos de navegación (URL, etc), marcadores, historial…
  • Abrir ventanas o pestañas.
  • Sobreescribir la ventana de historial o marcadores.
  • Administrar las otras extensiones
  • Sincronizar datos entre instalaciones
  • …. (y más en API de chrome)

 

Extensión de ejemplo para Gmail

 

Extensión de ejemplo

Contador de letras en gmail

Empezaremos haciendo una extensión sencillísima para contar las letras que escribimos en Gmail y a lo largo de siguientes entregas la iremos haciendo más interesante mostrando datos estadísticos de uso y lo que se me vaya ocurriendo con el proposito de ir introduciendo las distintas posibilidades de la programación de extensiones y sin tener en cuenta su utilidad real.

El código completo lo podeis encontrar en mi github.

La extensión añade un contador en la barra de herramientas al lado de los iconos (ver imagen adjunta).

 

Entorno de desarrollo

Para probar la extensión tenemos que ir a chrome://extensions/ y activar el Modo desarrollador. A partir de este momento veremos un botón para instalar extensiones desde un directorio de nuestro ordenador o para empaquetar la extensión. Además ahora podremos ver en las extensiones la posibilidad de inspeccionar el proceso de segundo plano de las extensiones que lo tengan. En los iconos de extensión de la barra ahora podremos inspeccionar su proceso.

 

Fichero manifest.json

Toda extensión en chrome tiene un fichero manifest en formato json para definir las características principales de la extensión tales como nombre, descripción, iconos, permisos necesarios etc.

La lista completa de campos se puede ver aquí.

Nuestro fichero será el siguiente:

El manifest_version es simplemente la versión que estamos usando que siempre debe ser la 2 (actualmente), la 1 tenía otras medidas de seguridad menos restrictivas y ya no se acepta.

Se debe especificar los iconos en icons preferiblemente en varios tamaños para la página de extensiones, la store, la barra de extensiones si es que la extensión tiene botón en ella, etc…

Lo más interesante aquí es content_scripts. Nuestra extensión va a inyectar código en la página de gmail por lo que primero especificamos en qué url’s queremos tratar con matches y a continuación los ficheros de javascript y css que queremos inyectar.

Permisos de la extensión

Debido a matches cuando el usuario instale esta extensión le pedirá permiso para acceder a sus datos en gmail con un aviso parecido al de la imagen adjunta.

Esto quiere decir que la extensión puede inyectar código en esa página que da poder para hacer muchas cosas como leer contenido de mails que la página esté mostrando o modificar contenidos.

Este tipo de permisos echa para atrás a mucha gente por lo que es importante evitar su uso si es posible y al instalar una extensión hacerlo sólo cuando se confia en ella. Aunque es difícil saber cuando confiar, han habido ejemplos de extensiones muy populares que se ha sabido que inyectaban publicidad u obtenian datos de navegación del usuario.

 

Es importante describir cómo se ejecuta el código inyectado.

El javascript se ejecuta en otro contexto diferente al de la página en la que estamos. Por tanto no podrá acceder a las variables globales o las funciones del código de la página, aunque sí por ejemplo al localStorage. En nuestro ejemplo inyectamos una versión de jquery pero da igual que la página esté ejecutando otra versión ya que no se mezclarán.

En cambio el CSS lógicamente si que afecta a toda la página y se mezcla con el CSS nativo. Por eso hay que tener cuidado al usar los selectores y ser muy específico con lo que queremos cambiar para no afectar a otros elementos de la página. Aunque suele ocurrir el problema contrario, en algunas páginas hay selectores muy genéricos que pueden afectar al contenido que queramos insertar. Por ejemplo puede haber una altura mínima para todos los DIV (un poco raro pero para que se entienda), por lo que en nuestro CSS habría que especificar la altura mínima que querríamos para que nos afecte. Cuando se trata de insertar un overlay en cualquier página puede llegar a ser muy complicado que se vea igual en todos los sitios.

Nuestro ejemplo es mucho más sencillo porque sólo insertamos en gmail por lo que tras una prueba vemos que no hay ningún efecto lateral extraño por lo que el siguiente CSS es suficiente para nuestro pequeño contador:

 

inject.css

 

Y a continuación por fin el código a inyectar, muy corto y sencillo gracias al jquery.

Primero una versión simple pero que con un pequño problema y a continuación la definitiva:

 

inject.js

El código lo inyectamos dentro de una función anónima autoejecutable para encapsular el contenido. No es estrictamente necesario pero es una buena práctica.

Lo primero que hay que hacer es buscar con las herramientas de desarrollador en el DOM el elemento al que le queremos hacer algo, en nuestro caso es el editor de gmail por lo que tras una pequeña investigación vemos que tiene la clase .editable y la barra donde queremos insertar el contador tiene la clase .aWQ.

Así que lo primero que hacemos es programar el evento de keypress con la función cuentaTexto en .editable.  Lo hacemos seleccionando el body para que el evento se programe en futuros divs .editable que todavía no existen.

La función cuentaTexto clona el elemento .editable para poder quitarle lo que no nos interesa sin que la página se vea afectada y poder contar el texto introducido. A continuación se pone la longitud en nuestro DIV y lo añadimos en el lugar adecuado.

Si probais esto vereis que funciona al contestar un mail pero no al crear uno nuevo. Aunque he programado el evento para divs editables  futuros la ventanita de nuevo mail no se ve afectada y no sé por qué, ¿quizás está en un iframe?, si alguien lo sabe que lo ponga en comentarios por favor.

Por tanto para arreglarlo he hecho un apaño que estropea bastante la elegancia de esta primera versión pero tampoco es que sea muy complicado:

 

inject.js (definitivo)

Añado un evento de click en el botón de Nuevo Mensaje REDACTAR (clase .T_I ) para saber cuando va a crearse la ventana y como no sé cuanto tiempo va a tardar en aparecer la ventana pongo un temporizador para que cada segundo intente añadir el evento keypress en el editor.  Hago un off antes del on para que no se programe más de una vez el evento.

En cuanto se ejecuta por primer ver cuentaTexto se quita el temporizador.

De esta forma, un poco chapuza la verdad, arreglamos el problema de la ventana de nuevo mensaje.

 

Es fácil darse cuenta que esta manera de interactuar con la página tiene un problema: el dia que google rediseñe la página y por tanto cambien las clases, nuestra extensión deja de funcionar y hay que volver a inspeccionar el DOM y cambiar los nombres de las clases.

 

Nada más por ahora, en próximas entregas iremos haciendo la extensión más interesante y aprenderemos más cosas sobre extensiones como hacer un proceso en segundo plano o un popup al hacer click en un icono de la barra de extensiones.

 

11 Comentarios

    • Hola Gabriel, gracias por comentar.
      Si estas desarrollando una extensión para un navegador en concreto no tiene sentido preocuparte porque el código funcione en otro, por eso decía lo de olvidarse del crossbrowser.
      Está claro que los monopolios no son buenos, si programas una extensión siempre puedes hacerla para los navegadores que quieras sino quieres contribuir a ello. Lo malo es que los otros navegadores no dan tantas facilidades como chrome lo que contribuye a tener un buen catálogo de extensiones y esa es una de las razones (entre muchas otras claro) que contribuyen a su dominio.

      Responder
  1. Excelente tutorial! Oscar, Estoy esperando próximas entregas…
    Muchas gracias por compartir tú conocimiento con nosotros.

    Responder
    • Gracias por tu interés Andrés.

      Responder
  2. Hola Oscar excelente tuto, estoy buscando algo parecido para un proyecto. saludos.

    Responder
    • Gracias por comentar Federico y perdona el retraso en contestar.

      Responder
  3. Necesito un desarrollador que me elabore una extensión para Chrome. Escribir al correo

    Responder
  4. Muy interesante amigo, ¿Queria saber si es posible crear una extension que se ejecute cuando no hay acceso a internet, mejor dicho para remplazar el juego del dinosaurio?.

    Responder
  5. Excelente material el que has publicado

    Oscar es posible que tengas alguna extension donde utiliza la API de Facebook ?

    Muchas Gracias

    Responder
    • Hola Rafal.
      No tengo ninguna extensión pública que use la API de facebook, pero la he usado. La única dificultad es el login ya que no se hace desde una página web normal sino desde una extensión que la API de facebook no tiene asociada a la app que se ha creado desde la página de desarrolladores de facebook.
      Puede ser una buena idea hacer un artículo sobre el login.

      Responder

Enviar comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *