Como desenvolver extensões para Chrome e Firefox
1. Fundamentos das Extensões de Navegador
Desenvolver extensões para navegadores exige compreender a arquitetura comum entre Chrome e Firefox, baseada em três componentes principais: o arquivo de manifesto (manifest.json), scripts de background e content scripts. O manifesto define metadados, permissões e recursos. No Chrome, o Manifest V3 é obrigatório desde 2023, utilizando service workers no lugar de background pages persistentes. O Firefox adota o padrão WebExtensions, compatível com a API do Chrome, mas com suporte ao Manifest V2 até 2025.
As principais diferenças incluem o namespace das APIs: Chrome usa chrome.*, enquanto Firefox usa browser.* (que retorna Promises nativamente). Permissões como storage e tabs são comuns, mas o Firefox exige browser_specific_settings para identificar o add-on.
2. Estrutura do Projeto e Configuração Inicial
Crie uma pasta para o projeto e adicione o arquivo manifest.json. Exemplo mínimo para Chrome (V3):
{
"manifest_version": 3,
"name": "Minha Extensão",
"version": "1.0.0",
"description": "Exemplo de extensão multiplataforma",
"permissions": ["storage", "tabs"],
"host_permissions": ["*://*/*"],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
Para Firefox, adicione:
"browser_specific_settings": {
"gecko": {
"id": "minha-extensao@exemplo.com",
"strict_min_version": "109.0"
}
}
Use chrome://extensions (Chrome) com modo desenvolvedor ativado para carregar a pasta. No Firefox, use about:debugging#/runtime/this-firefox.
3. Ciclo de Vida e Scripts de Background
No Chrome V3, o background é um service worker que não persiste entre eventos. Exemplo de background.js:
// Chrome V3 - Service Worker
chrome.runtime.onInstalled.addListener(() => {
console.log('Extensão instalada!');
chrome.storage.local.set({ installed: true });
});
chrome.action.onClicked.addListener((tab) => {
chrome.tabs.create({ url: 'https://exemplo.com' });
});
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'GET_DATA') {
chrome.storage.local.get('data', (result) => {
sendResponse(result);
});
return true; // Mantém a resposta assíncrona
}
});
Para compatibilidade com Firefox, use polyfill ou adapte para browser.*:
// Firefox - usa browser.* que retorna Promise
browser.runtime.onInstalled.addListener(() => {
browser.storage.local.set({ installed: true });
});
4. Content Scripts e Interação com Páginas Web
Content scripts são injetados no contexto da página. Defina no manifest.json:
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"css": ["styles.css"]
}
]
Exemplo de content.js:
// Envia mensagem para o background
chrome.runtime.sendMessage({ type: 'PAGE_LOADED', url: window.location.href }, (response) => {
console.log('Resposta do background:', response);
});
// Manipula DOM
const button = document.createElement('button');
button.innerText = 'Clique aqui';
button.addEventListener('click', () => {
chrome.runtime.sendMessage({ type: 'BUTTON_CLICKED' });
});
document.body.appendChild(button);
Para comunicação bidirecional, o background pode usar tabs.sendMessage:
// No background.js
chrome.tabs.sendMessage(tabId, { action: 'updateUI' }, (response) => {
console.log('Content script respondeu:', response);
});
Restrições: content scripts não acessam variáveis da página (como window.jQuery) diretamente, a menos que injetem script via script tag.
5. Interface de Usuário: Popups, Sidebars e Action Buttons
Crie popup.html:
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 300px; padding: 10px; font-family: Arial; }
button { margin: 5px; padding: 8px; }
</style>
</head>
<body>
<h3>Minha Extensão</h3>
<button id="save">Salvar</button>
<button id="load">Carregar</button>
<div id="output"></div>
<script src="popup.js"></script>
</body>
</html>
popup.js:
document.getElementById('save').addEventListener('click', () => {
chrome.storage.local.set({ data: 'exemplo' }, () => {
document.getElementById('output').innerText = 'Salvo!';
});
});
document.getElementById('load').addEventListener('click', () => {
chrome.storage.local.get('data', (result) => {
document.getElementById('output').innerText = result.data || 'Vazio';
});
});
Para sidebar no Firefox, adicione ao manifest:
"sidebar_action": {
"default_panel": "sidebar.html",
"default_title": "Minha Sidebar"
}
6. Funcionalidades Avançadas e APIs Específicas
Controle de abas com chrome.tabs:
// Abrir nova aba
chrome.tabs.create({ url: 'https://exemplo.com', active: true });
// Fechar aba atual
chrome.tabs.remove(tabId);
// Obter aba ativa
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
console.log('Aba ativa:', tabs[0].id);
});
Interceptação de rede com declarativeNetRequest (Chrome V3) — mais seguro que webRequest:
// No manifest.json
"declarative_net_request": {
"rule_resources": [{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}]
}
// rules.json
[{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": {
"urlFilter": "anuncio-tracker.com",
"resourceTypes": ["script"]
}
}]
7. Compatibilidade entre Chrome e Firefox
Use polyfill para unificar APIs. Exemplo:
// polyfill.js — carregue antes dos outros scripts
if (typeof browser === 'undefined') {
var browser = chrome;
}
// Agora use browser.* em todo o código
browser.storage.local.get('key').then((result) => {
console.log(result);
});
No manifest, diferencie versões mínimas:
// Chrome
"minimum_chrome_version": "109"
// Firefox
"browser_specific_settings": {
"gecko": {
"strict_min_version": "109.0"
}
}
Ferramenta web-ext para testar no Firefox:
npm install -g web-ext
web-ext run --firefox=nightly
8. Publicação e Manutenção
Empacote a extensão:
- Chrome: comprima a pasta em
.zipe envie ao Chrome Web Store. - Firefox: use
web-ext buildpara gerar.xpiou envie o código-fonte para análise.
Antes de publicar, valide:
- Teste em ambos navegadores.
- Verifique permissões mínimas necessárias.
- Monitore erros com
console.loge ferramentas de depuração.
Para atualizações, incremente a versão no manifest.json e reenvie. Mantenha um changelog e teste regressivamente.
Referências
- Documentação oficial de Extensões do Chrome — Guia completo sobre Manifest V3, APIs e boas práticas.
- MDN WebExtensions — Referência completa para desenvolvimento no Firefox, com exemplos de compatibilidade.
- Chrome Extensions Samples — Repositório oficial com exemplos práticos de extensões para Chrome.
- web-ext — Ferramenta de desenvolvimento Mozilla — Utilitário para testar, depurar e empacotar extensões Firefox.
- Polyfill browser.* para Chrome — Biblioteca que unifica APIs entre Chrome e Firefox usando Promises.