MENU Mário Valney

Como criar extensões do Google Chrome

Google 04 de janeiro de 2015 31 comentários
Google
  • 04 - 01 - 15
  •        
  • 31

E ae galera! Hoje vamos aprender a mudar a cor do Facebook criar extensões para o Google Chrome. Pois é! Sinceramente não conheço muito material em portuga sobre o assunto (claro que se você é DEV vai manjar de inglês o suficiente para desenrolar os sites gringos e, se não consegue ainda desenrolar, sugiro clicar aqui ou aqui e começar a aprender inglês logo).

Se você está aqui, você já sabe o que são extensões, contudo eu precisava de uma imagem bonitinha aqui então vai essa e já ajuda quem ainda não sabe o que são extensões...
Se você está aqui, você já sabe o que são extensões, contudo eu precisava de uma imagem bonitinha aqui então vai essa e já ajuda quem ainda não sabe o que elas são…

Getting Start!

Antes de mais nada eu vou deixar aqui o link da documentação do Google ( sugiro ler :D ) e um comentário também:

/* A melhor coisa de desenvolver extensões para o Chrome é
desenvolver para APENAS o Chrome. Sério... nada de ficar com
pena se vai rodar no iE7 e talz ( se você é Front me entende :D ) */

Agora sim! Podemos começar: hoje iremos criar uma extensão que muda a cor do Facebook.

Mas como fazemos isso?

A lógica do negócio é que uma extensão do Google Chrome nos permite alterar o navegador (e as páginas carregadas) sem mexer em código nativo. Utilizaremos apenas os bons e velhos 3 mosqueteiros: HTML, CSS e JS.

Manifesto

Está acompanhando nossas aulas de Android? Se estiver, já tem uma ideia do que seja um manifesto. Um arquivo de manifesto é o responsável por passar informações sobre o que você está desenvolvendo. No caso do Android é um arquivo XML que possui desde o nome do aplicativo até a versão mínima do Android suportada, entre várias outras coisas. Mas estamos falando de Extensões do Chrome, jovem soldado.

O manifesto de uma extensão é um arquivo JSON com todas as informações da sua extensão como versão do manifest (atualmente a versão é a 2 e o Chrome suporta apenas ela), nome da extensão, nome curto (até 12 caracteres), permissões, ações de página, ações no browser, e você deve chamá-lo de manifest.json e deixá-lo na pasta raiz da extensão.

Na documentação temos uma lista completa do que pode/deve colocar no manifesto, abaixo irei colocar o manifesto que utilizaremos na nossa extensão:

{
    // Obrigatório
    "manifest_version": 2,
    "name": "Facebatman",
    "version": "1.0",

    // Descrição da nossa extensão
    "description": "Deixe seu Facebook negro como a noite!",

    // Íconea da nossa extensão
    "icons": {
       "48": "icon48.png",
       "128": "icon128.png"
    },

    // Utilizaremos as "Page Actions" e registramos isso aqui
    "page_action": {
        "default_icon": {
            "19" : "icon-19.png"
        },
        "default_title": "Facebatman"
    },

    // Aqui declaramos as permissões que precisamos
    "permissions": [
        "tabs",
        "http://*/*",
        "https://*/*",
        "declarativeContent"
    ],

    // Utilizaremos uma "Event Page" (note o persistent: false)
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },

    // Injetaremos esses arquivos quando "match" ocorrer
    "content_scripts": [ {
        "js": [ "jquery.js", "facebatman.js" ],
        "css": [ "facebatman.css" ],
        "matches": [ "https://*.facebook.com/*" ]
    } ]
}

Informações Obrigatórias

No manifesto é obrigatório colocar a chave manifest_version que (atualmente) deve ter seu valor igual a 2 (sem aspas). Além disso, devemos colocar o nome e a versão da extensão, ambos em strings. Para a versão devemos utilizar uma string de até 4 números separados por pontos:

  • “version”: “1”
  • “version”: “1.0”
  • “version”: “2.10.2”
  • “version”: “3.1.2.4567”

Você pode também informar o nome da versão com a chave version_name, um nome curto (de até 12 caracteres) com a chave short_name e uma descrição escrevendo uma description, mas esses três não são obrigatórios.

Ícones

As extensões devem possuir um ícone principal (para a Chrome Store) de 128×128 pixels com transparência nas bordas (se for quadrado deve possuir área visível de 96×96, se for circular essa área cresce para 112×112) e outro de 48×48 pixels (não há nada sobre transparência para esse tamanho) para a página de gerenciamento de extensões (chrome://extensions).

Além desses ícones, vamos utilizar dois ícones (38×38 e 19×19) para aparecerem na barra de endereço, quando a extensão estiver ativa, ou seja, para usarmos como default_icon das ações de páginas (falaremos mais sobre isso daqui a pouco).

Page Actions

Como vamos executar uma ação apenas em uma página e não em todas, utilizaremos uma page action. No manifesto, informamos um ícone e um título padrão para aparecerem durante a execução da extensão. Eles irão aparecer na barra de endereço:

batbook - barra de endereco

Background

Podemos ler na documentação :

Uma necessidade comum para as extensões é ter um script único que rode durante todo o tempo para gerenciar algumas tarefas ou estados da extensão. Quem vem em socorro disso são as páginas de background.

Então a chave background nos permite declarar uma página de background para nossa extensão. Maaaaaaas…

SPOILER: Nade de bom virá disso...
SPOILER: Nade de bom virá disso…

Agora imagine comigo cada extensão ter seus scripts de background rodando toda hora. A galera da performance pira! Pois é… como eu disse ali em cima: utilizar páginas de background não é algo recomendável. Para resolver isso, temos as Páginas de Eventos, ou Event Pages, que rodam apenas quando necessário.

Para declarar uma Event Page é fácil: você só precisa acrescentar a chave persistent com o valor false no manifesto. Sem isso, você está utilizando uma Background Page e não queremos ferrar com a performance no navegador, né amiguinho? :D

Ainda falando do Background, no caso, das Event Pages, abaixo trago uma lista de prováveis situações nas quais ela pode ser ativada:

  • A extensão é instalada ou atualizada (usada para registrar alguns eventos).
  • A página de evento está escutando um evento e esse evento é disparado.
  • Um content script (falaremos mais tarde) ou outra extensão envia um mensagem.
  • Outra view na extensão (um popup, por exemplo) chama runtime.getBackgroundPage.

A página de eventos, depois de começar a rodar, só será fechada depois que todas as views (popup, por exemplo) fecharem também. Lembre que uma view abrir não significa que a página de evento começa a rodar, mas previne que ela seja interrompida.

Registrando e ouvindo eventos

O Chrome se mantem informado dos eventos aos quais a extensão adicionou listeners. Quando esse evento dispara a página de events é carregada. Por outro lado, o Chrome para de chamar a página de eventos, se a extensão utilizar removeListener para apagar esses listeners.

Além disso, devemos lembrar que os eventos só existem no contexto da página de eventos, então você precisa usar addListener cada vez que a página de eventos é carregada. Registrá-lo apenas em runtime.onInstalled é insuficiente.

Por outro lado, nossa extensão só precisa registrar uma regra à API Declarative Content que vai informar que deve ser iniciada quando a página contiver “facebook.com” em sua URL, ou seja, runtime.onInstalled é uma boa hora para registrar eventos que você quer que ocorra apenas na instalação ou atualização da extensão e na atualização do próprio Chrome (como vimos na lista anterior essa é uma das utilidades das Páginas de Eventos).

E lá vai:

// Quando instalar ou atualizar:
chrome.runtime.onInstalled.addListener(function() {
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
        chrome.declarativeContent.onPageChanged.addRules([{
            conditions: [
                new chrome.declarativeContent.PageStateMatcher({
                    pageUrl: { urlContains: 'facebook.com' },
                }) ],
            actions: [ new chrome.declarativeContent.ShowPageAction() ]
        }]);
    });
});

Code! Code! Code!

Chegou a parte boa!
Já falamos de quase tudo que utilizamos no manifesto, agora é a hora de falar da chave content_scripts, que é onde declaramos os arquivos que vamos injetar no DOM.

Resumindo, os Content Scripts são arquivos JS (e CSS também) que irão rodar no contexto das páginas web. Usando Document Object Model (sério? aaah… imagina.. :P ) podemos ler e alterar as páginas visitadas pelo navegador.

Antes de começar a codificar, vale falar da sintaxe da chave no manifesto.
Na documentação temos mais detalhes, mas basicamente, a chave recebeu uma array com outras três chaves: “js”, “css”, e “matches”:

As chaves “js” e “css”, recebem uma array com os arquivos a serem carregados (escreva o caminho relativo ao diretório raiz da extensão), na ordem a serem carregados (atenção nessa parte!) é por isso que o jquery.js veio antes do batbook.js.

A chave “matches” (obrigatória) recebe uma array de strings com as urls dos sites que irão receber essa injeção de código. Essas strings devem seguir um certo padrão.

Além dessas três chaves, podemos ter outras: leia a documentação para saber como decidir a ordem de injeção dos arquivos, como excluir urls dessa injeção (o contrário da chave “matches”), como incluir outros frames da página além do top frame e uma forma mais refinada de escolher quais páginas recebem ou não esse código.

E agora o código!

// Apenas para ensino, qualquer coisa desse tipo é chata pra caramba:
$(document).ready(function() {
	var nome = $('._2dpb').text();
	alert('Bem-vindo ' + nome + ' !');
});
._4f7n {
	background: #000000!important;
	border-color: #ffffff!important;
	border-color: #ffffff!important;
}

._4f7n:after,
._4f7n:before {
	display: none!important;
}

._50__,
._5cop ._59fb,
._4f7n a.jewelButton {
	-webkit-background-composite: destination-out;
}

E eu posso fazer isso?

Sim! Você pode!

Para inserir código numa página, sua extensão precisa ter cross-origin permissions para a página. O que significa ser possível usar o módulo chrome.tabs, ou seja, solicitar a permissão na chave permissions do manifesto.

Além dessa permissão, solicitamos também a permissão para o módulo declarativeContent, pois o utilizamos no background.js, lembra?

Ainda sobre permissões, recomendo a leitura da documentação, pois é bem importante!

Debuga. Debugaaa, dev acochambrão!

(Se você identificou a musiquinha acima você tem problemas piores que os meus… toca ae o/ )

– Quando você for desenvolver sua extensão, você vai precisar debugar, certo?
– Certo!
– Pois é… agora vem a parte chata!

Para começar a debugar sua extensão, você precisa carregá-la no navegador (tipo se estivesse instalando):

  • Vá na página de gerenciamento de extensões (chrome://extensions).
  • Agora ative a opção Modo do desenvolvedor marcando o checkbox.
  • Agora você pode clicar em Carregar extensão expandida…
  • Pronto! Navegue até a pasta onde está seu manifesto e clique em OK.

Sua extensão deve aparecer no painel como se você tivesse instalado ela nesse momento.

Vou ter que fazer isso toda vez que modificar algo?

Pois é… eu disse que era a parte chata.

Mas há algumas dicas que posso passar para vocês, mas são observações totalmente empíricas, ou seja, não achei nada que falasse disso, exceto minha própria experiência.
Caso notem algo diferente ou queiram acrescentar algo, deixem nos comentários! :D

Você precisa excluir e carregar a extensão novamente se:

  • Você modificar o manifest.json.
  • Você alterar algum evento que ocorra durante a instalação/atualização da extensão, por exemplo, o que código que escrevemos no nosso background.js.

Você precisa desativar e ativar a extensão se:

  • Modificar algum ícone
  • Alterar algum arquivo do Content Script (JS e CSS injetáveis).

Nota: para ativar/desativar a extensão, basta marcar/desmarcar o checkbox que fica à direita dela.

Mais coisas legais

Provavelmente você já consegue fazer várias coisas legais com isso que aprendemos hoje.

Contudo, ainda há muita coisa que podemos fazer com as extensões, como por exemplo, incluir um ícone ao lado da barra de endereço do browser (e não só na barra de endereço de páginas específicas) utilizando a API Browse Action em vez da API Page Action. Isso permite até criar um popup para quando clicar no botão.

Podemos também criar uma página de opções declarando a chave options_page.

Bonus: CSS Hard Core.

Eu estava sem muita coisa pra fazer (mentira) então saí mexendo mais ainda no CSS do Facebook. Isso resultou na versão Hard Core do batbook.css.

Hard Core CSS
Hard Core CSS

E é isso galera! Se gostou ou se ajudou, curta, compartilhe, envie para os amigos!
Se tiver algo para falar, xingar ou perguntar: comente!
E se quiser, pode baixar a extensão clicando aqui!

Por favor, considere desativar o AdBlock

Não perca nenhuma novidade, assinando nossa newsletter!



    Não se preocupe: não enviaremos muitos e-mails, nem mostraremos seu e-mail para ninguém. Dúvidas?


    Deixe seu comentário! Dúvida sobre como comentar
    ou vai postar código? Leia antes.