Codelab: Membuat Ekstensi Chrome di JavaScript menggunakan Gemini

1. Pengantar

Apakah Anda bergabung ke panggilan Meet tetapi tidak ingin menjadi orang pertama yang melakukannya? Jika Anda mengalami masalah ini, kami memiliki solusinya untuk Anda!

Dengan mengikuti codelab ini, Anda akan membuat ekstensi Chrome yang memberi tahu Anda saat peserta pertama bergabung ke panggilan.

Anda akan mempelajari berbagai elemen ekstensi Chrome, lalu mempelajari setiap bagian dari ekstensi tersebut secara mendalam. Anda akan mempelajari fungsi ekstensi seperti skrip konten, pekerja layanan, dan penerusan pesan.

Anda harus mematuhi rilis manifes v3 agar dapat menerima notifikasi setiap kali peserta bergabung ke panggilan Meet.

2. Sebelum memulai

Prasyarat

Meskipun codelab ini cocok untuk pemula, memiliki pemahaman dasar tentang JavaScript dapat meningkatkan pengalaman Anda.

Penyiapan/Persyaratan

  • Browser Chrome
  • Penyiapan IDE/Editor di sistem lokal.
  • Instal gcloud cli jika Anda ingin mengaktifkan Gemini API menggunakan gcloud.

Mengaktifkan Gemini API

Note that if you're writing the code in the Cloud Shell editor,
then you will have to download the folder somewhere on your local filesystem to test the extension locally.

3. Ayo lacak Sinterklas

Penginstalan Ekstensi Dasar

Mari buat direktori yang akan kita gunakan sebagai root project.

mkdir gemini-chrome-ext
cd gemini-chrome-ext

Sebelum mulai mengajukan pertanyaan spesifik kepada Gemini, mari kita ajukan beberapa pertanyaan tentang struktur umum ekstensi Chrome.

Lirik:

What are the important parts to build a chrome extension?

Kita mendapatkan respons yang menentukan detail kecil tentang file manifest, background script, dan detail tentang antarmuka pengguna. Mari bahas file spesifik ini secara lebih mendetail.

Lirik:

Create a manifest.json file to build a chrome extension.
Make the name of the extension "Meet Joinees Notifier"
and the author "<YOUR_EMAIL>"

Anda dapat menggunakan nama dan email yang diinginkan pada kolom penulis.

Gemini menampilkan konten file manifes yang kita butuhkan, tetapi kita mendapatkan beberapa kolom tambahan yang tidak diperlukan, seperti kolom action. Kita juga membutuhkan deskripsi. Ayo perbaiki.

Lirik:

Remove the "action" field and make the description as
"Adds the ability to receive a notification when a participant joins a Google meet".

Mari kita masukkan konten ini ke dalam file manifest.json di root project Anda.

Pada tahap ini, file manifes akan terlihat seperti ini.

{
    "name": "Meet Joinees Notifier",
    "version": "1.0",
    "manifest_version": 3,
    "description": "Adds the ability to receive a notification when a participant joins a Google Meet",
    "author": "<YOUR_EMAIL>"
}

Untuk saat ini, hapus kolom tambahan lain yang dihasilkan dalam file manifes karena codelab ini mengasumsikan kolom ini dalam file manifes Anda.

Sekarang, bagaimana kita menguji apakah ekstensi itu bekerja? Mari kita tanya teman kita Gemini, oke?

Lirik:

Guide me on the steps needed to test a chrome extension on my local filesystem.

Di sana saya diberi beberapa langkah untuk mengujinya. Mari kita buka "Extensions Page" dengan membuka chrome://extensions dan pastikan untuk mengaktifkan tombol "Developer Mode", yang akan menampilkan tombol "Load unpacked", yang dapat kita gunakan untuk membuka folder yang berisi file ekstensi secara lokal. Setelah melakukannya, kita akan dapat melihat ekstensi di "Extensions Page".

3d802a497ce0cfc2.pngS

92db1999a1800ecd.pngS

Bagus! Kita dapat melihat ekstensi kita, tetapi mari kita mulai tambahkan beberapa fungsi.

4. Menambahkan skrip konten

Kita ingin menjalankan beberapa kode JavaScript hanya di https://meet.google.com yang dapat kita lakukan menggunakan skrip konten. Mari kita tanyakan kepada Gemini, bagaimana cara mencapainya di ekstensi kita.

Lirik:

How to add a content script in our chrome extension?

Atau lebih spesifik:

Lirik:

How to add a content script to run on meet.google.com subdomain in our chrome extension?

Atau versi lain:

Lirik:

Help me add a content script named content.js to run on meet.google.com subdomain
in our chrome extension. The content
script should simply log "Hello Gemini" when we navigate to "meet.google.com".

Gemini memberikan perubahan persis yang perlu kita lakukan di file manifest.json dan juga javascript yang kita perlukan dalam file content.js.

Dengan penambahan content_scripts, file manifes kita menjadi:

{
    "name": "Meet Joinees Notifier",
    "version": "1.0",
    "manifest_version": 3,
    "description": "Adds the ability to receive a notification when a participant joins a Google Meet",
    "author": "abc@example.com",
    "content_scripts": [
        {
          "matches": ["https://meet.google.com/*"],
          "js": ["content.js"]
        }
    ]
}

Tindakan ini akan memberi tahu Chrome untuk memasukkan skrip konten content.js setiap kali kita membuka halaman di subdomain " https://meet.google.com". Mari kita tambahkan file ini dan lakukan pengujian, kan?

Mari tambahkan kode ini dalam file content.js.

console.log("Hello Gemini");

Tentu saja. Saat membuka meet.google.com, kita melihat "Hello Gemini" pada konsol javascript(Mac: Cmd + Opt + J / Win/Linux: Ctrl + Shift + J).

manifest.json

{

"name": "Meet Joinees Notifier",

"version": "1.0",

"manifest_version": 3,

"description": "Adds the ability to receive a notification when a participant joins a Google Meet",

"author": "luke@cloudadvocacyorg.joonix.net",

"permissions": [

    "tabs",

    "notifications"

],

"content_scripts": [

    {

        "matches": [

            "https://meet.google.com/*"

        ],

        "js": [

            "content.js"

        ]

    }

]

}

content.js

Ⰳconsole.log("Halo Gemini!");

6216bab627c31e6c.pngS

d61631cd9962ffe5.png

Bagus! Sekarang kita berada pada posisi di mana kita dapat menambahkan beberapa fungsi khusus JavaScript ke aplikasi kita. Mari luangkan waktu sejenak dan pikirkan apa yang ingin kita capai.

Memperbaiki skrip konten

Kita ingin mendapatkan notifikasi saat seseorang bergabung ke rapat saat berada di halaman rapat(Di mana kita memiliki opsi untuk bergabung ke rapat tersebut). Untuk mencapai hal ini, mari kita amati bagaimana layar berubah secara visual saat rapat kosong vs saat seseorang telah bergabung ke rapat.

Seperti ini tampilannya saat tidak ada orang dalam rapat.

fe5a0c95b20e7f72.png

Sedangkan ini adalah visualisasi ketika ada beberapa peserta dalam pertemuan.

7a5ef60521d961cc.pngS

Kita bisa melihat 2 perbedaan penting sejak awal:

  1. Teks statusnya berubah dari "Tidak ada orang lain di sini" ke "[User] ada dalam panggilan ini".
  2. Kita dapat melihat gambar pengguna yang telah bergabung ke panggilan.

Kedua perubahan ini akan bekerja jika kita ingin tahu apakah ada yang telah bergabung dalam rapat, tetapi perubahan yang kedua memiliki beberapa kemungkinan untuk mendapatkan informasi tentang pengguna yang telah bergabung. Jadi, mari kita coba menggunakannya.

Membuka "Elements Inspector" di chrome dengan hotkey ( Mac: Cmd + Opt + C / Win: Ctrl + Shift + C), lalu klik gambar pengguna yang telah bergabung.

Kita dapat melihat bahwa ada gambar dengan beberapa string class dan atribut judul gambar tersebut memiliki nama pengguna yang telah bergabung ke rapat. Selain itu, tag gambar ini digabungkan dalam div dengan class U04fid. Setelah kita menambahkan beberapa peserta ke rapat uji coba, kita dapat melihat bahwa div induk ini menghosting beberapa gambar(sesuai dengan pengguna yang berbeda).

Jadi, kami memiliki sebagian strategi:

  1. Mendeteksi saat div dengan class U04fid berisi elemen apa pun.
  2. Jika ya, maka itu berarti ada yang bergabung dalam pertemuan kita.
  3. Beri tahu pengguna.

Mari kembali ke Gemini dan tanyakan bagaimana kita dapat mencapai hal ini langkah demi langkah.

Lirik:

How to detect for element changes in the HTML page?

Ini memberi kita solusi yang melibatkan MutationObserver, tetapi tidak ada yang spesifik dengan persyaratan kita. Mari kita coba mengubah perintah.

Lirik:

How can I detect if an element "div.U04fid" has any child images in the HTML page?

Kali ini, kita mendapatkan solusi yang tidak menyertakan MutationObserver, tetapi solusi yang memeriksa pengguna yang bergabung menggunakan div induk.

Inilah yang kami terima:

const divU04fid = document.querySelector('div.U04fid');
const childImages = divU04fid.querySelectorAll('img');
if (childImages.length > 0) {
  // div.U04fid has at least one child image.
}

Mari kita coba mengubah pendekatan kita lebih banyak:

Lirik:

Create a method which checks if the element div.U04fid has any child elements,
if it does it should log it on the console. The method should be called checkJoinees
and it should be called as a callback for MutationObserver which is observing the document.body.

Operator tersebut menampilkan cuplikan kode berikut:

function checkJoinees(mutations) {
    for (const mutation of mutations) {
      if (mutation.type === 'childList') {
        // A child node was added or removed.
        if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
          // div.U04fid has at least one child element.
          console.log('div.U04fid has at least one child element.');
        }
      }
    }
    return false;
}

const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
  childList: true,
  delay: 1000
});

Salin kode ini ke dalam file content.js, muat ulang ekstensi(lalu muat ulang halaman rapat).

Sekarang ketika seseorang bergabung ke rapat, kita dapat melihat laporan log di konsol.

5. Mengirim notifikasi ke pengguna

Setelah kita dapat mendeteksi kapan peserta telah bergabung ke rapat, mari coba tambahkan bagian notifikasi di ekstensi Chrome kita. Kita dapat menjelajahi dokumentasi ekstensi Chrome atau bahkan menyesuaikan perintah untuk mengetahui apa yang kita cari, tetapi pada dasarnya kita perlu menggunakan chrome.notifications.create API dan panggilan ke metode ini harus dari pekerja layanan latar belakang.

Lirik:

Using the documentation for chrome notifications tell me how to use the chrome.notifications.create method.

Kita melihat beberapa langkah mendetail yang sorotan utamanya adalah:

  • Tambahkan izin notifications dalam file manifes.
  • Lakukan panggilan ke chrome.notifications.create
  • Panggilan harus berada dalam skrip latar belakang.

Untuk menambahkan skrip latar belakang ke ekstensi Chrome di manifest version 3, kita memerlukan deklarasi background.service_worker di file manifest.json.

Jadi, kita membuat file bernama background.js dan menambahkan baris berikut ini ke file manifest.json.

"background": {
        "service_worker": "background.js"
},
"permissions": [
        "notifications"
]

Dengan tambahan di atas, file manifes kita menjadi:

{
    "name": "Meet Joinees Notifier",
    "version": "1.0",
    "manifest_version": 3,
    "description": "Adds the ability to receive a notification when a participant joins a Google Meet",
    "author": "<YOUR_EMAIL>",
    "content_scripts": [
        {
          "matches": ["https://meet.google.com/*"],
          "js": ["content.js"]
        }
    ],
    "background": {
        "service_worker": "background.js"
    },
    "permissions": [
            "notifications"
    ]
}

Lirik:

Create a method sendNotification that calls the chrome.notifications.create
method with the message, "A user joined the call" for a chrome extension with manifest v3,
the code is in the background service worker

Simpan gambar ini di root folder Anda dan ganti namanya menjadi success.png.

b2c22f064a3f2d9c.png

Lalu tambahkan cuplikan kode berikut ke background.js Anda.

function sendNotification(notificationId, message) {
    chrome.notifications.create(notificationId, {
      type: "basic",
      title: "A user joined the call",
      message: message,
      iconUrl: "./success.png"
    });
}

sendNotification("notif-id", "test message");

Sekarang muat ulang ekstensi dari halaman ekstensi dan Anda akan langsung melihat pop-up notifikasi.

6. Tambahkan pesan yang diteruskan di ekstensi Chrome Anda

Sekarang, langkah besar terakhir yang kita perlukan adalah menghubungkan deteksi skrip konten terhadap peserta dan metode sendNotification di skrip latar belakang. Dalam konteks ekstensi Chrome, cara melakukannya adalah melalui teknik yang disebut message passing.

Hal ini memungkinkan komunikasi antara berbagai bagian ekstensi Chrome, dalam kasus kita dari skrip konten ke pekerja layanan latar belakang. Mari tanyakan kepada teman kita Gemini tentang cara mencapainya.

Lirik:

How to send a message from the content script to the background script in a chrome extension

Gemini merespons dengan panggilan yang relevan ke chrome.runtime.sendMessage dan chrome.runtime.onMessage.addListener.

Pada dasarnya, kita akan menggunakan sendMessage untuk mengirim pesan dari skrip konten bahwa seseorang telah bergabung ke panggilan Meet dan onMessage.addListener sebagai pemroses peristiwa untuk bereaksi terhadap pesan yang dikirim oleh skrip konten. Dalam hal ini, kita akan memicu panggilan ke metode sendNotification dari pemroses peristiwa ini.

Kita akan meneruskan pesan notifikasi dan properti action ke pekerja layanan latar belakang. Properti action menjelaskan hal yang direspons oleh skrip latar belakang.

Jadi, berikut adalah kode content.js kita:

function checkJoinees(mutations) {
    for (const mutation of mutations) {
      if (mutation.type === 'childList') {
        // A child node was added or removed.
        if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
          // div.U04fid has at least one child element.
          sendMessage();
        }
      }
    }
    return false;
}

const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
  childList: true,
  delay: 1000
});

function sendMessage() {
    chrome.runtime.sendMessage({
        txt: "A user has joined the call!",
        action: "people_joined"
    });
}

Dan ini adalah kode background.js kita:

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.action === "people_joined") {
      sendNotification("notif-id", message.txt);
    }
  });
  

function sendNotification(notificationId, message) {
    chrome.notifications.create(notificationId, {
      type: "basic",
      title: "A user joined the call",
      message: message,
      iconUrl: "./success.png"
    });
}

Mari kita coba untuk menyesuaikan pesan notifikasi dan mendapatkan ID notifikasi yang unik. Untuk pesan notifikasi, kita dapat menyertakan nama pengguna. Jika kita mengingat kembali dari langkah sebelumnya, kita bisa melihat nama pengguna di atribut judul gambar. Jadi, kita dapat mengambil nama peserta menggunakan document.querySelector('div.U04fid > img').getAttribute('title').

Terkait ID notifikasi, kita dapat mengambil ID tab skrip konten dan menggunakannya sebagai ID notifikasi. Hal ini dapat dilakukan dalam pemroses peristiwa chrome.runtime.onMessage.addListener dengan memanfaatkan sender.tab.id.

Terakhir, file kita akan terlihat seperti ini:

manifest.json

{
    "name": "Meet Joinees Notifier",
    "version": "1.0",
    "manifest_version": 3,
    "description": "Adds the ability to receive a notification when a participant joins a Google Meet",
    "author": "<YOUR_EMAIL>",
    "content_scripts": [
        {
          "matches": ["https://meet.google.com/*"],
          "js": ["content.js"]
        }
    ],
    "background": {
        "service_worker": "background.js"
    },
    "permissions": [
            "notifications"
    ]
}

content.js

function checkJoinees(mutations) {
    for (const mutation of mutations) {
      if (mutation.type === 'childList') {
        // A child node was added or removed.
        if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
            const name = document.querySelector('div.U04fid > img').getAttribute('title');
            sendMessage(name);
        }
      }
    }
    return false;
}

const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
  childList: true,
  delay: 1000
});

function sendMessage(name) {
    const joinee = (name === null ? 'Someone' : name),
        txt = `${joinee} has joined the call!`;

    chrome.runtime.sendMessage({
        txt,
        action: "people_joined",
    });
}

background.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.action === "people_joined") {
      sendNotification("" + sender.tab.id, message.txt); // We are casting this to string as notificationId is expected to be a string while sender.tab.id is an integer.
    }
  });
  

function sendNotification(notificationId, message) {
    chrome.notifications.create(notificationId, {
      type: "basic",
      title: "A user joined the call",
      message: message,
      iconUrl: "./success.png"
    });
}

7. Selamat

Dalam waktu singkat, kami dapat membuat ekstensi Chrome dengan bantuan Gemini. Baik Anda seorang developer ekstensi Chrome berpengalaman maupun yang baru mengenal ekstensi, Gemini dapat membantu menyelesaikan tugas apa pun yang ingin Anda capai.

Sebaiknya tanyakan berbagai hal yang dapat Anda lakukan dengan ekstensi Chrome. Ada banyak API yang patut dijelajahi seperti chrome.storage, alarms, dll. Di mana pun Anda merasa buntu, gunakan Gemini atau dokumentasinya untuk mengetahui kesalahan Anda atau mengumpulkan berbagai cara untuk menyelesaikan masalah.

Terkadang perlu mengubah perintah untuk mendapatkan bantuan yang diperlukan, tetapi kita dapat melakukannya dari satu tab yang menyimpan semua perjalanan kontekstual kita.