Script di contenuti

Gli script di contenuti sono file che vengono eseguiti nel contesto delle pagine web. Utilizzando il Document Object Model (DOM) standard, sono in grado di leggere i dettagli delle pagine web visitate dal browser, apportarvi modifiche e passare informazioni all'estensione principale.

Informazioni sulle funzionalità degli script di contenuti

Gli script di contenuti 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 di Chrome:

Gli script di contenuti non consentono di accedere direttamente ad altre API.

Lavorare in mondi isolati

Gli script di contenuti risiedono 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 all'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>

L'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);

Alla pressione del pulsante, vengono visualizzati entrambi gli avvisi.

I mondi isolati non consentono agli script di contenuti, all'estensione e alla pagina web di accedere alle variabili o alle funzioni create dagli altri. Inoltre, gli script di contenuti possono attivare funzionalità che non devono essere accessibili alla pagina web.

Inserisci script

Gli script di contenuti possono essere inseriti in modo programmatico o dichiarativa.

Inserisci in modo programmatico

Utilizza l'inserimento programmatico per gli script di contenuti che devono essere eseguiti in occasioni specifiche.

Per inserire uno script di contenuti programmatici, fornisci l'autorizzazione activeTab nel file manifest. Questo ruolo concede l'accesso sicuro all'host del sito attivo e l'accesso temporaneo all'autorizzazione Schede, consentendo l'esecuzione dello script dei contenuti 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 di contenuti che devono essere eseguiti automaticamente sulle pagine specificate.

Gli script inseriti in modo dichiarativo vengono registrati nel file manifest sotto il campo "content_scripts". Possono includere file JavaScript, file CSS o entrambi. Tutti gli script di contenuti eseguiti automaticamente 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 } array di stringhe Obbligatorio. Specifica le pagine in cui verrà inserito questo script di contenuti. Consulta Pattern di corrispondenza per ulteriori dettagli sulla sintassi di queste stringhe e Pattern di corrispondenza e glob per informazioni su come escludere gli URL.
css {: #css } array di stringhe Facoltativo. L'elenco di file CSS da inserire nelle pagine corrispondenti. Questi vengono inseriti nell'ordine in cui appaiono in questo array, prima che venga creato o visualizzato qualsiasi DOM per la pagina.
js {: #js } array di stringhe Facoltativo. L'elenco di file JavaScript da inserire nelle pagine corrispondenti. Questi vengono inseriti nell'ordine in cui appaiono in questo array.
match_about_blank {: #match_about_blank } boolean Facoltativo. Indica se lo script deve essere inserito in un frame about:blank in cui il frame principale o di apertura corrisponde a uno dei pattern dichiarati in matches. Il valore predefinito è false.

Escludi corrispondenze e glob

La corrispondenza della pagina specificata è personalizzabile includendo i seguenti campi nella registrazione del file manifest.

Nome Tipo Descrizione
exclude_matches {: #exclude_matches } array di stringhe Facoltativo. Sono escluse le pagine in cui questo script di contenuti verrebbe altrimenti inserito. Per ulteriori dettagli sulla sintassi di queste stringhe, consulta la sezione Pattern di corrispondenza.
include_globs {: #include_globs } array di stringhe Facoltativo. Applicato dopo il giorno matches per includere solo gli URL che corrispondono anche a questo glob. È destinata a emulare la parola chiave Greasemonkey @include.
exclude_globs {: #exclude_globs } array di stringhe Facoltativo. Applicato dopo il giorno matches per escludere gli URL che corrispondono a questo glob. È destinata a emulare la parola chiave @excludeGreasemonkey.

Lo script di contenuti verrà inserito in una pagina se il relativo URL corrisponde a un pattern matches e a un pattern include_globs, purché l'URL non corrisponda anche a un pattern exclude_matches o exclude_globs.

Poiché la proprietà matches è obbligatoria, è possibile usare exclude_matches, include_globs e exclude_globs soltanto per limitare le pagine interessate.

La seguente estensione avrebbe inserito 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à del globo seguono una sintassi diversa e più flessibile rispetto ai pattern di corrispondenza. Le stringhe glob accettabili sono gli URL che possono contenere asterischi e punti interrogativi con caratteri jolly. L'asterisco * corrisponde a qualsiasi stringa di qualsiasi lunghezza, inclusa la stringa vuota, mentre il punto interrogativo ? corrisponde a qualsiasi carattere singolo.

Ad esempio, il glob http:// ??? .example.com/foo/ * corrisponde a uno dei seguenti elementi:

  • http:// www .example.com/foo /bar
  • http:// l'indirizzo .example.com/foo /

Tuttavia, non corrisponde a quanto segue:

  • http:// mio .example.com/foo/bar
  • http:// example .com/foo/
  • http://www.example.com/foo

Questa estensione inserirà 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 inserirà lo script di 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"]
    }
  ],
  ...
}

È possibile includere uno, tutti o alcuni di questi elementi per raggiungere l'ambito corretto.

{
  "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 di file JavaScript nella pagina web viene 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" ogni volta che è possibile.

Il browser sceglie un orario in cui inserire gli script tra il giorno "document_end" e quello immediatamente 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 della pagina.

Gli script di contenuti in esecuzione alle ore "document_idle" non richiedono l'ascolto dell'evento window.onload; ne viene garantito l'esecuzione al termine del DOM. Se uno script deve sicuramente essere eseguito dopo il giorno window.onload, l'estensione può controllare se onload è già stato attivato utilizzando la proprietà document.readyState.
document_start {: #document_start } stringa Gli script vengono inseriti dopo qualsiasi file da css, ma prima che venga creato un altro DOM o prima che venga eseguito qualsiasi altro script.
document_end {: #document_end } stringa Gli script vengono inseriti immediatamente dopo il completamento del DOM, ma prima del caricamento di sottorisorse come immagini e frame.

Specifica frame

Il campo "all_frames" consente all'estensione di specificare se i file JavaScript e CSS devono essere inseriti in tutti i frame corrispondenti ai requisiti per gli URL specificati o solo nel frame più alto 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 } boolean Facoltativo. Il valore predefinito è false, che indica che viene abbinato solo il frame superiore.

Se specificato true, verrà inserito in tutti i frame, anche se non è quello più in alto nella scheda. Ogni frame viene controllato in modo indipendente per verificare i requisiti dell'URL e non verrà inserito nei frame secondari se non vengono soddisfatti i requisiti dell'URL.

Comunicazione con la pagina di incorporamento

Sebbene gli ambienti di esecuzione degli script di contenuti e le 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.

Puoi ottenere un esempio 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 i messaggi. Questo messaggio viene intercettato e controllato dallo script di contenuti e quindi pubblicato nel processo di estensione. In questo modo, la pagina stabilisce una linea di comunicazione per il processo di estensione. Il contrario è possibile con mezzi simili.

Rafforza la tua sicurezza

Mentre i mondi isolati forniscono 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 una richiesta XMLHttpRequest, presta attenzione a filtrare gli attacchi di cross-site scripting di contenuti prima di inserirli. Comunicare 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 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);