Criando extensões para o Firefox - Parte I

28/08/06

Todo mundo já teve uma idéia ou sentiu falta de algum recurso em um programa. No caso de navegadores, é muito fácil adicionar funcionalidades, pelo menos para quem usa Mozilla.

O Mozilla permite adicionar, remover ou alterar funcionalidades utilizando apenas Javascript, CSS e XML. Isso te dá flexibilidade suficiente para fazer absolutamente tudo o que você quiser. Neste artigo, você terá uma idéia de como fazer sua própria extensão utilizando recursos como requisições remotas (XMLHttpRequest), suporte a múltiplos idiomas e configurações (about:config).

Mas o que é uma extensão, afinal?

Uma extensão nada mais é do que um série de arquivos escritos em XUL, Javascript e CSS e compactados em formato ZIP, com a extensão xpi. Veja, por exemplo, como é a estrutura da extensão webdeveloper, de Chris Pederick.

Estrutura da extensão Webdeveloper, criada por Chris Pederick

Você pode ou não compactar sua estrutura em formato JAR, a exemplo da extensão Webdeveloper. Neste artigo, não iremos compactá-la.

Toda a interface de sua extensão será feita com tags em XML. Por exemplo, para adicionar um botão você pode utilizar a tag <button />. Já o comportamento que sua extensão terá é definido com Javascript. Por exemplo, podemos exibir uma mensagem "Você clicou no botão" com o código <button oncommand="alert('Você clicou no botão');" />.

Percebeu que tudo é feito de maneira clara e simples?

Preparando o ambiente para desenvolvimento

Para começar a desenvolver, podemos instalar algumas extensões que irão facilitar nossa vida:

  • Console2: exibe os erros no chrome de maneira organizada;
  • DOM Inspector: visualizador da estrutura DOM; ajuda na hora de analisarmos o documento;
  • ReloadChromezilla: atualiza o chrome sem a necessidade de reiniciar o browser.

Além disso, devemos definir algumas configurações do navegador. Basta digitar about:config como URI na barra de endereços. Se não sabe do que estou falando, dê uma olhada aqui e aqui.

  • javascript.options.showInConsole: defina como true para exibir os erros de chrome no console;
  • nglayout.debug.disable_xul_cache: defina como true para desabilitar o cache dos arquivos XUL;

Uma coisa extremamente útil é trabalhar com dois perfis distintos. O Firefox não permite que mais de um perfil seja aberto por padrão, mas é possível abrir quantos você quiser. Basta digitar set MOZ_NO_REMOTE=1 na linha de comando. Depois, abra o perfil com o comando firefox -P dev (se for fazer uma extensão para o Thunderbird, é aconselhável que você faça isso). Para usuários de Windows, adicione a pasta do Firefox na variável de ambiente PATH. Veja mais sobre como fazer isso aqui.

Arquivos de Configuração

Para permitir que sua extensão seja instalada, é preciso configurar dois arquivos com algumas informações. São eles chrome.manifest e install.rdf.

Entendendo o "Install Manifest"

O install.rdf é um arquivo XML que contém informações que são utilizadas pelo instalador no momento em que você for adicionar a extensão. Veja um exemplo:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
	<Description about="urn:mozilla:install-manifest">
		<em:id>{XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}</em:id>
		<em:name>Extensão de Exemplo</em:name>
		<em:version>1.0</em:version>
		<em:description>Uma extensão de exemplo com algumas funcionalidades</em:description>
		<em:creator>Seu nome aqui</em:creator>
		<em:contributor>Uma pessoa que te ajudou</em:contributor>
		<em:contributor>Outra pessoa</em:contributor>
		<em:homepageURL>http://sampleextension.mozdev.org/</em:homepageURL>
		<em:optionsURL>chrome://sampleext/content/settings.xul</em:optionsURL>
		<em:aboutURL>chrome://sampleext/content/about.xul</em:aboutURL>
		<em:iconURL>chrome://sampleext/skin/mainicon.png</em:iconURL>
		<em:updateURL>http://sampleextension.mozdev.org/update.rdf</em:updateURL>
		<em:type>2</em:type>
		<em:targetApplication>
			<Description>
				<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
				<em:minVersion>0.9</em:minVersion>
				<em:maxVersion>1.0</em:maxVersion>
			</Description>
		</em:targetApplication>
	</Description>
</RDF>

Os pricipais elementos deste arquivo são:

id
Obrigatório. Identificador único de sua extensão. Atualmente, somente duas maneiras são aceitas. A primeira é gerando um ID com uma ferramenta desenvolvida pela Microsoft e disponibilizada aqui. Você também pode gerá-la aqui e aqui. A segunda é utilizando o formato extensao@dominio, por exemplo, extensao@simplesideias.com.br.
name
Obrigatório. É o nome de sua extensão, por exemplo, "GMail Notifier".
version

Obrigatório. Versão de sua extensão. Se você não em idéia de como definir a versão de sua extensão, use algo como X.Y.Z, onde:

  • X denota a versão da extensão
  • Y denota implementação de funcionalidades
  • Z denota correções de bugs

Na prática, fica algo assim:

  • 1.0: versão inicial da extensão;
  • 1.0.1: correção de algum bug ou modificação não-significativa;
  • 1.1: implementação de nova funcionalidade ou modificação significativa;
  • 1.1.1: correção de bug ou modificação não-significativa;
description
Obrigatório. Uma descrição de sua extensão, expressa de maneira suscinta.
creator
Obrigatório. Nome do criador da extensão.
homepageURL
Opcional. Site onde o usuário pode encontrar mais informações sobre a extensão.
optionsURL
Opcional. Arquivo que será exibido quando o usuário selecionar a opção "Preferências" da extensão o gerenciador de extensões.
updateURL
Opcional. Caminho para atualizações da extensão. Veja um exemplo deste arquivo:
<?xml version="1.0"?>
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/2004/em-rdf#">
<r:Description about="urn:mozilla:extension:
{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}">
  <updates>
    <r:Seq>
      <r:li>
        <r:Description>
          <version>0.1</version>
          <targetApplication>
            <r:Description>
              <id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</id>
              <minVersion>0.8</minVersion>
              <maxVersion>1.9</maxVersion>
              <updateLink>http://www.webserver.com/foowidget.xpi</updateLink>
            </r:Description>
          </targetApplication>
        </r:Description>
      </r:li>
    </r:Seq>
  </updates>
  <version>0.1</version>
  <updateLink>http://www.webserver.com/foowidget.xpi</updateLink>
</r:Description>
</r:RDF>
targetApplication

Obrigatório. Identifica quais aplicativos sua extensão suporta. Veja algumas GUIDs:

Relação de GUIDs
Aplicativo GUID
Firefox {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
Thunderbird {3550f703-e582-4d05-9a08-453d09bdfdc6}
Mozilla Suite {86c18b42-e466-45a9-ae7a-9b95ba6f5640}
SeaMonkey {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
Netscape {3db10fab-e461-4c80-8b97-957ad5f8ea47}
Flock {a463f10c-3994-11da-9945-000d60ca027b}

Para que sua extensão suporte o Mozilla Suite e SeaMonkey, é preciso incluir no pacote o arquivo install.js. Futuramente, não será mais preciso incluí-lo.

Entendendo o "Chrome Manifest"

Chrome é o nome dado à interface de pacotes criada pelos navegadores Mozilla. Para acessar arquivos adicionados ao Chrome, basta definir a URI chrome://. Um pacote padrão pode ser acessado através da URI chrome://browser/. Para que nossa extensão seja considerada parte do Chrome, é preciso criar um arquivo chamado "Chrome Manifest".

O "Chrome Manifest" é responsável por indicar a localização dos arquivos utilizados por sua extensão. Esse arquivo tem um formato que deve ser seguido e deve estar localizado na raíz da extensão sob o nome chrome.manifest. Veja um exemplo:

content       pacote   content/
locale        pacote   pt-BR   locale/pt-BR/
locale        pacote   en-US   locale/en-US/
overlay       chrome://browser/content/browser.xul    chrome://pacote/content/browser.xul

As linhas acima indicam o conteúdo da extensão pacote está no diretório content; possui dois idiomas (pt-BR e en-US) e seus arquivos estão localizados no diretório locale; o arquivo que irá exibir nossa extensão no browser é indicado como overlay.

Apesar do suporte à múltiplos idiomas não ser obrigatório, é extremamente recomendado que você o faça. É muito simples e permite que ela seja utilizada por um maior número de pessoas no mundo!

De olho no câmbio

Nada melhor do que a prática para entender como se faz uma extensão. É recomendado que você tenha conhecimentos de Javascript e CSS, já que estes não serão explicados passo-a-passo. Se você não entende nada desses dois itens, existe bastante coisa disponível por !

Nós iremos criar uma extensão que exibe informações sobre o câmbio, com dados disponibilizados pelo site WebServiceX. Para definirmos melhor o que temos que fazer, segue uma lista:

  • A extensão atualizará as informações sobre o câmbio em intervalos de 180 segundos;
  • Ao clicar o botão esquerdo do mouse, atualizaremos as informações instaneamente;
  • Ao clicar com o botão direito, abriremos uma janela de preferências para que seja feita a escolha das moedas para a conversão.
  • As moedas escolhidas deverão ser armazenadas de forma que o usuário não precise selecioná-las novamente;
  • Nossa extensão terá a seguinte aparência:
    Exchange Notifier
  • As moedas disponíveis para fazer a conversão são Real, Dólar Americano, Euro, Yen, Yuan, Peso Argentino e Libra Esterlina. Os dados serão obtidos através de uma requisição com o objeto XMLHttpRequest, popularmente chamado de AJAX.

Criando nossos arquivos de configuração

Para iniciar crie um diretório com o nome "exchangenotifier". Esse será nosso diretório-raiz e também o nome de nosso pacote (daqui para frente referenciado como "raíz", certo?). Crie um arquivo com o nome "install.rdf" e adicione o seguinte conteúdo:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
	<Description about="urn:mozilla:install-manifest">
		<em:id>exchangenotifier@simplesideias.com.br</em:id>
		<em:name>Exchange Notifier</em:name>
		<em:version>1.0</em:version>
		<em:description>Money exchange. Information powered by WebserviceX</em:description>
		<em:creator>Nando Vieira</em:creator>
		<em:homepageURL>http://simplesideias.com.br/</em:homepageURL>
		<em:optionsURL>chrome://exchangenotifier/content/settings.xul</em:optionsURL>
		<em:type>2</em:type>
 
		<em:targetApplication>
			<Description>
				<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
				<em:minVersion>0.9</em:minVersion>
				<em:maxVersion>2+</em:maxVersion>
			</Description>
		</em:targetApplication>
	</Description>
</RDF>

Não se preocupe em colocar a descrição em português. Na segunda parte deste artigo iremos adicionar suporte a múltiplos idiomas.

Agora, criar nosso arquivo "Chrome Manifest"; crie na raíz um arquivo chamado "chrome.manifest" com o seguinte conteúdo:

content     exchangenotifier   content/
overlay     chrome://browser/content/browser.xul    chrome://exchangenotifier/content/browser.xul

Novamente, temos a definição do arquivos que compoem nossa extensão. Vale lembrar que não precisamos definir individualmente cada arquivo. Isso poderia ser maçante no caso de termos uma quantidade muito grande de arquivos como imagens. Bastou definir o diretório (neste caso "content").

Como nossa extensão terá algumas configurações que deverão ser salvas (moedas de conversão, por exemplo), já podemos adicioná-las automaticamente durante o processo de instalação, com valores-padrão. Crie um diretório "default" na raíz com um subdiretório "preferences". Um arquivo .js adicionará estas configurações:

pref('extensions.exchangenotifier.from', '');
pref('extensions.exchangenotifier.to', '');
pref('extensions.exchangenotifier.last_exchange', '');
pref('extensions.exchangenotifier.last_status', '');

Agora, crie um diretório na raíz chamado "content". Veja como está nossa estrutura:

Estrutura

Nosso primeiro arquivo XUL

O arquivo "browser.xul" relacionando no Chrome Manifest irá sobrepor (overlay) a interface do browser. Para indicarmos onde ela irá aparecer, devemos definir o ID do elemento da interface. Neste exemplo iremos exibir um ícone na barra de status. Adicione o código abaixo em "browser.xul".

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://exchangenotifier/content/style.css" type="text/css"?>
<!DOCTYPE overlay>
<overlay id="exn-overlay" 
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <!-- Aqui vai o código XUL de nossa extensão -->
</overlay>

Essa é, provavelmente, a estrutura mais básica de um arquivo XUL que irá funcionar como "overlay". Temos um arquivo CSS que irá definir a formatação. O elemento overlay tem um ID único definido aqui como exn-overlay.

Você pode abrir este arquivo no Firefox para ver se ele está funcionando. Se tiver algo errado, uma mensagem de erro XML será exibida.

Um problema muito constante ao desenvolver extensões e agravado quando se está começando, é não saber quais são as tags disponíveis. O melhor lugar para se obter estas informações é em XULPlanet. Lá, você tem toda a relação de tags com uma descrição e exemplo de cada uma.

Por acaso, o elemento que precisamos adicionar chama-se statusbar. O elemento statusbar pode ter diversos elementos statusbarpanel, que nada mais são do que aqueles vários "quadradinhos" onde muitas extensões são exibidas.

Exemplos de statusbarpanel

Sabendo disso, já podemos adicionar nossa extensão à barra de status com o seguinte código:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://exchangenotifier/content/style.css" type="text/css"?>
<!DOCTYPE overlay>
<overlay id="exchangenotifier-overlay" 
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <statusbar id="status-bar">
		<statusbarpanel id="exn-statusbar">
			<image id="exn-icon" />
			<label id="exn-label"></label>
		</statusbarpanel>
    </statusbar>
</overlay>

Note como é simples a maneira que adicionamos itens ao browser. Todas as tags possuem nomes que remetem ao próprio elemento (statusbar, image, label, button, dialog).

Crie o arquivo "style.css" dentro do diretório "content". É ele que irá cuidar de toda a parte visual de nossa extensão. Adicione o seguinte conteúdo:

#exn-icon {
    list-style-image: url("chrome://exchangenotifier/content/chart_curve.png");
}

A imagem utilizada nesta extensão foi retirada do pacote Silk Icons, disponibilizado por famfamfam.

Visualizando sua extensão

A maneira mais simples de visualizar a extensão durante o desenvolvimento, é movendo o diretório raíz para a pasta de extensões presente no seu perfil. Para quem usa Ubuntu Dapper o caminho padrão é ~/.mozilla/firefox/xxxxxxxx.default. No Windows XP (versão em inglês), o caminho é C:\Documents And Settings\USER\Application Data\Mozilla\Firefox\Profiles\xxxxxxxx.default. Outros sistemas, não tenho a menor idéia. Faça um busca pelo diretório Profiles e você provavelmente encontrará. Leia mais aqui. Depois, basta reiniciar o Firefox para ativar a extensão.

Estrutura

Acesse o about:config e digite "exchangenotifier". Você verá que as preferências que colocamos no arquivo "prefs.js" foram adicionadas.

About:config

É isso aí! Espero que você tenha gostado da primeira parte deste artigo. Se tiver dúvidas ou sugestões, deixe seu comentário! Pegue a extensão que fizemos até agora, baixando o arquivo exchangenotifier-1.xpi.

Referências

  • http://kb.mozillazine.org/Install.rdf#Creating_install.rdf_using_tools
  • http://kb.mozillazine.org/Setting_up_extension_development_environment
  • http://developer.mozilla.org/en/docs/Building_an_Extension
  • http://developer.mozilla.org/en/docs/Install_Manifests
  • http://www.rietta.com/~frank/firefox/Tutorial/overview.html
  • http://roachfiend.com/archives/2004/12/08/how-to-create-firefox-extensions/
  • http://www.hevanet.com/acorbin/xul/top.xul
  • http://roachfiend.com/archives/2005/03/09/enabling-extension-updates/

Comentários #


#1 Edu Ottaviani disse:
28 Out 06, 09:24PM

Cara, muito interessante esse post. Eu não uso o Firefox aqui em casa, nem o IE, por increça que parível tenho usado um browser diferente, o K-meleon, acho que eu e uma meia dúzia de pessoas no mundo usam =/. Eu comecei a ler esse post agora, então ainda vou precisar aprender direitinho sobre o assunto antes de eu me aventurar em criar algum tipo de extensão, mas eu queria saber se é possivel usar extensões do firefox no k-Meleon. Caso eu queria usar a extensão "exchangenotifier", vc saberia me dizer o que tenho de fazer para habilitá-la no K-meleon? Caso isso seja possível de ser feito sem algum tipo de alteração no arquivo é claro.

Abraços

#2 Nando Vieira disse:
28 Out 06, 09:34PM

Olá Edu. Não sei te dizer como é o suporte à extensões do K-meleon. Se ele seguiu a mesma estrutura do Mozilla Suite, é possível, mas você terá que criar o arquivo "install.js", além de colocar o ID do browser. Seria interessante você entrar em contato com os desenvolvedores e perguntar em que nível está esse suporte. Se tiver alguma informação, posta aqui para vermos o que dá para fazer.

#3 Marcello Gomes disse:
22 Dez 06, 02:43AM

Olá Nando Vieira. Gostaria de saber se você pretende fazer a segunda parte deste artigo, gostei muito desta primeira parte, muito bem explicado, e gostaria muito de saber como termina.

Abraços

#4 Nando Vieira disse:
22 Dez 06, 07:55AM

Olá Marcello! Já estou escrevendo a segunda parte. Como é um conteúdo um pouco extenso e tenho que alternar entre todas as outras coisas, estou enrolando… :P

Abraço!

#5 Marcello Gomes disse:
22 Dez 06, 02:53PM

Ok. Nando vou ficar esperando ansiosamente…afinal material de boa qualidade vale a pena esperar…

#6 Lista 2.0 atualizada com boo-box, Outrolado, Spesa e 0BR | Web 2.... disse:
31 Jan 07, 11:41AM

[...] Neste tempo fora, eu também montei um projeto mais humilde. É o 0BR. Ele serve como um encurtador de URL só que na linha Web 2.0. Está em beta mesmo, então ainda tem muita coisa para fazer. O Marco foi super solícito em ajudar, mesmo com o pouco tempo. O 0BR já conta com uma Extensão Firefox. Feita do zero, foi um exercício bem prazeroso de como construir uma extensão. O que me incentivou foi um post do Simples Idéias. Com a idéia geral na cabeça, parti para o tutorial do próprio Mozilla. A extensão é open source, se quiser brincar ou contribuir, manda ver. Tem também material aprendido/coletado de vários outros blogs, mas que acabei não anotando, mas se eu lembrar atualizo o post. O 0BR terá uma série de serviços assim que surgir mais tempo. [...]

#7 Marcelo Eyer Fernandes disse:
17 Fev 07, 12:34AM

É verdade, seria interessante fazer para o K-Meleon. Edu já descobriu algo a respeito?
A propósito, o número de usuários de K-Meleon vem crescendo muito, vemos isso claramente na comunidade do Orkut, inicialmente com poucos membros e hoje com 106 membros. Ele é feito sim com engine do Mozilla, e normalmente os plugins do Netscape que são compativeis. Quem puder ajudar poste aqui e/ou lá na comunidade também.

#8 Rafael Spengler disse:
19 Maio 07, 11:26AM

Olá, Nando!

Excelente o seu artigo. Muito esclarecedor, ainda mais pela falta de conteúdo de qualidade sobre o assunto disponível na Internet. Meus parabéns!

Agora, tenho uma dúvida: é possível fazer com que o Firefox abra um aplicativo local a partir de algum botão? Por exemplo, quero que haja um botão no browser para que ele execute o Kate (KDE users, uni-vos! hehe) ou o MSN (no caso do Windows).
Estive pesquisando sobre isso e não encontrei a solução…

Se souber de algo, por favor, me avise. ;)

Muito obrigado e, mais uma vez, parabéns.
Abraço.

#9 Nando Vieira disse:
19 Maio 07, 01:41PM

Rafael, dê uma olhada no código fonte do FoxyTunes[1], pois é exatamente isso que ele faz.

[1] https://addons.mozilla.org/en-US/firefox/addon/219

#10 Melissa Marcondes disse:
13 Jul 07, 10:41AM

Olá ! MUito bom mesmo o artigo, mas não consegui visualizar a extensão no about:config….o q pode ser???

AH, eu também espero anciosa a publicação da segunda parte ! Se puder me enviar um e-mail qdo estiver pronto ficarei muito feliz !

#11 Sândalo Bessa disse:
14 Ago 07, 11:39AM

Muito legal o artigo. Parabéns! Se puder, me avise por e-mail quando for colocar a segunda parte do artigo.

#12 Sândalo Bessa disse:
16 Ago 07, 09:38AM

A partir do seu artigo criei minha extensão. Consegui fazer até o velho "Hello, world". Mas agora "impaquei". E ai vai minha dúvida. Como faço para acessar Objetos da página através de minha extensão? O código abaixo parece não funcionar.
var linhas = window.document.getElementsByTagName('tr');

Desde já agradecido.

#13 Sândalo Bessa disse:
17 Ago 07, 11:58AM

Olá Nando, como disse no comentário anterior, estou tentando fazer um pequena extensão a partir do seu artigo. Mas quando tento acessar qualquer elemento da página não vem nada. Um simples "window.document.getElementsByTagName('tr')" que deveria trazer uma coleção de linhas, simplesmente não traz nada. Será que tem a ver com segurança? Se poder dar um força, agradeço, pois achei muito interessante o artigo mas não consigo passar desse ponto.
Agradecido Sândalo Bessa.

#14 Kelcio Casemiro de Oliveira disse:
21 Ago 07, 03:11PM

Oi Nando, muito bom seu artigo. Estou tentando desabilitar o menu de contexto da barra de abas e o duplo click também, mas não tem jeito. Se você souber como bloquear também o shift+click-esquerdo para não abrir uma nova janela fico muito grato.

Obrigado Nando.

#15 ricardo disse:
09 Set 07, 12:13PM

muito interessante sua matéria. consegui fazer minha "extensão" seguindo
o tutorial disponivel no developer.mozilla.org, mas sua matéria tirou muitas dúvidas.
agora quero implementar um jeito dela chamar funções em dll usando XPCOM mas esta dificil, hehe

se alguem estiver disposto a implementar algo juntos, contate-me

#16 silvandro disse:
27 Nov 07, 04:10AM

Muito bom o seu artigo gostaria de saber como faço para pegar o código html da pagina que esta ativa no firefox

#17 Priscila disse:
04 Fev 08, 01:42PM

olá Nando!
como fazemos para tirar uma extensão do firefox? grata.

#18 Priscila disse:
04 Fev 08, 01:45PM

No seu Firefox, clique em:
Ferramentas > Complementos

Na janela de complementos, selecione a aba "Extensões". As extensões instaladas no navegador estarão listadas lá. Basta clicar no botão "Desinstalar" da Extensão que você deseja.

#19 Francisco.ETI.BR » Blog Archive » Criando Extensões ... disse:
06 Out 08, 01:52PM

[...] http://simplesideias.com.br/criando-extensoes-para-o-firefox-i/ [...]

Deixe um comentário




Este blog usa o Gravatar.


Não é aceito código HTML:
adicione-o no pastie.caboo.se ou paste.milk-it.net e poste apenas o link.

Se este é seu primeiro comentário, ele terá que ser aprovado antes de ser exibido.