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 seperti ini, kami punya 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 ekstensi secara mendalam. Anda akan mempelajari fungsi ekstensi seperti skrip konten, pekerja layanan, dan penerusan pesan.

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

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 Anda.
  • 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.

Perintah:

What are the important parts to build a chrome extension?

Kita akan mendapatkan respons yang menentukan detail kecil tentang file manifest, background script, dan detail tentang antarmuka pengguna. Mari kita bahas lebih mendetail untuk file tertentu ini.

Perintah:

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 yang diinginkan dan email Anda di kolom penulis.

Gemini menampilkan konten file manifes yang kita butuhkan, tetapi kita mendapatkan beberapa kolom tambahan yang tidak kita perlukan, seperti kolom action. Selain itu, kita memerlukan deskripsi. Ayo perbaiki.

Perintah:

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

Hapus kolom tambahan lain yang dihasilkan dalam file manifes Anda untuk saat ini karena codelab ini mengasumsikan kolom-kolom ini ada dalam file manifes Anda.

Sekarang, bagaimana cara menguji apakah ekstensi berfungsi? Mari kita tanya teman kita, Gemini.

Perintah:

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

Namun, saya mendapatkan beberapa langkah tentang cara 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.png92db1999a1800ecd.png

Bagus! Kita dapat melihat ekstensi, tetapi mari kita mulai menambahkan 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 cara melakukannya di ekstensi kita.

Perintah:

How to add a content script in our chrome extension?

Atau lebih spesifik lagi:

Perintah:

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

Atau versi lain:

Perintah:

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 memberi tahu kita perubahan persis yang perlu dilakukan pada file manifest.json dan juga javascript yang diperlukan 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"]
        }
    ]
}

Hal ini memberi tahu Chrome untuk menyuntikkan skrip konten content.js setiap kali kita membuka halaman di subdomain " https://meet.google.com". Mari kita tambahkan file ini dan mengujinya.

Tambahkan kode ini ke file content.js.

console.log("Hello Gemini");

Tentu saja! Saat membuka meet.google.com, kita akan melihat "Hello Gemini" di 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("Hello Gemini!");

6216bab627c31e6c.png

d61631cd9962ffe5.png

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

Meningkatkan kualitas skrip konten

Kami ingin mendapatkan notifikasi saat seseorang bergabung ke rapat saat kami berada di halaman rapat(Tempat kami memiliki opsi untuk bergabung ke rapat). Untuk mencapainya, mari kita amati bagaimana perubahan visual layar saat rapat kosong vs. saat seseorang telah bergabung ke rapat.

Tampilannya seperti ini saat tidak ada orang dalam rapat.

fe5a0c95b20e7f72.png

Sedangkan ini adalah tampilan visual saat ada beberapa peserta dalam rapat.

7a5ef60521d961cc.png

Kita dapat langsung melihat 2 perbedaan penting:

  1. Teks status berubah dari "Tidak ada orang lain di sini" menjadi "[Pengguna] sedang dalam panggilan ini".
  2. Kita dapat melihat gambar pengguna yang telah bergabung dalam panggilan.

Kedua perubahan ini akan berfungsi bagi kita jika kita ingin mengetahui apakah ada orang yang telah bergabung ke rapat, tetapi yang terakhir memiliki beberapa kemungkinan untuk mendapatkan informasi tentang pengguna yang telah bergabung, jadi mari kita coba gunakan yang terakhir.

Buka "Elements Inspector" di Chrome dengan tombol pintas ( 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 memiliki nama pengguna yang telah bergabung ke rapat. Selain itu, tag gambar ini dibungkus dalam div dengan class U04fid. Setelah menambahkan beberapa peserta ke rapat pengujian, 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, berarti ada peserta yang bergabung dalam rapat kita.
  3. Memberi tahu pengguna.

Mari kembali ke Gemini dan tanyakan cara melakukannya langkah demi langkah.

Perintah:

How to detect for element changes in the HTML page?

Hal ini memang memberikan solusi yang melibatkan MutationObserver, tetapi tidak ada yang spesifik untuk persyaratan kita. Mari kita coba ubah perintahnya.

Perintah:

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 peserta menggunakan div induk.

Berikut 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 ubah pendekatan kita lebih jauh:

Perintah:

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.

Fungsi ini 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 file content.js, muat ulang ekstensi(lalu muat ulang halaman meet).

Sekarang, saat seseorang bergabung ke rapat, kita dapat melihat pernyataan log di konsol.

5. Mengirim notifikasi kepada pengguna

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

Perintah:

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

Kita melihat beberapa langkah mendetail dengan sorotan utamanya adalah:

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

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

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

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

Dengan penambahan 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"
    ]
}

Perintah:

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

Kemudian, 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. Menambahkan penerusan pesan di ekstensi Chrome

Sekarang, langkah utama terakhir yang kita perlukan adalah menghubungkan deteksi peserta oleh skrip konten 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 kita tanya teman kita, Gemini, cara melakukannya.

Perintah:

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 apa yang direspons oleh skrip latar belakang.

Jadi, berikut 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 menyesuaikan pesan notifikasi dan mendapatkan ID notifikasi unik. Untuk pesan notifikasi, kita dapat menyertakan nama pengguna. Jika kita ingat dari langkah sebelumnya, kita dapat melihat nama pengguna di atribut judul gambar. Jadi, kita dapat mengambil nama peserta menggunakan document.querySelector('div.U04fid > img').getAttribute('title').

Mengenai ID notifikasi, kita dapat mengambil ID tab skrip konten dan menggunakannya sebagai ID notifikasi. Hal ini dapat dilakukan di 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 yang berpengalaman, atau baru mengenal dunia ekstensi,Gemini dapat membantu Anda menyelesaikan tugas apa pun yang ingin Anda capai.

Sebaiknya tanyakan berbagai hal yang dapat Anda lakukan dengan ekstensi Chrome. Ada banyak API yang layak dijelajahi seperti chrome.storage, alarms, dll. Jika Anda merasa kesulitan, gunakan Gemini atau dokumentasi untuk mengetahui kesalahan Anda atau mengumpulkan berbagai cara untuk menyelesaikan masalah.

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