Saya sedang belajar cara membuat ekstensi Chrome. Saya baru saja mulai mengembangkan satu untuk menangkap acara YouTube. Saya ingin menggunakannya dengan pemutar flash YouTube (nanti saya akan mencoba membuatnya kompatibel dengan HTML5).
manifest.json:
{
"name": "MyExtension",
"version": "1.0",
"description": "Gotta catch Youtube events!",
"permissions": ["tabs", "http://*/*"],
"content_scripts" : [{
"matches" : [ "www.youtube.com/*"],
"js" : ["myScript.js"]
}]
}
myScript.js:
function state() { console.log("State Changed!"); }
var player = document.getElementById("movie_player");
player.addEventListener("onStateChange", "state");
console.log("Started!");
Masalahnya adalah konsol memberi saya "Memulai!" , tetapi tidak ada "Negara Berubah!" ketika saya memutar / menghentikan video YouTube.
Ketika kode ini diletakkan di konsol, itu berhasil. Apa yang saya lakukan salah?
player.addEventListener("onStateChange", state);
https://
atauhttp://
, iniwww.youtube.com/*
tidak akan membiarkan Anda mengemas ekstensi dan akan membuat kesalahan pemisah skema HilangJawaban:
Skrip konten dieksekusi di lingkungan "dunia terisolasi" . Anda harus menyuntikkan
state()
metode Anda ke halaman itu sendiri.Saat Anda ingin menggunakan salah satu
chrome.*
API dalam skrip, Anda harus menerapkan pengendali acara khusus, seperti yang dijelaskan dalam jawaban ini: Ekstensi Chrome - mengambil pesan asli Gmail .Jika tidak, jika Anda tidak harus menggunakan
chrome.*
API, saya sangat menyarankan untuk menyuntikkan semua kode JS Anda di halaman melalui menambahkan<script>
tag:Daftar Isi
Metode 1: Suntikkan file lain
Ini adalah metode termudah / terbaik ketika Anda memiliki banyak kode. Sertakan kode JS Anda yang sebenarnya dalam file dalam ekstensi Anda, katakanlah
script.js
. Kemudian biarkan skrip konten Anda sebagai berikut (dijelaskan di sini: Google Chome "Pintasan Aplikasi" Javascript Khusus ):Catatan: Jika Anda menggunakan metode ini,
script.js
file yang disuntikkan harus ditambahkan ke"web_accessible_resources"
bagian ( contoh ). Jika tidak, Chrome akan menolak memuat skrip Anda dan menampilkan kesalahan berikut di konsol:Metode 2: Suntikkan kode tertanam
Metode ini berguna ketika Anda ingin menjalankan sepotong kode dengan cepat. (Lihat juga: Cara menonaktifkan hotkey facebook dengan ekstensi Chrome? ).
Catatan: literal templat hanya didukung di Chrome 41 dan di atasnya. Jika Anda ingin ekstensi berfungsi di Chrome 40-, gunakan:
Metode 2b: Menggunakan fungsi
Untuk sejumlah besar kode, mengutip string tidak layak. Alih-alih menggunakan array, sebuah fungsi dapat digunakan, dan dirender:
Metode ini berfungsi, karena
+
operator pada string dan fungsi mengubah semua objek menjadi string. Jika Anda berniat menggunakan kode lebih dari sekali, sebaiknya buat fungsi untuk menghindari pengulangan kode. Suatu implementasi mungkin terlihat seperti:Catatan: Karena fungsi ini diserialisasi, ruang lingkup asli, dan semua properti terikat hilang!
Metode 3: Menggunakan acara inline
Terkadang, Anda ingin menjalankan beberapa kode segera, misalnya untuk menjalankan beberapa kode sebelum
<head>
elemen dibuat. Ini dapat dilakukan dengan memasukkan<script>
tag dengantextContent
(lihat metode 2 / 2b).Alternatif, tetapi tidak disarankan adalah menggunakan acara inline. Tidak disarankan karena jika halaman menetapkan kebijakan Keamanan Konten yang melarang skrip inline, maka acara inline pendengar diblokir. Skrip sebaris yang disuntikkan oleh ekstensi, di sisi lain, masih berjalan. Jika Anda masih ingin menggunakan acara sebaris, ini caranya:
Catatan: Metode ini mengasumsikan bahwa tidak ada pendengar acara global lain yang menangani
reset
acara tersebut. Jika ada, Anda juga dapat memilih salah satu acara global lainnya. Cukup buka konsol JavaScript (F12), ketikdocument.documentElement.on
, dan pilih dari acara yang tersedia.Nilai dinamis dalam kode yang disuntikkan
Kadang-kadang, Anda harus meneruskan variabel arbitrer ke fungsi yang disuntikkan. Sebagai contoh:
Untuk menyuntikkan kode ini, Anda harus meneruskan variabel sebagai argumen ke fungsi anonim. Pastikan untuk menerapkannya dengan benar! Berikut ini tidak akan berfungsi:
Solusinya adalah menggunakan
JSON.stringify
sebelum melewati argumen. Contoh:Jika Anda memiliki banyak variabel, sebaiknya gunakan
JSON.stringify
sekali, untuk meningkatkan keterbacaan, sebagai berikut:sumber
script-src
arahan yang mengecualikan asal ekstensi, metode 2 dapat diblokir dengan menggunakan CSP yang mengecualikan "tidak aman-sebaris" `.script.parentNode.removeChild(script);
. Alasan saya melakukannya adalah karena saya suka membersihkan kekacauan saya. Ketika skrip inline dimasukkan ke dalam dokumen, skrip segera dieksekusi dan<script>
tag dapat dengan aman dihapus.location.href = "javascript: alert('yeah')";
di mana saja dalam skrip konten Anda. Lebih mudah untuk cuplikan kode pendek, dan juga dapat mengakses objek JS halaman.javascript:
. Kode yang mencakup beberapa baris mungkin tidak berfungsi seperti yang diharapkan. Sebuah garis-komentar (//
) akan memotong sisanya, jadi ini akan gagal:location.href = 'javascript:// Do something <newline> alert(0);';
. Ini dapat dielakkan dengan memastikan bahwa Anda menggunakan komentar multi-baris. Hal lain yang harus diperhatikan adalah bahwa hasil ekspresi harus batal.javascript:window.x = 'some variable';
akan menyebabkan dokumen diturunkan, dan diganti dengan frasa 'some variable'. Jika digunakan dengan benar, itu memang alternatif yang menarik<script>
.Satu-satunya
hilangtersembunyi dari jawaban sempurna Rob W adalah bagaimana berkomunikasi antara skrip halaman yang disuntikkan dan skrip konten.Di sisi penerima (skrip konten Anda atau skrip halaman yang disuntikkan) tambahkan pendengar acara:
Di sisi inisiator (skrip konten atau skrip halaman yang disuntikkan) kirim acara:
Catatan:
Di Firefox, untuk mengirim objek (yaitu bukan nilai primitif) dari skrip konten ke konteks halaman Anda harus mengkloningnya secara eksplisit ke dalam target menggunakan
cloneInto
(fungsi bawaan), jika tidak maka akan gagal dengan kesalahan pelanggaran keamanan .sumber
CustomEvent
Konstruktor menggantikandocument.createEvent
API yang sudah usang .CustomEvent
konstruktor. Saya mengalami 2 kemunduran yang sangat membingungkan: 1. hanya dengan menempatkan tanda kutip tunggal di sekitar 'detail' secara membingungkan membuat nilainull
ketika diterima oleh pendengar Script Konten saya. 2. Lebih penting lagi, untuk beberapa alasan saya harusJSON.parse(JSON.stringify(myData))
atau kalau tidak, itu juga akan menjadinull
. Mengingat hal ini, bagi saya tampaknya klaim pengembang Chromium berikut - bahwa algoritma "terstruktur klon" digunakan secara otomatis - tidak benar. bugs.chromium.org/p/chromium/issues/detail?id=260378#c18Saya juga menghadapi masalah pemesanan skrip yang dimuat, yang diselesaikan melalui pemuatan skrip berurutan. Loading didasarkan pada jawaban Rob W .
Contoh penggunaannya adalah:
Sebenarnya, saya agak baru di JS, jadi silakan ping saya ke cara yang lebih baik.
sumber
formulaImageUrl
ataucodeImageUrl
, maka Anda secara efektif merusak fungsionalitas halaman. Jika Anda ingin meneruskan variabel ke halaman web, saya sarankan untuk melampirkan data ke elemen skrip (e.g. script.dataset.formulaImageUrl = formulaImageUrl;
) dan menggunakan misalnya(function() { var dataset = document.currentScript.dataset; alert(dataset.formulaImageUrl;) })();
dalam skrip untuk mengakses data.dataset
?document.currentScript
hanya menunjuk ke tag skrip saat dijalankan. Jika Anda pernah ingin mengakses tag skrip dan / atau atribut / propertinya (mis.dataset
), Maka Anda perlu menyimpannya dalam variabel. Kita membutuhkan IIFE untuk mendapatkan penutupan untuk menyimpan variabel ini tanpa mencemari namespace global.return;
).dalam skrip Konten, saya menambahkan tag skrip ke kepala yang mengikat penangan 'onmessage', di dalam penangan yang saya gunakan, eval untuk mengeksekusi kode. Dalam skrip konten stan saya menggunakan onmessage handler juga, jadi saya mendapatkan komunikasi dua arah. Chrome Documents
pmListener.js adalah pendengar url pesan posting
Dengan cara ini, saya dapat memiliki komunikasi 2 arah antara CS ke Real Dom. Ini sangat berguna misalnya jika Anda perlu mendengarkan acara webscoket, atau variabel memori atau acara.
sumber
Anda dapat menggunakan fungsi utilitas yang saya buat untuk menjalankan kode dalam konteks halaman dan mendapatkan kembali nilai yang dikembalikan.
Ini dilakukan dengan membuat serial suatu fungsi ke string dan menyuntikkannya ke halaman web.
Utilitas tersedia di sini di GitHub .
Contoh penggunaan -
sumber
Jika Anda ingin menyuntikkan fungsi murni, alih-alih teks, Anda dapat menggunakan metode ini:
Dan Anda dapat melewatkan parameter (sayangnya tidak ada objek dan array yang dapat dikompresi) ke fungsi. Tambahkan ke dalam baretese, seperti:
sumber