Skrypty treści to pliki, które są uruchamiane w kontekście stron internetowych. Za pomocą standardowego obiektowego modelu dokumentu (DOM) mogą odczytywać szczegóły stron odwiedzanych przez przeglądarkę, wprowadzać na nich zmiany i przekazywać informacje do rozszerzenia nadrzędnego.
Informacje o możliwościach skryptów treści
Skrypty treści mogą uzyskiwać dostęp do interfejsów API Chrome używanych przez rozszerzenie nadrzędne, wymieniając wiadomości z rozszerzeniem. Mogą też uzyskać dostęp do adresu URL pliku rozszerzenia za pomocą chrome.runtime.getURL()
i korzystać z tego samego wyniku tak samo jak w innych adresach URL.
// Code for displaying EXTENSION_DIR/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Dodatkowo skrypt treści ma bezpośredni dostęp do tych interfejsów API Chrome:
Skrypty treści nie mają bezpośredniego dostępu do innych interfejsów API.
Praca w odizolowanym świecie
Skrypty treści działają w izolowanym świecie, co umożliwia skryptowi treści wprowadzanie zmian w środowisku JavaScriptu bez konfliktów ze stroną lub dodatkowymi skryptami treści.
Rozszerzenie może działać na stronie internetowej z kodem podobnym do tego w przykładzie poniżej.
<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>
To rozszerzenie może wstrzyknąć poniższy skrypt treści.
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
Po naciśnięciu przycisku pojawią się oba alerty.
Odizolowane światy nie zezwalają skryptom treści, rozszerzeniu ani stronie internetowej na dostęp do żadnych zmiennych lub funkcji tworzonych przez inne strony. Umożliwia to również skryptom treści włączenie funkcji, które nie powinny być dostępne na stronie internetowej.
Wstrzyknij skrypty
Skrypty treści można wstrzykiwać programowo lub deklaratywnie.
Wstawiaj automatycznie
Używaj wstrzykiwania automatycznego w przypadku skryptów treści, które mają być uruchamiane w określonych sytuacjach.
Aby wstrzyknąć skrypt treści zautomatyzowanej, podaj w pliku manifestu uprawnienie activeTab. Daje to bezpieczny dostęp do hosta aktywnej witryny i tymczasowy dostęp do uprawnień kart, co umożliwia uruchamianie skryptu zawartości w bieżącej aktywnej karcie bez określania uprawnień z innych domen.
{
"name": "My extension",
...
"permissions": [
"activeTab"
],
...
}
Skrypty treści można wstrzykiwać jako kod.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "changeColor"){
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="orange"'
});
}
});
Można też wstrzykiwać cały plik.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "runContentScript"){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
}
});
Wstrzykiwać deklaratywnie
Użyj wstrzykiwania deklaratywnego w przypadku skryptów treści, które powinny być uruchamiane automatycznie na określonych stronach.
Skrypty wstrzyknięte deklaratywnie są zarejestrowane w pliku manifestu w polu "content_scripts"
.
Mogą one obejmować pliki JavaScript, pliki CSS lub oba te elementy. Wszystkie automatycznie uruchamiane skrypty treści muszą określać wzorce dopasowania.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"css": ["myStyles.css"],
"js": ["contentScript.js"]
}
],
...
}
Nazwa | Typ | Opis |
---|---|---|
matches {: #matches } |
Wymagane. Określa, na których stronach będzie wstrzyknięty ten skrypt treści. Więcej informacji o składni tych ciągów tekstowych znajdziesz w sekcji Wzorce dopasowania, a w sekcji Wzorce dopasowania i obiektów glob dowiesz się, jak wykluczać adresy URL. | |
css {: #css } |
Opcjonalne. Lista plików CSS, które mają zostać wstawione na pasujących stronach. Są one wstrzykiwane w kolejności, w jakiej pojawiają się w tej tablicy, przed utworzeniem lub wyświetleniem DOM dla strony. | |
js {: #js } |
Opcjonalne. Lista plików JavaScript, które mają zostać wstawione na pasujących stronach. Są one wstrzykiwane w kolejności, w jakiej występują w tej tablicy. | |
match_about_blank {: #match_about_blank } |
boolean | Opcjonalne. Określa, czy skrypt powinien wstrzyknąć w ramkę about:blank , w której ramka nadrzędna lub otwierająca odpowiada jednemu z wzorców zadeklarowanych w zasadzie matches . Domyślna wartość to false . |
Wyklucz dopasowania i obiekty globs
Określone dopasowanie stron można dostosować, uwzględniając w rejestracji manifestu poniższe pola.
Nazwa | Typ | Opis |
---|---|---|
exclude_matches {: #excl_matches } |
Opcjonalne. Wyklucza strony, do których w innym przypadku zostałby wstrzyknięty ten skrypt treści. Więcej informacji o składni tych ciągów tekstowych znajdziesz w sekcji Wzorce dopasowania. | |
include_globs {: #include_globs } |
Opcjonalne. Stosowane po matches , aby uwzględniać tylko te adresy URL, które również pasują do tego wzorca glob. Ma emulować słowo kluczowe @include Greasemonkey. |
|
exclude_globs {: #excl_globs } |
Opcjonalne. Stosowane po matches w celu wykluczania adresów URL pasujących do tego wzorca glob. Ma emulować słowo kluczowe @exclude Greasemonkey. |
Skrypt treści zostanie wstawiony na stronie, jeśli jej adres URL pasuje do dowolnego wzorca matches
i dowolnego wzorca include_globs
, o ile adres URL nie jest też zgodny ze wzorcem exclude_matches
ani exclude_globs
.
Właściwość matches
jest wymagana, więc za pomocą właściwości exclude_matches
, include_globs
i exclude_globs
można tylko ograniczyć zakres stron, których dotyczy problem.
To rozszerzenie wstrzykuje skrypt treści na stronie http://www.nytimes.com/ health, ale nie na stronie http://www.nytimes.com/ business .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
Właściwości kuli ziemskiej mają inną, bardziej elastyczną składnię niż wzorce dopasowania. Dopuszczalne ciągi znaków glob to adresy URL, które mogą zawierać symbole wieloznaczne i znaki zapytania. Gwiazdka * pasuje do dowolnego ciągu o dowolnej długości, w tym do pustego ciągu znaków, a do znaku zapytania ? pasuje do dowolnego pojedynczego znaku.
Na przykład adres glob http:// ??? .example.com/foo/ * odpowiada dowolnym z tych elementów:
- http:// www .example.com/foo /bar
- http:// .example.com/foo /
Nie jest on jednak zgodny z tymi zasadami:
- http:// mój .example.com/foo/bar
- http:// example .com/foo/
- http://www.example.com/foo
To rozszerzenie wstrzykuje skrypt treści do stron http:/www.nytimes.com/ arts /index.html i http://www.nytimes.com/ jobs /index.html, ale nie do witryny http://www.nytimes.com/ sports /index.html.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
Spowoduje to wstawienie skryptu dotyczącego treści do http:// historii .nytimes.com czy http://.nytimes.com/ historii, ale nie do http:// science .nytimes.com czy http://www.nytimes.com/ science .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Aby uzyskać prawidłowy zakres, można uwzględnić jedną, wszystkie lub niektóre z nich.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Czas trwania
Umieszczanie plików JavaScript na stronie internetowej jest kontrolowane przez pole run_at
. Wybrane i domyślne pole to "document_idle"
, ale w razie potrzeby można je też określić jako "document_start"
lub "document_end"
.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
Nazwa | Typ | Opis |
---|---|---|
document_idle {: #document_idle } |
ciąg znaków | Preferowana. Gdy tylko jest to możliwe, używaj metody "document_idle" .Przeglądarka wybiera czas wstrzyknięcia skryptów między "document_end" a bezpośrednio po uruchomieniu zdarzenia windowonload . Dokładny moment wstrzyknięcia zależy od tego, jak złożony jest dokument i jak długo trwa jego wczytywanie. Jest zoptymalizowany pod kątem szybkości wczytywania strony.Skrypty treści działające w "document_idle" nie muszą nasłuchiwać zdarzenia window.onload – gwarantowane jest uruchomienie po zakończeniu DOM. Jeśli skrypt musi zostać uruchomiony po window.onload , rozszerzenie może sprawdzić, czy został już uruchomiony tag onload , korzystając z właściwości document.readyState . |
document_start {: #document_start } |
ciąg znaków | Skrypty są wstrzykiwane po plikach z pliku css , ale przed utworzeniem jakiegokolwiek elementu DOM lub uruchomieniem jakiegokolwiek innego skryptu. |
document_end {: #document_end } |
ciąg znaków | Skrypty są wstrzykiwane bezpośrednio po zakończeniu DOM, ale przed załadowaniem zasobów podrzędnych, takich jak obrazy i ramki. |
Określ klatki
Pole "all_frames"
umożliwia rozszerzeniu określenie, czy pliki JavaScript i CSS mają być umieszczane we wszystkich ramkach pasujących do wymagań dotyczących adresu URL, czy tylko w ramce najwyższego poziomu na karcie.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
Nazwa | Typ | Opis |
---|---|---|
all_frames {: #all_frames } |
boolean | Opcjonalne. Wartość domyślna to false , co oznacza, że dopasowywana jest tylko górna klatka.Jeśli określisz wartość true , zostanie ona wstrzyknięta we wszystkich klatkach, nawet jeśli nie będzie to najwyższa ramka na karcie. Każda ramka jest sprawdzana niezależnie pod kątem wymagań dotyczących adresu URL. Jeśli te wymagania nie zostaną spełnione, nie będzie wstrzykiwana do ramek podrzędnych. |
Komunikacja ze stroną umieszczania
Mimo że środowiska wykonawcze skryptów treści i strony, na których je znajdują, są od siebie odizolowane, mają one dostęp do DOM strony. Jeśli strona chce komunikować się ze skryptem treści lub rozszerzeniem przez skrypt treści, musi to zrobić za pomocą współdzielonego modelu DOM.
Przykład można uzyskać za pomocą 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);
Strona bez rozszerzeń, example.html, publikuje wiadomości na siebie. Wiadomość jest przechwytywana i sprawdzana przez skrypt treści, a następnie publikowana w procesie rozszerzenia. W ten sposób strona nawiązuje komunikację z procesem rozszerzenia. W podobny sposób można zaradzić na odwrót.
Dbaj o bezpieczeństwo
Choć odizolowane światy stanowią warstwę ochrony, używanie skryptów związanych z treścią może skutkować lukami w zabezpieczeniach rozszerzenia i strony internetowej. Jeśli skrypt treści otrzymuje treści z innej witryny, na przykład tworząc żądanie XMLHttpRequest, przed wstrzyknięciem takiego skryptu musisz odfiltrować ataki typu cross-site scripting. Aby uniknąć ataków typu "man-in-the-middle", komunikuj się tylko przez HTTPS.
Pamiętaj, aby filtrować strony pod kątem złośliwych stron. Niebezpieczne są na przykład te wzorce:
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);
Zamiast tego wybierz bezpieczniejsze interfejsy API, które nie uruchamiają skryptów:
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);