Bagaimana saya bisa menghilangkan ribuan tab ...

... dan terlambat 3 tahun. Idealnya, harus seperti ini: pengguna meluncurkan browser, dan browser menunjukkan apa yang dibutuhkan pengguna. Tetapi sementara ini tidak diterapkan, Anda harus menggunakan mesin pencari. Idealnya, harus seperti ini: pengguna membuka mesin pencari, memasukkan permintaan pencarian, dan itu menunjukkan apa yang dibutuhkan pengguna. Tetapi sementara tombol "Saya merasa beruntung" tidak bekerja dengan baik (meskipun belakangan ini ada gerakan yang terlihat jelas ke arah ini), kadang-kadang Anda harus pergi ke beberapa alamat dari halaman hasil pencarian.

Skenario menggunakan mesin pencari, tampaknya, telah diperbaiki secara historis (ketika internet lambat): sampai ke halaman hasil pencarian, saya membuka beberapa tab di latar belakang, dan sementara sisanya memuat, sudah mungkin untuk membaca tab pertama. Dalam kasus ketika saya menemukan informasi yang diperlukan pada salah satu tab, sisanya harus ditutup secara manual. Jika tidak segera ditutup, tab tetap menggantung, menggembungkan jumlah tab terbuka di browser, yang, biasanya, jarang ditutup setelah itu.

Selain itu, jika Anda mengklik pada halaman dengan tautan yang terbuka di jendela baru, beberapa tab (secara logis) tab dibuat. Ketika Anda menemukan informasi yang Anda butuhkan, Anda tidak selalu dapat mengingat tab mana yang terhubung, Anda tidak dapat menutup semuanya, yang juga mengarah pada penggelembungan jumlah tab yang terbuka.

Saya selalu membutuhkan tombol "Ditemukan" , yang akan membersihkan setelah saya konsekuensi dari pencarian (sebut saja "Saya beruntung" ). Setelah terjun ke dunia ekstensi browser, saya pikir itu adalah sesuatu yang bisa membantu dalam hal ini. Jadi samar-samar mulai muncul keinginan untuk menulis ekstensi yang akan menyelesaikan masalah saya.

Saya akan menceritakan kisah saya kepada Anda, saya akan memimpin cerita dalam urutan kronologis, kesimpulannya mungkin tidak terduga.

Langkah pertama menuju


Hal pertama yang saya lakukan adalah menyiapkan infrastruktur: webpack + babel . Dan saat itu juga saya tidak suka kode duplikat babel untuk para pembantunya di setiap modul. Itu mungkin untuk mengkonfigurasinya untuk menggunakan objek babelHelper, tetapi kemudian file kode babelHelperharus terhubung dalam konfigurasi webpack . Menyimpan file seperti itu dalam proyek dan menunjukkannya entryjelek, saya membuat plug-in untuk webpack yang melakukan ini secara otomatis untuk saya. Setelah menghabiskan banyak usaha pada langkah pertama dan menulis beberapa kode lagi untuk ekstensi itu sendiri, saya sedikit melambat.

Plugin

Dasar


Waktu berlalu, dan hanya plug-in untuk webpack yang tersedia, yang tidak menyelesaikan masalah saya dengan cara apa pun. Dan setiap kali saya mencari sesuatu dan tidak menutup tab, ada pemikiran: "Akan menyenangkan untuk melengkapi ekstensi itu ..." Keinginan tumbuh dan tumbuh, dan sekarang, suatu hari, kuantitas tumbuh menjadi kualitas.

Saatnya untuk mengetahui apa ide utamanya:
Pengguna sampai ke halaman hasil pencarian - SICKLE , kami mengurai hasilnya, menyimpan alamat tautan untuk diri kami sendiri, setelah pengguna mengklik salah satu alamat, menunjukkan kepadanya pemberitahuan dengan sisa alamat dan tombol "Ditemukan" untuk menutup tab.

Ketika Anda pergi ke halaman mungkin ada berbagai opsi. Yang paling sederhana: satu permintaan - satu respons dari server ( 200) Yang paling sulit: satu permintaan - beberapa pengalihan server ( 3xx ), setelah itu pengalihan klien (menggunakan <meta/>atau javascript), API riwayat juga di atas . Dan kombinasi di antara mereka, sebagai aturan, sebagian besar situs termasuk dalam kategori ini.

Kasus transisi sederhana:

Kasus transisi sederhana (jawaban 200)

Kasus transisi yang kompleks:

Kasing transisi kompleks (pengarahan 3xx + klien)

Artinya, menyimpan alamat halaman dan hanya mengeceknya tidak selalu cukup. Oleh karena itu, Anda perlu membuat Transisi logis, tempat menuliskan semua alamat yang ditemui di jalan, dan kemudian memeriksa bahwa Transisi logis berisi alamat yang disimpan. Tugasnya jelas, tetapi tidak semuanya begitu mudah dalam eksekusi.

Di Chrome, ada dua API yang terkait dengan navigasi: navigasi web dan permintaan web - masing-masing dengan acara sendiri. Yang pertama - menghubungkan transisi dan UI browser, yang terakhir - permintaan jaringan yang mendasarinya. Karena itu, jika perubahan alamat pada halaman terjadi karena API riwayat, tidak akan ada acara untuk yang terakhir, dan jika pengalihan terjadi selama permintaan jaringan, yang pertama tidak melaporkannya sama sekali. Oleh karena itu, perlu untuk menggunakan kedua API, mengumpulkan sejumput dari setiap peristiwa setiap API, untuk membentuk satu Transisi logis.

Beberapa detail
, webNavigation (wN) :

onBeforeNavigate -> onCommitted -> onDOMContentLoaded -> onCompleted

webRequest (wR):

onBeforeRequest -> [onBeforeRedirect -> onBeforeRequest]* -> onCompleted | onErrorOccurred

wR wN ( ), .. - wN.onBeforeNavigate wR.onBeforeRequest, - . .

, , .

Pengembangan


... Mari kita kembali ke momen ketika kuantitas telah berkembang menjadi kualitas. Sejumlah besar waktu telah berlalu dari awal pengembangan ke titik ini: browser mulai mendukung modul es6 , shadow DOM dan fitur modern lainnya. Untuk membangun proyek, saya pindah ke Rollup , kali ini saya tidak perlu menulis plugin. Setelah membangun fondasi - kemampuan untuk memperoleh informasi tentang transisi apa pun di tab apa pun, tetap menerapkan logika parsing SICKLES yang didukung dan menampilkan pemberitahuan pada halaman terkait.

Tugas pertama cukup primitif: kita tahu alamat SICKLE, naik ke halaman konten menggunakan skrip konten, dapatkan data yang kami minati, simpan, tunggu pengguna untuk masuk ke salah satu halaman untuk menunjukkan pemberitahuan kepadanya dengan halaman lain.

Untuk tugas kedua, Anda perlu mengimplementasikan pemberitahuan itu sendiri, apa yang harus ditampilkan kepada pengguna di halaman. Dan di sini juga, skrip konten tidak bisa dilakukan.

Awalnya, hanya ada satu handler (alias controller) yang bertanggung jawab atas logika selama interaksi pengguna dengan mesin pencari. Kemudian muncul ide, mengapa tidak menampilkan pemberitahuan pada tab terkait saat pengguna cukup mengeklik tautan yang terbuka di tab baru. Saya harus mengulang logika, membuatnya lebih universal. Mirip dengan middleware React / Redux, Anda dapat menghubungkan beberapa penangan Transisi, yang di masa depan akan memungkinkan Anda untuk menerapkan kemampuan untuk menonaktifkan / mengaktifkan berbagai penangan dalam pengaturan ekstensi.

Pribadi


Karena notifikasi adalah panel di bagian bawah layar, dan ditambahkan ke tata letak halaman, skrip pada halaman dapat mengakses elemen ini dengan cara yang sama seperti elemen lain di halaman ini. Yaitu, secara teoritis, halaman tersebut dapat mengetahui permintaan pencarian yang Anda gunakan, di mana mesin pencari dan halaman-halaman lain mana yang ditawarkan kepada Anda, mana yang tidak terlalu bagus.

Sebuah teknologi yang disebut shadow DOM datang untuk menyelamatkan . Tidak disarankan untuk menggunakannya closed modedi web saat membuatnya shadowRoot, karena itu tidak masuk akal (Anda masih harus menyimpan tautan ke elemen di shadowRootsuatu tempat jika Anda ingin memiliki akses ke sana secara terprogram; Anda juga dapat mendefinisikan kembali fungsi attachShadowuntuk membuatshadowRootdalam mode terbuka, dan kemudian skrip yang dimuat setelah redefinisi sudah akan menggunakan versi fungsi yang baru).

Dalam hal ekspansi, tidak demikian halnya. Skrip konten dan skrip halaman hidup dalam dunia paralel. Skrip dari halaman tidak memiliki akses ke objek yang ditentukan dalam skrip konten, sementara skrip konten beroperasi dengan implementasi asli dari fungsi objek DOM (fungsi yang dikesampingkan oleh skrip dari halaman tidak memiliki efek pada fungsi dengan mana skrip konten bekerja). Menggabungkan kedua kondisi ini, kita melihat bahwa adalah mungkin untuk membuat elemen dengan elemen pribadi shadowRootdengan menyimpan tautan ke dalamnya dalam sebuah variabel.

Dalam hal ini, skrip dari halaman hanya dapat mengakses elemen pembungkus, yang akan kosong untuk itu. Dia tidak akan dapat menerima teks permintaan atau halaman yang diajukan. Harus berhati-hati untuk tidak memberikan tautan ke elemen apa pun di dalam notifikasi atau teks biasa dalam peristiwa yang dihasilkan. Oleh karena itu, dalam ekstensi, id yang dihasilkan digunakan dalam acara, dan skrip latar belakang sudah memahami apa yang diperlukan oleh id ini. Untuk halaman, id ini tidak ada artinya.

Kesulitan terjemahan


Awalnya, ekstensi hanya dikembangkan untuk Google Chrome , tetapi karena WebExtensions API , di suatu tempat di kepala saya tetap memiliki kemampuan untuk port ke browser lain. Dan kehadiran webextension-polyfill menginspirasi kepercayaan. Tapi bagaimanapun caranya. Polyphil untuk ekstensi ini hanya membawa kemampuan untuk menggunakan API chrome dengan janji.

Firefox telah menjadi kekecewaan tahun ini. Ketidakcocokan API chrome di Firefox ( Bug 1543647 , Bug 1595621 ) ternyata sangat penting untuk ekstensi untuk bekerja, kita dapat mengatakan itu tidak berfungsi di browser ini (seperti yang diharapkan).

Vivaldi adalah yang terdekat, tetapi juga bukan tanpa biaya. PeristiwawN.onCreatedNavigationTargetItu tidak terjadi ketika pengguna membuka tautan dengan tombol tengah mouse atau melalui tombol Shift|Ctrl+ kiri mouse, alih-alih acara wN.onCommitted transitionType == 'start_page', yang tidak ada di API chrome , karena ini, tidak dalam semua kasus ekstensi bekerja dengan benar. Juga di Vivaldi tidak berfungsi tombol pintas untuk ekstensi. Apa itu fitur pembunuh dalam kasus ini di Chrome, memungkinkan Anda dengan cepat menavigasi tab dan menutupnya, tanpa perlu menggunakan mouse untuk ini.

Kesimpulan


Selama penulisan kode, logika untuk menampilkan pemberitahuan berubah beberapa kali, menyederhanakan setiap waktu. Akibatnya, ternyata mungkin untuk tidak pagar taman dengan Transisi logis, tetapi untuk menangkap "transisi terkait" dari pengguna (dalam hal wN.onCommittedada bendera transitionTypeyang menunjukkan untuk apa transisi, dalam banyak kasus itu adalah "tautan", yang berarti bahwa pengguna beralih dengan referensi), yang akan sangat menyederhanakan kode dan berfungsi dalam banyak kasus, tetapi tidak semuanya.

Juga, tidak berada dalam subjek, saya mengharapkan lebih banyak kompatibilitas dalam hal API WebExtensions. Seperti biasa, baik untuk hidup di dunia peramban modern saat Anda tidak memerlukan dukungan untuk versi yang lebih lama. Animasi CSS adalah hal yang luar biasa: apa yang Anda gunakan untuk menggunakan js library sekarang dilakukan dalam beberapa baris pada css. Elemen khusus tidak berfungsi dalam ekstensi, tetapi bayangan DOM berfungsi, memungkinkan Anda memanfaatkan semua fitur-fiturnya.

Ekspansi
chrome web store: Handy Search

Source: https://habr.com/ru/post/undefined/


All Articles