Skrip konten

Skrip konten adalah file yang berjalan dalam konteks halaman web. Dengan menggunakan Dokumen Model Objek (DOM), mereka dapat membaca detail halaman web yang dikunjungi browser, perubahan pada mereka 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. File tersebut 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 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 tanpa bertentangan dengan skrip halaman atau 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 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 pemberitahuan akan muncul jika tombol ditekan.

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

Memasukkan skrip

Skrip Konten dapat dimasukkan secara terprogram atau secara 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. Tindakan ini memberikan akses aman ke host situs aktif dan akses sementara ke izin tab, sehingga skrip konten dapat berjalan di tab aktif saat ini tanpa menentukan izin lintas-asal.

{
  "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

Gunakan injeksi deklaratif untuk skrip konten yang harus dijalankan secara otomatis di halaman tertentu.

Skrip yang dimasukkan secara deklaratif didaftarkan dalam manifes pada kolom "content_scripts". File tersebut dapat menyertakan file JavaScript, file CSS, atau keduanya. Semua skrip konten yang berjalan 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 Pencocokan Pola untuk mengetahui detail selengkapnya tentang sintaksis string ini serta 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. Hal ini dimasukkan sesuai urutan kemunculannya di 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 di array ini.
match_about_blank {: #match_about_blank } boolean Opsional. Apakah skrip harus dimasukkan 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 manifes pendaftaran.

Nama Jenis Deskripsi
exclude_matches {: #exclude_matches } array string Opsional. Mengecualikan halaman yang seharusnya dimasukkan skrip konten ini. Lihat Pola Pencocokan untuk mengetahui 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. Dimaksudkan untuk mengemulasi kata kunci @include GreaseMonkey.
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 dalam halaman jika URL-nya cocok dengan pola matches dan pola include_globs apa pun, selama URL tersebut juga tidak cocok dengan pola exclude_matches atau exclude_globs.

Karena properti matches diperlukan, 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 pola pencocokan. String glob yang dapat diterima adalah URL yang dapat berisi tanda bintang "karakter pengganti" dan tanda tanya. Tanda bintang * cocok dengan string dengan panjang berapa pun, termasuk string kosong, sedangkan tanda tanya ? kecocokan karakter tunggal apa pun.

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

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

Namun, tidak cocok dengan hal 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 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 beberapa dari hal ini 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

Saat file JavaScript dimasukkan ke halaman web dikontrol oleh kolom run_at. Kolom yang lebih disukai 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 memasukkan skrip antara "document_end" dan segera setelah peristiwa windowonload diaktifkan. Momen injeksi yang tepat bergantung pada seberapa rumit dokumen dan waktu yang dibutuhkan untuk memuat halaman, serta dioptimalkan untuk kecepatan pemuatan halaman.

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

Tentukan frame

Kolom "all_frames" memungkinkan ekstensi 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, yang berarti hanya frame atas yang cocok.

Jika true ditentukan, true akan dimasukkan ke semua frame, meskipun frame tersebut bukan frame paling atas di tab. Setiap frame diperiksa secara terpisah untuk mengetahui persyaratan URL, dan tidak akan dimasukkan 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, hal itu harus dilakukan melalui DOM bersama.

Contoh dapat diselesaikan 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 disadap dan diperiksa oleh skrip konten dan kemudian diposting ke proses ekstensi. Dengan cara ini, halaman akan membuat jalur komunikasi ke proses ekstensi. Hal sebaliknya dapat dilakukan melalui cara yang serupa.

Tetap aman

Dunia yang terisolasi memberikan lapisan perlindungan, tapi skrip konten dapat menciptakan kerentanan di ekstensi dan laman web. Jika skrip konten menerima konten dari situs terpisah, seperti membuat XMLHttpRequest, berhati-hati dalam memfilter konten lintas situs pembuatan skrip sebelum menginjeksikannya. Hanya berkomunikasi melalui HTTPS untuk menghindari Serangan &quot;man-in-the-middle&quot;.

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