Inhaltsskripte sind Dateien, die im Kontext von Webseiten ausgeführt werden. Das standardmäßige Document Objektmodell (DOM) können sie Details zu den vom Browser besuchten Webseiten lesen, und Informationen an die übergeordnete Erweiterung übergeben.
Funktionen des Content-Scripts
Inhaltsskripte können direkt auf die folgenden Erweiterungs-APIs zugreifen:
dom
i18n
storage
runtime.connect()
runtime.getManifest()
runtime.getURL()
runtime.id
runtime.onConnect
runtime.onMessage
runtime.sendMessage()
Inhaltsskripte können nicht direkt auf andere APIs zugreifen. Nutzer können aber indirekt darauf zugreifen, indem sie Nachrichten mit anderen Teilen der Erweiterung austauschen.
Sie können auch über ein Content-Skript auf andere Dateien in Ihrer Erweiterung zugreifen, indem Sie
APIs wie fetch()
Dazu müssen Sie sie als
über das Web zugängliche Ressourcen. Beachten Sie, dass die Ressourcen dadurch auch für alle
eigene oder Drittanbieter-Skripts,
die auf derselben Website ausgeführt werden.
In isolierten Welten arbeiten
Inhaltsskripte befinden sich in einer isolierten Welt, sodass ein Inhaltsskript Änderungen an seinem JavaScript-Umgebung ohne Konflikte mit der Seite oder anderen Erweiterungen Inhaltsskripte.
Eine Erweiterung kann auf einer Webseite mit Code ausgeführt werden, der dem folgenden Beispiel ähnelt.
webPage.html
<html>
<button id="mybutton">click me</button>
<script>
var greeting = "hello, ";
var button = document.getElementById("mybutton");
button.person_name = "Bob";
button.addEventListener(
"click", () => alert(greeting + button.person_name + "."), false);
</script>
</html>
Diese Erweiterung könnte das folgende Inhaltsskript mithilfe einer der in den Abschnitt Scripts einfügen.
content-script.js
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener(
"click", () => alert(greeting + button.person_name + "."), false);
Durch diese Änderung werden beide Benachrichtigungen nacheinander angezeigt, wenn auf die Schaltfläche geklickt wird.
Skripts einfügen
Content-Skripts können statisch, deklariert dynamisch oder programmatisch eingeschleust werden.
Mit statischen Deklarationen einfügen
Verwenden Sie Deklarationen von statischen Inhalten in der Datei „manifest.json“ für Skripts, die automatisch auf einer bekannten Gruppe von Seiten ausgeführt werden.
Statisch deklarierte Skripts werden im Manifest unter dem Schlüssel "content_scripts"
registriert.
Sie können JavaScript-Dateien, CSS-Dateien oder beides enthalten. In allen automatisch ausgeführten Content-Skripts muss angegeben werden,
Übereinstimmungsmuster.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"css": ["my-styles.css"],
"js": ["content-script.js"]
}
],
...
}
Name | Typ | Beschreibung |
---|---|---|
matches |
String-Array | Erforderlich. Gibt an, in welche Seiten dieses Inhaltsskript eingeschleust wird. Weitere Informationen zur Syntax dieser Strings finden Sie unter Übereinstimmungsmuster. und unter Übereinstimmungsmuster und Globs finden Sie Informationen dazu, wie Sie URLs. |
css |
String-Array | Optional. Die Liste der CSS-Dateien, die in übereinstimmende Seiten eingeschleust werden sollen. Dies sind in der Reihenfolge injiziert, in der sie in diesem Array erscheinen, bevor ein DOM erstellt oder angezeigt wird für die Seite. |
js |
|
Optional. Die Liste der JavaScript-Dateien, die in übereinstimmende Seiten eingeschleust werden sollen. Dateien in der Reihenfolge eingeschleust, in der sie in diesem Array erscheinen. Jeder String in dieser Liste muss relativen Pfad zu einer Ressource im Stammverzeichnis der Erweiterung. Führende Schrägstriche (/) sind automatisch zugeschnitten. |
run_at |
RunAt | Optional. Gibt an, wann das Skript in die Seite eingeschleust werden soll. Standardeinstellung:
document_idle |
match_about_blank |
boolean | Optional. Legt fest, ob das Skript in einen about:blank -Frame eingefügt werden soll
wobei der übergeordnete oder Opener-Frame mit einem der in
matches . Die Standardeinstellung ist "false". |
match_origin_as_fallback |
boolean |
Optional. Ob das Skript Frames einschleusen soll, die
die von einem übereinstimmenden Ursprung erstellt wurden, deren URL oder Ursprung aber nicht direkt
mit dem Muster übereinstimmen. Dazu gehören auch Frames mit unterschiedlichen Schemas, z. B.
about: , data: , blob: und
filesystem: . Siehe auch
Injection in verwandten Frames
|
world |
ExecutionWorld |
Optional. Die JavaScript-Welt, in der ein Script ausgeführt werden soll. Die Standardeinstellung ist ISOLATED . Siehe auch
Arbeiten Sie in isolierten Welten.
|
Mit dynamischen Deklarationen einfügen
Skripts für dynamische Inhalte sind nützlich, wenn die Abgleichsmuster für Inhaltsskripte nicht bekannt sind oder wenn Inhaltsskripte nicht immer auf bekannten Hosts eingeschleust werden sollten.
Seit der Einführung von Chrome 96 ähneln dynamische Deklarationen statischen
Deklarationen. Das Content-Script-Objekt ist jedoch mithilfe von
im chrome.scripting
-Namespace statt in
manifest.json. Mit der Scripting API können auch
Entwickler von Erweiterungen
in:
- Registrieren Sie Inhaltsskripte.
- Liste der registrierten Inhaltsskripte abrufen
- Aktualisieren Sie die Liste der registrierten Inhaltsskripte.
- Entfernen Sie registrierte Inhaltsskripte.
Wie statische Deklarationen können auch dynamische Deklarationen JavaScript-Dateien, CSS-Dateien oder beides enthalten.
service-worker.js
chrome.scripting
.registerContentScripts([{
id: "session-script",
js: ["content.js"],
persistAcrossSessions: false,
matches: ["*://example.com/*"],
runAt: "document_start",
}])
.then(() => console.log("registration complete"))
.catch((err) => console.warn("unexpected error", err))
service-worker.js
chrome.scripting
.updateContentScripts([{
id: "session-script",
excludeMatches: ["*://admin.example.com/*"],
}])
.then(() => console.log("registration updated"));
service-worker.js
chrome.scripting
.getRegisteredContentScripts()
.then(scripts => console.log("registered content scripts", scripts));
service-worker.js
chrome.scripting
.unregisterContentScripts({ ids: ["session-script"] })
.then(() => console.log("un-registration complete"));
Programmatisch einfügen
Verwenden Sie die programmatische Injektion für Content-Skripts, die als Reaktion auf Ereignisse oder bei bestimmten für verschiedene Anlässe.
Um ein Inhaltsskript programmatisch einzufügen, benötigt Ihre Erweiterung Hostberechtigungen für
der Seite, auf der Skripte
eingeschleust werden sollen. Hostberechtigungen können entweder
über das Manifest Ihrer Erweiterung oder vorübergehend über "activeTab"
anfordern.
Im Folgenden finden Sie verschiedene Versionen einer aktiven tab-basierten Erweiterung.
manifest.json:
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
Inhaltsskripte können als Dateien eingeschleust werden.
content-script.js
document.body.style.backgroundColor = "orange";
service-worker.js:
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"]
});
});
Oder ein Funktionstext kann eingeschleust und als Inhaltsskript ausgeführt werden.
service-worker.js:
function injectedFunction() {
document.body.style.backgroundColor = "orange";
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
});
});
Beachten Sie, dass die injizierte Funktion eine Kopie der Funktion ist, auf die im
chrome.scripting.executeScript()
-Aufruf, nicht die ursprüngliche Funktion selbst. Daher ist der Wert der Funktion
Körper muss in sich geschlossen sein; führen Verweise auf Variablen außerhalb der Funktion dazu, dass der Inhalt
zum Auslösen einer ReferenceError
.
Beim Einschleusen als Funktion können Sie auch Argumente an die Funktion übergeben.
service-worker.js
function injectedFunction(color) {
document.body.style.backgroundColor = color;
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
args : [ "orange" ],
});
});
Übereinstimmungen und globs ausschließen
Nehmen Sie die folgenden Felder in ein deklaratives Feld auf, um den Seitenabgleich anzupassen: Registrierung.
Name | Typ | Beschreibung |
---|---|---|
exclude_matches |
String-Array | Optional. Schließt Seiten aus, auf die dieses Inhaltsskript andernfalls eingeschleust würde in die Sie hineinversetzen können. Weitere Informationen zur Syntax von für diese Zeichenfolgen. |
include_globs |
String-Array | Optional. Wird nach dem matches angewendet, um nur die URLs einzuschließen, die auch
mit diesem Glob übereinstimmen. Damit soll @include emuliert werden.
Greasemonkey-Keyword. |
exclude_globs |
Array von String | Optional. Wird nach dem matches angewendet, um entsprechende URLs auszuschließen
glob. Soll die @exclude emulieren
Greasemonkey-Keyword. |
Das Content-Skript wird in eine Seite eingefügt, wenn die beiden folgenden Bedingungen zutreffen:
- Seine URL stimmt mit jedem
matches
-Muster und jedeminclude_globs
-Muster überein. - Die URL stimmt auch nicht mit dem Muster
exclude_matches
oderexclude_globs
überein. Da das Attributmatches
erforderlich ist,exclude_matches
,include_globs
undexclude_globs
lässt sich lediglich einschränken, welche Seiten betroffen sind.
Die folgende Erweiterung fügt das Inhaltsskript in https://www.nytimes.com/health
ein
aber nicht in https://www.nytimes.com/business
.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.nytimes.com/*" ],
excludeMatches : [ "*://*/*business*" ],
js : [ "contentScript.js" ],
}]);
Glob-Eigenschaften folgen einer anderen, flexibleren Syntax als Übereinstimmungsmuster. Akzeptabler Glob
Strings sind URLs, die „Platzhalter“ enthalten können Sternchen und Fragezeichen. Das Sternchen (*
)
entspricht einem beliebigen String beliebiger Länge, einschließlich des leeren Strings, während das Fragezeichen (?
) mit dem
aus einem beliebigen Zeichen.
Der glob https://???.example.com/foo/\*
stimmt beispielsweise mit einem der folgenden Elemente überein:
https://www.example.com/foo/bar
https://the.example.com/foo/
Folgendes stimmt jedoch nicht überein:
https://my.example.com/foo/bar
https://example.com/foo/
https://www.example.com/foo
Diese Erweiterung fügt das Inhaltsskript in https://www.nytimes.com/arts/index.html
und
https://www.nytimes.com/jobs/index.htm*
, aber nicht in
https://www.nytimes.com/sports/index.html
:
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
Diese Erweiterung fügt das Inhaltsskript in https://history.nytimes.com
und
https://.nytimes.com/history
, aber nicht in https://science.nytimes.com
oder
https://www.nytimes.com/science
:
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Sie können eine, alle oder einige davon einschließen, um den richtigen Umfang zu erreichen.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Laufzeit
Das Feld run_at
steuert, wann JavaScript-Dateien in die Webseite eingeschleust werden. Die bevorzugten und
Der Standardwert ist "document_idle"
. Unter dem RunAt-Typ finden Sie
Werte.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.nytimes.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
Name | Typ | Beschreibung |
---|---|---|
document_idle |
String | Bevorzugt. Verwenden Sie nach Möglichkeit "document_idle" .Den Browser wählt einen Zeitpunkt für das Einfügen von Skripts zwischen "document_end" und sofort nach
window.onload
ausgelöst wird. Der genaue Zeitpunkt der Einschleusung hängt davon ab, wie komplex das Dokument ist
wie lange es dauert, bis sie geladen ist, und ist für die Seitenladegeschwindigkeit optimiert.Content-Scripts die um "document_idle" laufen, müssen nicht
window.onload ausführen, werden sie garantiert nach Abschluss des DOMs ausgeführt. Wenn ein
Das Skript muss unbedingt nach window.onload ausgeführt werden. Die Erweiterung kann prüfen,
onload wurde bereits mithilfe von document.readyState ausgelöst
Property. |
document_start |
String | Skripts werden nach allen Dateien aus css eingeschleust, aber vor jedem anderen DOM
oder ein anderes Skript ausgeführt wird. |
document_end |
String | Skripts werden unmittelbar nach Abschluss des DOMs eingeschleust, aber vor Unterressourcen wie Bilder und Frames geladen wurden. |
Frames angeben
Im Feld "all_frames"
kann die Erweiterung angeben, ob JavaScript- und CSS-Dateien
in alle Frames, die den angegebenen URL-Anforderungen entsprechen, oder nur in den obersten Frame einer
.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id: "test",
matches : [ "https://*.nytimes.com/*" ],
allFrames : true,
js : [ "contentScript.js" ],
}]);
Name | Typ | Beschreibung |
---|---|---|
all_frames |
boolean | Optional. Die Standardeinstellung ist false . Das bedeutet, dass nur der oberste Frame
stimmt überein.Wenn true angegeben ist, werden alle Frames eingefügt, auch wenn der
ist nicht der oberste Frame in der Registerkarte. Jeder Frame wird separat auf URL geprüft.
Anforderungen. Es wird nicht in untergeordnete Frames eingeschleust, wenn die URL-Anforderungen nicht erfüllt sind. |
In verwandte Frames einfügen
Erweiterungen können Skripts in Frames ausführen, die mit einer übereinstimmenden Frame, aber sie stimmen nicht überein. Ein gängiges Szenario, in dem dies für Frames mit URLs, die von einem übereinstimmenden Frame erstellt wurden, deren URLs jedoch nicht mit den im Skript angegebenen Mustern übereinstimmen.
Dies ist der Fall, wenn eine Erweiterung Frames mit URLs einfügen möchte,
haben die Schemas about:
, data:
, blob:
und filesystem:
. In diesen Fällen
Die URL stimmt nicht mit dem Muster des Content-Skripts überein (und im Fall von about:
und
data:
, fügen Sie nicht einmal die übergeordnete URL oder den Ursprung in die URL ein.
überhaupt, wie in about:blank
oder data:text/html,<html>Hello, World!</html>
).
Diese Frames können jedoch immer noch mit dem erstellenden Frame verknüpft werden.
Um in diese Frames einzuschleusen, können Erweiterungen den Parameter
"match_origin_as_fallback"
in einer Content Script-Spezifikation im
Manifests.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.google.com/*"],
"match_origin_as_fallback": true,
"js": ["contentScript.js"]
}
],
...
}
Wenn dieses Flag angegeben und auf true
gesetzt ist, prüft Chrome den Ursprung des
Initiator des Frames, um zu bestimmen, ob der Frame übereinstimmt, und nicht
die URL des Frames selbst. Beachten Sie, dass sich dieser Wert auch vom
Ursprung des Ziel-Frames (z.B. data:
URLs haben keinen Ursprung.
Der Initiator des Frames ist der Frame, der das Ziel erstellt oder darauf navigiert hat. Frame. Normalerweise ist dies der direkte übergeordnete Punkt oder die Einleitung, aber nicht unbedingt (wie bei wenn ein Frame in einem iFrame innerhalb eines iFrames navigiert.
Da dabei der origin-Wert des Initiator-Frames verglichen wird,
von diesem Ursprung aus auf jedem Pfad möglich sein. Um dies zu verdeutlichen,
erfordert alle mit "match_origin_as_fallback"
angegebenen Inhaltsskripte
auf true
gesetzt, um auch den Pfad *
anzugeben.
Wenn sowohl "match_origin_as_fallback"
als auch "match_about_blank"
angegeben sind,
"match_origin_as_fallback"
hat Priorität.
Kommunikation mit der Einbettungsseite
Obwohl die Ausführungsumgebungen von Inhaltsskripten und die Seiten, auf denen sie gehostet werden, isoliert sind teilen sie Zugriff auf das DOM der Seite. Wenn die Seite mit dem Content-Skript oder mit der Erweiterung über das Content-Skript erstellt werden, muss es dies über das freigegebene DOM tun.
Ein Beispiel hierfür ist mit window.postMessage()
:
content-script.js
var port = chrome.runtime.connect();
window.addEventListener("message", (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);
example.js
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
Auf der Seite ohne Erweiterung (beispiel.html) werden Nachrichten an sich selbst gesendet. Diese Nachricht wird abgefangen und vom Content-Skript überprüft und dann an den Erweiterungsprozess gesendet. So kann die Seite baut eine Kommunikationsverbindung mit dem Erweiterungsprozess auf. Umgekehrt ist es möglich, auf ähnliche Weise ausdrücken.
Auf Erweiterungsdateien zugreifen
Um aus einem Content-Skript auf eine Erweiterungsdatei zuzugreifen, können Sie Folgendes aufrufen:
chrome.runtime.getURL()
, um die absolute URL des Erweiterungs-Assets zu erhalten, wie im folgenden Beispiel (content.js
) gezeigt:
content-script.js
let image = chrome.runtime.getURL("images/my_image.png")
Wenn Sie Schriftarten oder Bilder in einer CSS-Datei verwenden möchten, können Sie mit @@extension_id
eine URL erstellen, wie im folgenden Beispiel (content.css
) gezeigt:
content.css
body {
background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');
}
@font-face {
font-family: 'Stint Ultra Expanded';
font-style: normal;
font-weight: 400;
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Stint Ultra Expanded.woff') format('woff');
}
Alle Assets müssen in der Datei manifest.json
als über das Internet zugängliche Ressourcen deklariert werden:
manifest.json
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Schutzfunktionen
Isolierte Welten bieten zwar eine Schutzebene, aber durch die Verwendung von Content-Skripts
Sicherheitslücken in einer Erweiterung und auf der Webseite. Wenn das Content-Skript Content von einem
separater Website zu erstellen, z. B. durch Aufrufen von fetch()
, achten Sie darauf,
Cross-Site-Scripting-Angriffe, bevor sie eingeschleust werden. Kommunizieren Sie nur über HTTPS,
um "man-in-the-middle" zu vermeiden.
Filtern Sie auch nach schädlichen Webseiten. Zum Beispiel sind die folgenden Muster gefährlich und in Manifest V3 nicht zulässig:
content-script.js
const data = document.getElementById("json-data"); // WARNING! Might be evaluating an evil script! const parsed = eval("(" + data + ")");
content-script.js
const elmt_id = ... // WARNING! elmt_id might be '); ... evil script ... //'! window.setTimeout("animate(" + elmt_id + ")", 200);
Bevorzugen Sie stattdessen sicherere APIs, die keine Skripts ausführen:
content-script.js
const data = document.getElementById("json-data") // JSON.parse does not evaluate the attacker's scripts. const parsed = JSON.parse(data);
content-script.js
const elmt_id = ... // The closure form of setTimeout does not evaluate scripts. window.setTimeout(() => animate(elmt_id), 200);