Skrip konten adalah file yang berjalan dalam konteks halaman web. Dengan menggunakan Document Object Model (DOM) standar, mereka dapat membaca detail halaman web yang dikunjungi browser, membuat perubahan padanya, dan meneruskan informasi ke ekstensi induknya.
Memahami kemampuan skrip konten
Skrip konten dapat mengakses API Chrome yang digunakan oleh ekstensi induknya dengan bertukar pesan
dengan ekstensi. Mereka juga dapat mengakses URL file ekstensi dengan
chrome.runtime.getURL() dan menggunakan hasilnya sama seperti URL lainnya.
// Code for displaying EXTENSION_DIR/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Selain itu, skrip konten dapat mengakses Chrome API berikut secara langsung:
Skrip konten tidak dapat mengakses API lain secara langsung.
Bekerja di dunia terisolasi
Skrip konten berada di dunia yang terisolasi, sehingga skrip konten dapat membuat perubahan pada lingkungan JavaScript-nya tanpa berkonflik dengan halaman atau skrip konten tambahan.
Ekstensi dapat berjalan di halaman web dengan kode yang mirip dengan contoh di bawah.
<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>
Ekstensi tersebut dapat menyuntikkan skrip konten berikut.
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
Kedua pemberitahuan akan muncul jika tombol ditekan.
Dunia terisolasi tidak mengizinkan skrip konten, ekstensi, dan halaman web untuk mengakses variabel atau fungsi yang dibuat oleh pihak lain. Hal ini juga memberi skrip konten kemampuan untuk mengaktifkan fungsi yang tidak boleh diakses oleh halaman web.
Menyisipkan skrip
Skrip Konten dapat disisipkan secara terprogram atau deklaratif.
Menyuntikkan secara terprogram
Gunakan penyisipan terprogram untuk skrip konten yang perlu dijalankan pada kesempatan tertentu.
Untuk menyuntikkan skrip konten terprogram, berikan izin activeTab dalam manifes. Hal ini memberikan akses aman ke host situs aktif dan akses sementara ke izin tab, sehingga memungkinkan skrip konten berjalan di tab aktif saat ini tanpa menentukan izin lintas origin.
{
"name": "My extension",
...
"permissions": [
"activeTab"
],
...
}
Skrip konten dapat dimasukkan sebagai kode.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "changeColor"){
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="orange"'
});
}
});
Atau, seluruh file dapat disisipkan.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "runContentScript"){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
}
});
Menyuntikkan secara deklaratif
Gunakan injeksi deklaratif untuk skrip konten yang harus dijalankan secara otomatis di halaman tertentu.
Skrip yang disuntikkan secara deklaratif didaftarkan dalam manifes di kolom "content_scripts".
File ini dapat mencakup file JavaScript, file CSS, atau keduanya. Semua skrip konten yang berjalan otomatis harus menentukan
pola kecocokan.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"css": ["myStyles.css"],
"js": ["contentScript.js"]
}
],
...
}
| Nama | Jenis | Deskripsi |
|---|---|---|
matches {: #matches } |
Wajib. Menentukan halaman tempat skrip konten ini akan disisipkan. Lihat Pola Pencocokan untuk mengetahui detail selengkapnya tentang sintaksis string ini dan Pola pencocokan dan glob untuk mengetahui informasi tentang cara mengecualikan URL. | |
css {: #css } |
Opsional. Daftar file CSS yang akan disisipkan ke halaman yang cocok. Ini disisipkan dalam urutan kemunculannya dalam array ini, sebelum DOM dibuat atau ditampilkan untuk halaman. | |
js {: #js } |
Opsional. Daftar file JavaScript yang akan disisipkan ke halaman yang cocok. Objek ini disisipkan sesuai urutannya dalam array ini. | |
match_about_blank {: #match_about_blank } |
boolean | Opsional. Apakah skrip harus disisipkan ke dalam frame about:blank tempat frame induk atau pembuka cocok dengan salah satu pola yang dideklarasikan di matches. Defaultnya adalah false. |
Mengecualikan kecocokan dan glob
Pencocokan halaman yang ditentukan dapat disesuaikan dengan menyertakan kolom berikut dalam pendaftaran manifes.
| Nama | Jenis | Deskripsi |
|---|---|---|
exclude_matches {: #exclude_matches } |
Opsional. Mengecualikan halaman yang seharusnya disisipkan skrip konten ini. Lihat Pola Pencocokan untuk mengetahui detail selengkapnya tentang sintaksis string ini. | |
include_globs {: #include_globs } |
Opsional. Diterapkan setelah matches untuk menyertakan hanya URL yang juga cocok dengan glob ini. Dimaksudkan untuk meniru kata kunci Greasemonkey @include. |
|
exclude_globs {: #exclude_globs } |
Opsional. Diterapkan setelah matches untuk mengecualikan URL yang cocok dengan glob ini. Dimaksudkan untuk meniru kata kunci Greasemonkey @exclude. |
Skrip konten akan disisipkan ke halaman jika URL-nya cocok dengan pola matches dan pola
include_globs, selama URL tersebut juga tidak cocok dengan pola exclude_matches atau
exclude_globs.
Karena properti matches wajib diisi, exclude_matches, include_globs, dan exclude_globs
hanya dapat digunakan untuk membatasi halaman mana yang akan terpengaruh.
Ekstensi berikut akan menyuntikkan skrip konten ke http://www.nytimes.com/ health tetapi tidak ke http://www.nytimes.com/ business .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
Properti glob mengikuti sintaksis yang berbeda dan lebih fleksibel daripada pola kecocokan. String glob yang dapat diterima adalah URL yang dapat berisi tanda bintang dan tanda tanya "karakter pengganti". Tanda bintang * cocok dengan string apa pun dengan panjang berapa pun, termasuk string kosong, sedangkan tanda tanya ? mencocokkan satu karakter.
Misalnya, glob http:// ??? .example.com/foo/ * cocok dengan salah satu dari berikut:
- http:// www .example.com/foo /bar
- http:// the .example.com/foo /
Namun, tidak cocok dengan hal berikut:
- http:// my .example.com/foo/bar
- http:// example .com/foo/
- http://www.example.com/foo
Ekstensi ini akan menyuntikkan skrip konten ke http:/www.nytimes.com/ arts /index.html dan http://www.nytimes.com/ jobs /index.html, tetapi tidak ke http://www.nytimes.com/ sports /index.html.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
Ekstensi ini akan menyuntikkan skrip konten ke http:// history .nytimes.com dan http://.nytimes.com/ history, tetapi tidak ke http:// science .nytimes.com atau http://www.nytimes.com/ science .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Satu, semua, atau sebagian di antaranya dapat disertakan untuk mencapai cakupan yang benar.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
Waktu proses
Waktu penyisipan file JavaScript ke halaman web dikontrol oleh kolom run_at. Kolom
pilihan dan default adalah "document_idle", tetapi juga dapat ditentukan sebagai "document_start" atau
"document_end" jika diperlukan.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
| Nama | Jenis | Deskripsi |
|---|---|---|
document_idle {: #document_idle } |
string | Lebih disukai. Gunakan "document_idle" jika memungkinkan.Browser memilih waktu untuk menyuntikkan skrip antara "document_end" dan segera setelah peristiwa windowonload diaktifkan. Momen injeksi yang tepat bergantung pada seberapa kompleks dokumen dan berapa lama waktu yang dibutuhkan untuk memuat, serta dioptimalkan untuk kecepatan pemuatan halaman.Skrip konten yang berjalan di "document_idle" tidak perlu memproses peristiwa window.onload, karena dijamin akan berjalan setelah DOM selesai. Jika skrip pasti perlu dijalankan setelah window.onload, ekstensi dapat memeriksa apakah onload telah diaktifkan menggunakan properti document.readyState. |
document_start {: #document_start } |
string | Skrip disisipkan setelah file apa pun dari css, tetapi sebelum DOM lain dibuat atau skrip lain dijalankan. |
document_end {: #document_end } |
string | Skrip disisipkan segera setelah DOM selesai, tetapi sebelum subresource seperti gambar dan frame dimuat. |
Menentukan frame
Kolom "all_frames" memungkinkan ekstensi menentukan apakah file JavaScript dan CSS harus disisipkan ke dalam semua frame yang cocok dengan persyaratan URL yang ditentukan atau hanya ke dalam frame teratas di tab.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
| Nama | Jenis | Deskripsi |
|---|---|---|
all_frames {: #all_frames } |
boolean | Opsional. Nilai defaultnya adalah false, yang berarti hanya frame teratas yang dicocokkan.Jika ditentukan true, kode akan disisipkan ke semua frame, meskipun frame tersebut bukan frame teratas di tab. Setiap frame diperiksa secara independen untuk persyaratan URL, dan tidak akan disisipkan ke dalam frame turunan jika persyaratan URL tidak terpenuhi. |
Komunikasi dengan halaman penyematan
Meskipun lingkungan eksekusi skrip konten dan halaman yang menghostingnya terisolasi satu sama lain, keduanya berbagi akses ke DOM halaman. Jika halaman ingin berkomunikasi dengan skrip konten, atau dengan ekstensi melalui skrip konten, halaman harus melakukannya melalui DOM bersama.
Contoh dapat dilakukan menggunakan 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);
Halaman non-ekstensi, example.html, memposting pesan ke dirinya sendiri. Pesan ini dicegat dan diperiksa oleh skrip konten, lalu diposting ke proses ekstensi. Dengan cara ini, halaman menjalin komunikasi dengan proses ekstensi. Kebalikannya dapat dilakukan dengan cara yang serupa.
Tetap aman
Meskipun dunia terisolasi memberikan lapisan perlindungan, penggunaan skrip konten dapat menimbulkan kerentanan dalam ekstensi dan halaman web. Jika skrip konten menerima konten dari situs terpisah, seperti membuat XMLHttpRequest, berhati-hatilah untuk memfilter konten dari serangan cross-site scripting sebelum menyisipkannya. Hanya berkomunikasi melalui HTTPS untuk menghindari serangan "man-in-the-middle".
Pastikan untuk memfilter halaman web berbahaya. Misalnya, pola berikut berbahaya:
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);
Sebagai gantinya, pilih API yang lebih aman yang tidak menjalankan skrip:
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);