Skrip konten

Skrip konten adalah file yang dijalankan dalam konteks halaman web. Dengan menggunakan Document Object Model (DOM) standar, pengguna dapat membaca detail halaman web yang dikunjungi browser, membuat perubahan pada halaman tersebut, dan meneruskan informasi ke ekstensi induknya.

Memahami kemampuan skrip konten

Skrip konten dapat mengakses Chrome API yang digunakan oleh ekstensi induknya dengan bertukar pesan dengan ekstensi. Mereka juga dapat mengakses URL file ekstensi dengan chrome.runtime.getURL() dan menggunakan hasilnya yang 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 API Chrome berikut secara langsung:

Skrip konten tidak dapat mengakses API lain secara langsung.

Bekerja di dunia yang terisolasi

Skrip konten berada di dunia yang terisolasi, sehingga skrip konten dapat membuat perubahan pada lingkungan JavaScript-nya tanpa bertentangan dengan halaman atau skrip konten tambahan.

Ekstensi dapat berjalan di halaman web dengan kode yang mirip dengan contoh di bawah ini.

<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 memasukkan 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 peringatan akan muncul jika tombol ditekan.

Dunia terisolasi tidak mengizinkan skrip konten, ekstensi, dan halaman web untuk mengakses variabel atau fungsi apa pun yang dibuat oleh orang lain. Hal ini juga memberi skrip konten kemampuan untuk mengaktifkan fungsi yang seharusnya tidak dapat diakses oleh halaman web.

Memasukkan skrip

Skrip Konten dapat dimasukkan secara terprogram atau deklaratif.

Memasukkan secara terprogram

Gunakan injeksi terprogram untuk skrip konten yang perlu dijalankan pada acara tertentu.

Untuk memasukkan skrip konten terprogram, berikan izin activeTab dalam manifes. Hal ini memberikan akses aman ke host situs yang aktif dan akses sementara ke izin tab, sehingga skrip konten dapat berjalan pada 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 dimasukkan.

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

Memasukkan secara deklaratif

Menggunakan injeksi deklaratif untuk skrip konten yang harus dijalankan secara otomatis di halaman yang ditentukan.

Skrip yang dimasukkan secara deklaratif didaftarkan dalam manifes di bagian kolom "content_scripts". File tersebut dapat mencakup file JavaScript, file CSS, atau keduanya. Semua skrip konten yang dijalankan secara otomatis harus menentukan pola pencocokan.

{
 "name": "My extension",
 ...
 "content_scripts": [
   {
     "matches": ["http://*.nytimes.com/*"],
     "css": ["myStyles.css"],
     "js": ["contentScript.js"]
   }
 ],
 ...
}
Nama Jenis Deskripsi
matches {: #matches } array string Wajib. Menentukan halaman tempat skrip konten ini akan dimasukkan. Lihat Pola Pencocokan untuk detail selengkapnya tentang sintaksis string ini dan Pola pencocokan dan glob untuk mengetahui informasi tentang cara mengecualikan URL.
css {: #css } array string Opsional. Daftar file CSS yang akan dimasukkan ke halaman yang cocok. Ini dimasukkan sesuai urutan kemunculannya dalam array ini, sebelum DOM dibuat atau ditampilkan untuk halaman.
js {: #js } array string Opsional. Daftar file JavaScript yang akan dimasukkan ke halaman yang cocok. Ini dimasukkan sesuai urutan kemunculannya dalam array ini.
match_about_blank {: #match_about_blank } boolean Opsional. Apakah skrip harus dimasukkan ke dalam frame about:blank tempat frame induk atau frame pembuka cocok dengan salah satu pola yang dideklarasikan dalam matches. Defaultnya adalah false.

Kecualikan pencocokan dan glob

Pencocokan halaman yang ditentukan dapat disesuaikan dengan menyertakan kolom berikut dalam pendaftaran manifes.

Nama Jenis Deskripsi
exclude_matches {: #exclude_matches } array string Opsional. Mengecualikan halaman tempat skrip konten ini akan dimasukkan. Lihat Pola Pencocokan untuk detail selengkapnya tentang sintaksis string ini.
include_globs {: #include_globs } array string Opsional. Diterapkan setelah matches untuk hanya menyertakan URL yang juga cocok dengan glob ini. Ditujukan untuk mengemulasi kata kunci GreaseMonkey @include.
exclude_globs {: #exclude_globs } array string Opsional. Diterapkan setelah matches untuk mengecualikan URL yang cocok dengan glob ini. Ditujukan untuk mengemulasi kata kunci @excludeGreaseMonkey.

Skrip konten akan dimasukkan ke halaman jika URL-nya cocok dengan pola matches apa pun dan pola include_globs apa pun, selama URL tersebut juga tidak cocok dengan pola exclude_matches atau exclude_globs.

Karena properti matches bersifat wajib, exclude_matches, include_globs, dan exclude_globs hanya dapat digunakan untuk membatasi halaman mana yang akan terpengaruh.

Ekstensi berikut akan memasukkan 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 pencocokan pola. String glob yang dapat diterima adalah URL yang dapat berisi tanda bintang "karakter pengganti" dan tanda tanya. Tanda bintang * cocok dengan string apa pun dengan panjang berapa pun, termasuk string kosong, sedangkan tanda tanya ? cocok dengan satu karakter apa pun.

Misalnya, glob http:// ??? .example.com/foo/ * cocok dengan salah satu parameter berikut:

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

Namun, kode tersebut tidak cocok dengan kode berikut:

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

Ekstensi ini akan memasukkan 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 memasukkan skrip konten ke http:// history .nytimes.com dan http://.nytimes.com/ history, tetapi tidak ke dalam 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 dapat disertakan untuk mencapai ruang lingkup 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

Saat file JavaScript dimasukkan ke halaman web dikontrol oleh kolom run_at. Kolom prefferer dan default-nya 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 akan memilih waktu untuk memasukkan skrip antara "document_end" dan segera setelah peristiwa windowonload diaktifkan. Momen injeksi yang tepat bergantung pada seberapa rumit dokumen dan berapa lama waktu yang diperlukan untuk memuatnya, serta dioptimalkan untuk kecepatan pemuatan halaman.

Skrip konten yang berjalan pada "document_idle" tidak perlu memproses peristiwa window.onload, skrip tersebut dijamin akan berjalan setelah DOM selesai. Jika skrip benar-benar harus dijalankan setelah window.onload, ekstensi dapat memeriksa apakah onload sudah diaktifkan menggunakan properti document.readyState.
document_start {: #document_start } string Skrip dimasukkan setelah file apa pun dari css, tetapi sebelum DOM lain dibuat atau skrip lain dijalankan.
document_end {: #document_end } string Skrip dimasukkan segera setelah DOM selesai, tetapi sebelum subresource seperti gambar dan bingkai dimuat.

Menentukan frame

Kolom "all_frames" memungkinkan ekstensi untuk menentukan apakah file JavaScript dan CSS harus dimasukkan ke semua frame yang cocok dengan persyaratan URL yang ditentukan atau hanya ke frame paling atas 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. Defaultnya adalah false, artinya hanya frame atas yang cocok.

Jika ditentukan true, frame akan dimasukkan ke semua frame, meskipun frame tersebut bukan frame teratas di tab. Setiap frame diperiksa secara terpisah untuk persyaratan URL, dan tidak akan dimasukkan ke dalam frame turunan jika persyaratan URL tidak terpenuhi.

Komunikasi dengan halaman sematan

Meskipun lingkungan eksekusi skrip konten dan halaman yang menghostingnya terisolasi dari 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.

Contohnya 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 halaman itu sendiri. Pesan ini dicegat dan diperiksa oleh skrip konten, lalu diposting ke proses ekstensi. Dengan cara ini, halaman menetapkan jalur komunikasi ke proses ekstensi. Hal sebaliknya dapat dilakukan melalui cara yang sama.

Tetap aman

Meskipun dunia terisolasi memberikan lapisan perlindungan, penggunaan skrip konten dapat menimbulkan kerentanan pada ekstensi dan halaman web. Jika skrip konten menerima konten dari situs terpisah, seperti membuat XMLHttpRequest, berhati-hatilah untuk memfilter serangan pembuatan skrip lintas situs konten sebelum memasukkannya. Hanya berkomunikasi melalui HTTPS untuk menghindari serangan "man-in-the-middle".

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