Script di contenuti

Gli script di contenuti sono file che vengono eseguiti nel contesto delle pagine web. Utilizzando il modello Documento modello a oggetti (DOM), sono in grado di leggere i dettagli delle pagine web visitate dal browser, modifiche e passare le informazioni all'estensione principale.

Comprendere le funzionalità degli script di contenuti

Gli script di contenuti possono accedere alle API di Chrome utilizzate dall'estensione principale tramite lo scambio di messaggi con l'estensione. Possono anche accedere all'URL del file di un'estensione con chrome.runtime.getURL() e utilizza 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 contenuti non sono in grado di accedere direttamente ad altre API.

Lavorare in mondi isolati

I script di contenuti risiedono in un mondo isolato e consentono a un copione di apportare modifiche ambiente JavaScript senza essere in conflitto con la pagina o con gli script di contenuti aggiuntivi.

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 premi il pulsante, vengono visualizzati entrambi gli avvisi.

I mondi isolati non consentono agli script di contenuti, all'estensione e alla pagina web di accedere a qualsiasi variabili o funzioni create dagli altri. In questo modo, inoltre, gli script di contenuti possono attivare funzionalità che non dovrebbero essere accessibili alla pagina web.

Inietta script

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

Inserisci in modo programmatico

Usa 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. Questa operazione concede accesso sicuro all'host del sito attivo e accesso temporaneo alle schede abilitando l'esecuzione dello script dei contenuti nella scheda attiva corrente senza specificare 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"'
      });
    }
  });

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'inserimento dichiarativo per gli script di contenuti che devono essere eseguiti automaticamente su 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 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 } array di stringhe 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 pattern glob per informazioni su come escludere gli URL.
css {: #css } array di stringhe Facoltativo. L'elenco di file CSS da inserire 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 di file JavaScript da inserire nelle pagine corrispondenti. che 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.

Escludi corrispondenze e glob

La corrispondenza delle pagine specificate è personalizzabile includendo i seguenti campi nel file manifest registrazione.

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 il giorno matches per includere solo gli URL corrispondenti 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 corrispondenti a questo glob. Ha lo scopo di 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, 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 avrebbe inserito lo script dei 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 glob http:// ??? .example.com/foo/ * corrisponde a una delle seguenti corrispondenze:

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

Tuttavia, non corrisponde a quanto segue:

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

Questa estensione inietterebbe 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 inserisce lo script dei contenuti in http:// history .nytimes.com e http://.nytimes.com/ history ma non 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

Quando i file JavaScript vengono inseriti nella pagina web è controllato dal campo run_at. La il campo prefferito 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 Preferito. Utilizza "document_idle" quando possibile.

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

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 su se stessa. Questo messaggio è stato intercettato e venga esaminata dallo script dei contenuti e pubblicata nel processo di estensione. In questo modo, la pagina stabilisce una linea di comunicazione con il processo di estensione. L'inversione è possibile grazie alla con mezzi simili.

Rafforza la tua sicurezza

Mentre i mondi isolati forniscono un livello di protezione, l'uso degli script di contenuti può creare le 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. Comunicare solo tramite HTTPS per evitare Attacchi &quot;man-in-the-middle&quot;.

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