Script di contenuti

Gli script dei contenuti sono file 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, apportare modifiche e passare informazioni all'estensione principale.

Informazioni sulle funzionalità degli script dei 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 per gli 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 di contenuti può accedere direttamente alle seguenti API di Chrome:

Gli script di contenuto non sono in grado di accedere direttamente ad altre API.

Lavorare in mondi isolati

Gli script di contenuti sono in un ambiente isolato, il che consente a uno script di contenuti di apportare modifiche al proprio ambiente JavaScript senza entrare in conflitto con la pagina o con altri script di contenuti.

Un'estensione può essere eseguita in una pagina web con 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 iniettare 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. Inoltre, consente agli script dei contenuti di attivare funzionalità che non devono essere accessibili alla pagina web.

Inietta script

Gli script di contenuti possono essere iniettati in modo programmatico o declarativo.

Eseguire l'iniezione in modo programmatico

Utilizza l'iniezione programmatica per gli script dei contenuti che devono essere eseguiti in occasioni specifiche.

Per iniettare uno script di contenuti programmatici, 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 tabs, consentendo allo script dei contenuti di essere eseguito nella scheda attiva corrente senza specificare le autorizzazioni cross-origin.

{
  "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"'
      });
    }
  });

In alternativa, è possibile iniettare un intero file.

chrome.runtime.onMessage.addListener(
  function(message, callback) {
    if (message == "runContentScript"){
      chrome.tabs.executeScript({
        file: 'contentScript.js'
      });
    }
  });

Esegui l'iniezione in modo dichiarativo

Utilizza l'iniezione dichiarativa per gli script dei contenuti che devono essere eseguiti automaticamente in pagine specifiche.

Gli script iniettati in modo dichiarativo vengono registrati nel file manifest nel campo "content_scripts". Possono includere file JavaScript, file CSS o entrambi. Tutti gli script di contenuti con 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 } array di stringhe Obbligatorio. Specifica le pagine in cui verrà inserito questo script dei contenuti. Per maggiori dettagli sulla sintassi di queste stringhe, consulta Pattern di corrispondenza e Pattern di corrispondenza e pattern glob per informazioni su come escludere gli URL.
css {: #css } array di stringhe Facoltativo. L'elenco dei file CSS da iniettare nelle pagine corrispondenti. Vengono inseriti nell'ordine in cui appaiono in questo array, prima che venga creato o visualizzato il DOM per la pagina.
js {: #js } array di stringhe Facoltativo. L'elenco dei file JavaScript da iniettare 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 principale o di apertura 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 } array di stringhe Facoltativo. Esclude le pagine in cui altrimenti verrebbe inserito questo script dei contenuti. Per ulteriori dettagli sulla sintassi di queste stringhe, consulta Pattern di corrispondenza.
include_globs {: #include_globs } array di stringhe Facoltativo. Applicato dopo matches per includere solo gli URL che corrispondono anche a questo pattern generico. Destinata a emulare la parola chiave Greasemonkey @include.
exclude_globs {: #exclude_globs } array di stringhe Facoltativo. Viene applicato dopo matches per escludere gli URL corrispondenti a questo pattern generico. Destinata a emulare la parola chiave @excludeGreasemonkey.

Lo script dei contenuti verrà inserito in una pagina se il relativo URL corrisponde a qualsiasi pattern matches e a qualsiasi include_globs, purché 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 inserisce 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 di 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 pattern generico http:// ??? .example.com/foo/ * corrisponde a uno dei seguenti:

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

Tuttavia, non corrisponde a quanto segue:

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

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

Tempo di esecuzione

Il momento in cui i file JavaScript vengono inseriti nella pagina web è controllato dal campo run_at. Il campo preferito e predefinito è "document_idle", ma se necessario può essere specificato anche come "document_start" o "document_end".

{
  "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", se possibile.

Il browser sceglie un momento per iniettare gli script tra "document_end" e immediatamente dopo l'attivazione dell'evento windowonload. Il momento esatto dell'iniezione 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 in "document_idle" non devono monitorare l'evento window.onload, poiché viene garantito che vengano eseguiti dopo il completamento 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 iniettati dopo i file di css, ma prima che venga creato qualsiasi altro DOM o eseguito qualsiasi altro script.
document_end {: #document_end } stringa Gli script vengono iniettati immediatamente dopo il completamento del DOM, ma prima del caricamento di 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 corrispondenti ai requisiti dell'URL specificato o solo nel frame più alto in 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 eseguito il matching solo con il frame superiore.

Se viene specificato true, l'elemento verrà inserito in tutti i frame, anche se non è il frame più alto della scheda. Ogni frame viene controllato in modo indipendente per verificare la presenza dei requisiti relativi agli URL e non verrà inserito nei frame secondari se questi requisiti non sono soddisfatti.

Comunicazione con la pagina di incorporamento

Sebbene gli ambienti di esecuzione degli script di contenuti e le pagine che li ospitano siano isolati tra loro, condividono l'accesso al DOM della pagina. Se la pagina vuole comunicare con lo script di contenuto o con l'estensione tramite lo script di contenuto, 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 non di estensione, example.html, pubblica messaggi a se stessa. Questo messaggio viene intercettato e controllato dallo script di contenuti, quindi inviato al processo di estensione. In questo modo, la pagina stabilisce una linea di comunicazione con il processo di estensione. L'operazione inversa è possibile tramite metodi 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 distinto, ad esempio effettuando un XMLHttpRequest, assicurati di filtrare gli attacchi di scripting cross-site sui contenuti prima di iniettarli. Comunica solo tramite HTTPS per evitare attacchi di tipo "man-in-the-middle".

Assicurati di filtrare per 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);