Creare un’estensione per Google Chrome

Chrome, il browser web di google, ormai non ha più bisogno di presentazioni. Le sue prestazioni, le tab sandboxed e la sua dedizione agli standard web, aiutato dal motore di rendering WebKit, lo rendono un ottima scelta come browser predefinito.

Quello che gli manca ancora è un buon parco di estensioni. Da questo punto di vista Firefox parte avvantaggiato, ma la situazione sul fronte Chrome si sta lentamente sbloccando e nelle ultime versioni in sviluppo è già possibile usare userscripts (gli script Greasemonkey di Firefox) e estensioni, con tanto di sito dedicato.

In questo mio primo articolo vorrei quindi introdurvi allo sviluppo di estensioni per Chrome, io utilizzerò Chromium su Linux ma il processo non dovrebbe essere dissimile.

L’estensione che andremo a sviluppare andrà ad aggiungere un’icona in fondo alla barra degli indirizzi (chiamate pageActions) che ci permetterà di interrogare un servizio online per recuperare i dati da whois del dominio che stiamo visualizzando.

A questo indirizzo potete trovare l’attuale documentazione relativa allo sviluppo di estensioni per Chrome: code.google.com/chrome/extensions

Struttura dell’estensione

Creiamo una cartella “whois_checker” destinata a contenere i sorgenti.

Un’estensione Chrome è descritta dal suo manifest file “manifest.json”, un file JSON posizionato nella root della cartella.

{
    "name": "WhoIS Checker",
    "description": "Adds one-click whois check to your toolbar",
    "version": "1.0",
    "permissions": [
        "tabs",
        "http://*/*",
        "https://*/*"
    ],
    "background_page": "background.html",
    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["get_domain.js"]
        }
    ],
    "icons": { "48": "info-48.png" },
    "page_actions": [
        {
            "id": "WhoIsPageAction",
            "name": "Check whois for this domain",
            "icons": ["info-16.png"]
        }
    ]
}

Oltre ai parametri auto-esplicativi come name, description, version, etc… i parametri cui prestare più attenzione in questo caso sono 3:

  • background_page: Permette di specificare uno script che verrà eseguito singolarmente, ovvero, indipendentemente dal numero di tab/finestre aperte, ci sarà sempre e comunque un solo script in esecuzione.
  • content_scripts: Sono script che vengono eseguiti all’interno della pagina visualizzata e quindi sono in grado di alterarne o leggerne il contenuto. Per ogni tab/finestra aperta ci sarà quindi uno di questi script in esecuzione.
  • page_actions: Definisce delle azioni da associare alla tab corrente. Appaiono come icone contenute all’interno della barra degli indirizzi.

Analisi

Uno script viene eseguito al caricamento di ogni pagina (get_domain.js) e passerà l’informazione del dominio (window.location.hostname) allo script in background.html.

if (window == top) {
    // Passiamo l'hostname alla background page
    chrome.extension.connect().postMessage(window.location.hostname);
}

In background.html vengono attivati i listener che servono ad “ascoltare” i messaggi passati dai content_script e ricevuto un dominio valido (escludiamo gli indirizzi IP), abilitiamo esplicitamente la pageAction che a questo punto verrà mostrata nella barra degli indirizzi

var pageActionId = "WhoIsPageAction";
var hostnames = {};

chrome.extension.onConnect.addListener(function(port) {
    // Funzione chiamata del contentScript get_domain.js, che ci passer l'hostname della tab corrente
    port.onMessage.addListener(function(hostname) {
        // Niente whois sugli IP
        if (!/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/.exec(hostname)) {
            // Estraiamo il dominio di secondo livello dall'hostname
            var matches = /[^\.]+\.[^\.]+$/.exec(hostname);
            if (matches.length==1) {
                hostnames[port.tab.id] = matches[0];
                // Se tutto  andato a buon fine, abilitiamo la pageAction
                chrome.pageActions.enableForTab(pageActionId, {tabId: port.tab.id, url: port.tab.url, title: "Check WhoIs", iconId: 0});
            }
        }
    });
});

Con un’altro listener creiamo un’azione per la pageAction, dove, dopo aver recuperato la tab in uso, creiamo un url che punta al servizio online di query whois con il nostro dominio tra i parametri. Con questo url, apriamo una nuova tab del browser e il gioco è fatto

chrome.pageActions[pageActionId].addListener(function(pageActionId, pageActionInfo) {
    chrome.windows.getCurrent(function(window) {
        chrome.tabs.get(pageActionInfo.tabId, function(tab) {
            // Assicuriamoci che la finestra sia ancora selezionata
            if (window.focused) {
                // Creaiamo l'url del servizio di query whois e apriamolo in una nuova tab
                var url = "http://artera.it/whois?s=" + encodeURIComponent(hostnames[pageActionInfo.tabId]);
                chrome.tabs.create({url: url, windowId: window.windowId});
            }
        });
    });
});

Rimane solo da fare un po’ di pulizia alla chiusura della tab

chrome.tabs.onRemoved.addListener(function(tabId) {
    hostnames[tabId] = null;
});

Testare l’estensione

Durante lo sviluppo dell’estensione è possibile provarla e ricaricarla “al volo” senza doverla prima pacchettizare.
Ecco come fare:
Aprire una nuova tab su chrome://extensions , viene visualizzata una lista delle estensioni installate sul browser.
Cliccare su “+ Developer tools” e quindi su “Load unpacked Extension…”, selezionare quindi la cartella dell’estensione, che apparirà immediatamente in lista e potrà essere ricaricata a piacimento.

Pagina estensione | Installa | Sorgenti