Gli script dei contenuti sono file che vengono eseguiti nel contesto delle pagine web. Utilizzando il Document Object Model (DOM) standard, possono leggere i dettagli delle pagine web visitate dal browser, apportare modifiche e trasmettere informazioni all'estensione principale.
Comprendere le funzionalità degli script dei contenuti
I content script possono accedere alle API di Chrome utilizzate dall'estensione principale scambiando messaggi
con l'estensione. Possono anche accedere all'URL del file di un'estensione con
chrome.runtime.getURL() e utilizzare il risultato come altri URL.
// Code for displaying EXTENSION_DIR/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Inoltre, lo script dei contenuti può accedere direttamente alle seguenti API Chrome:
Gli script dei contenuti non possono accedere direttamente ad altre API.
Lavorare in mondi isolati
Gli script di contenuti vivono in un mondo isolato, consentendo a uno script di contenuti di apportare modifiche al proprio ambiente JavaScript senza entrare in conflitto con la pagina o con script di contenuti aggiuntivi.
Un'estensione può essere eseguita in una pagina web con un codice simile a quello dell'esempio riportato di seguito.
<html>
<button id="mybutton">click me</button>
<script>
var greeting = "hello, ";
var button = document.getElementById("mybutton");
button.person_name = "Bob";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
</script>
</html>
Questa estensione potrebbe inserire il seguente script di contenuti.
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
Se il pulsante viene premuto, vengono visualizzati entrambi gli avvisi.
I mondi isolati non consentono agli script dei contenuti, all'estensione e alla pagina web di accedere a variabili o funzioni create dagli altri. In questo modo, gli script dei contenuti possono anche attivare funzionalità che non devono essere accessibili alla pagina web.
Inserire script
Gli script dei contenuti possono essere inseriti programmaticamente o in modo dichiarativo.
Inserisci in modo programmatico
Utilizza l'inserimento programmatico per gli script dei contenuti che devono essere eseguiti in occasioni specifiche.
Per inserire uno script dei contenuti programmatico, fornisci l'autorizzazione activeTab nel manifest. In questo modo viene concesso l'accesso sicuro all'host del sito attivo e l'accesso temporaneo all'autorizzazione schede, consentendo allo script dei contenuti di essere eseguito nella scheda attiva corrente senza specificare le autorizzazioni multiorigine.
{
"name": "My extension",
...
"permissions": [
"activeTab"
],
...
}
Gli script di contenuti possono essere inseriti come codice.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "changeColor"){
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="orange"'
});
}
});
Oppure può essere inserito un intero file.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "runContentScript"){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
}
});
Inserisci in modo dichiarativo
Utilizza l'inserimento dichiarativo per gli script dei contenuti che devono essere eseguiti automaticamente su pagine specifiche.
Gli script inseriti in modo dichiarativo vengono registrati nel manifest nel campo "content_scripts".
Possono includere file JavaScript, file CSS o entrambi. Tutti gli script dei contenuti a esecuzione automatica devono specificare
pattern di corrispondenza.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"css": ["myStyles.css"],
"js": ["contentScript.js"]
}
],
...
}
| Nome | Tipo | Descrizione |
|---|---|---|
matches {: #matches } |
Obbligatorio. Specifica le pagine in cui verrà inserito questo script di contenuti. Per maggiori dettagli sulla sintassi di queste stringhe, consulta Pattern di corrispondenza e Pattern di corrispondenza e glob per informazioni su come escludere gli URL. | |
css {: #css } |
(Facoltativo) L'elenco dei file CSS da inserire nelle pagine corrispondenti. Vengono inseriti nell'ordine in cui appaiono in questo array, prima che venga costruito o visualizzato qualsiasi DOM per la pagina. | |
js {: #js } |
(Facoltativo) L'elenco dei file JavaScript da inserire nelle pagine corrispondenti. Questi vengono inseriti nell'ordine in cui appaiono in questo array. | |
match_about_blank {: #match_about_blank } |
booleano | (Facoltativo) Indica se lo script deve essere inserito in un frame about:blank in cui il frame padre o opener corrisponde a uno dei pattern dichiarati in matches. Il valore predefinito è false. |
Escludere corrispondenze e glob
La corrispondenza delle pagine specificata è personalizzabile includendo i seguenti campi nella registrazione del manifest.
| Nome | Tipo | Descrizione |
|---|---|---|
exclude_matches {: #exclude_matches } |
(Facoltativo) Esclude le pagine in cui altrimenti verrebbe inserito questo script di contenuti. Per ulteriori dettagli sulla sintassi di queste stringhe, consulta Pattern di corrispondenza. | |
include_globs {: #include_globs } |
(Facoltativo) Applicato dopo il giorno matches per includere solo gli URL che corrispondono anche a questo glob. Destinato a emulare la parola chiave @include di Greasemonkey. |
|
exclude_globs {: #exclude_globs } |
(Facoltativo) Applicato dopo matches per escludere gli URL che corrispondono a questo glob. Destinato a emulare la parola chiave @excludeGreasemonkey. |
Lo script dei contenuti verrà inserito in una pagina se il relativo URL corrisponde a un pattern matches e a un pattern include_globs, a condizione che l'URL non corrisponda anche a un pattern exclude_matches o exclude_globs.
Poiché la proprietà matches è obbligatoria, exclude_matches, include_globs e exclude_globs
possono essere utilizzati solo per limitare le pagine interessate.
La seguente estensione inserirebbe lo script di contenuti in http://www.nytimes.com/ health ma non in http://www.nytimes.com/ business .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
Le proprietà glob seguono una sintassi diversa e più flessibile rispetto ai pattern di corrispondenza. Le stringhe glob accettabili sono URL che possono contenere asterischi e punti interrogativi "jolly". L'asterisco * corrisponde a qualsiasi stringa di qualsiasi lunghezza, inclusa la stringa vuota, mentre il punto interrogativo ? corrisponde a qualsiasi singolo carattere.
Ad esempio, il glob http:// ??? .example.com/foo/ * corrisponde a uno dei seguenti elementi:
- http:// www .example.com/foo /bar
- http:// the .example.com/foo /
Tuttavia, non corrisponde a quanto segue:
- http:// my .example.com/foo/bar
- http:// example .com/foo/
- http://www.example.com/foo
Questa estensione inserirebbe lo script dei contenuti in http:/www.nytimes.com/ arts /index.html e http://www.nytimes.com/ jobs /index.html, ma non in http://www.nytimes.com/ sports /index.html.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
Questa estensione inserirebbe lo script dei contenuti in http:// history .nytimes.com e http://.nytimes.com/ history, ma non in http:// science .nytimes.com o http://www.nytimes.com/ science .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Per ottenere l'ambito corretto, puoi includere uno, tutti o alcuni di questi elementi.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Durata esecuzione
L'inserimento dei file JavaScript nella pagina web è controllato dal campo run_at. Il campo
preferito e predefinito è "document_idle", ma può anche essere specificato come "document_start" o
"document_end", se necessario.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
| Nome | Tipo | Descrizione |
|---|---|---|
document_idle {: #document_idle } |
stringa | Preferita. Utilizza "document_idle" quando possibile.Il browser sceglie un momento per inserire gli script tra "document_end" e subito dopo l'attivazione dell'evento windowonload. Il momento esatto dell'inserimento dipende dalla complessità del documento e dal tempo necessario per il caricamento ed è ottimizzato per la velocità di caricamento pagina.Gli script dei contenuti eseguiti in "document_idle" non devono rimanere in attesa dell'evento window.onload, ma vengono eseguiti al termine del caricamento del DOM. Se uno script deve essere eseguito dopo window.onload, l'estensione può verificare se onload è già stato attivato utilizzando la proprietà document.readyState. |
document_start {: #document_start } |
stringa | Gli script vengono inseriti dopo tutti i file di css, ma prima che venga costruito qualsiasi altro DOM o eseguito qualsiasi altro script. |
document_end {: #document_end } |
stringa | Gli script vengono inseriti immediatamente dopo il completamento del DOM, ma prima del caricamento delle risorse secondarie come immagini e frame. |
Specifica i frame
Il campo "all_frames" consente all'estensione di specificare se i file JavaScript e CSS devono essere
inseriti in tutti i frame che corrispondono ai requisiti per gli URL specificati o solo nel frame principale di una
scheda.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
| Nome | Tipo | Descrizione |
|---|---|---|
all_frames {: #all_frames } |
booleano | (Facoltativo) Il valore predefinito è false, il che significa che viene abbinato solo il frame superiore.Se viene specificato true, l'iniezione viene eseguita in tutti i frame, anche se il frame non è quello più in alto nella scheda. Ogni frame viene controllato in modo indipendente per i requisiti per gli URL e non verrà inserito nei frame secondari se i requisiti per gli URL non vengono soddisfatti. |
Comunicazione con la pagina di incorporamento
Sebbene gli ambienti di esecuzione degli script di contenuti e delle pagine che li ospitano siano isolati l'uno dall'altro, condividono l'accesso al DOM della pagina. Se la pagina vuole comunicare con lo script dei contenuti o con l'estensione tramite lo script dei contenuti, deve farlo tramite il DOM condiviso.
Un esempio può essere realizzato utilizzando window.postMessage:
var port = chrome.runtime.connect();
window.addEventListener("message", function(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
}
}, false);
document.getElementById("theButton").addEventListener("click",
function() {
window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*");
}, false);
La pagina senza estensione, example.html, pubblica messaggi su se stessa. Questo messaggio viene intercettato e ispezionato dallo script di contenuti, quindi pubblicato nel processo di estensione. In questo modo, la pagina stabilisce una linea di comunicazione con il processo di estensione. È possibile fare il contrario con mezzi simili.
Rafforza la tua sicurezza
Sebbene i mondi isolati forniscano un livello di protezione, l'utilizzo di script di contenuti può creare vulnerabilità in un'estensione e nella pagina web. Se lo script dei contenuti riceve contenuti da un sito web separato, ad esempio effettuando una XMLHttpRequest, fai attenzione a filtrare i contenuti cross-site scripting prima di inserirli. Comunica solo tramite HTTPS per evitare attacchi "man-in-the-middle".
Assicurati di filtrare le pagine web dannose. Ad esempio, i seguenti pattern sono pericolosi:
var data = document.getElementById("json-data")
// WARNING! Might be evaluating an evil script!
var parsed = eval("(" + data + ")")
var elmt_id = ...
// WARNING! elmt_id might be "); ... evil script ... //"!
window.setTimeout("animate(" + elmt_id + ")", 200);
Preferisci invece API più sicure che non eseguono script:
var data = document.getElementById("json-data")
// JSON.parse does not evaluate the attacker's scripts.
var parsed = JSON.parse(data);
var elmt_id = ...
// The closure form of setTimeout does not evaluate scripts.
window.setTimeout(function() {
animate(elmt_id);
}, 200);