Lớp học lập trình: Tạo tiện ích của Chrome trong JavaScript bằng Gemini

Lớp học lập trình:
Tạo tiện ích của Chrome trong JavaScript bằng Gemini

Thông tin về lớp học lập trình này

subjectLần cập nhật gần đây nhất: thg 4 24, 2024
account_circleTác giả: Saransh Dhingra

1. Giới thiệu

Bạn đang tham gia một cuộc gọi trên Meet nhưng không muốn là người đầu tiên tham gia cuộc gọi đó? Nếu bạn gặp trường hợp này, thì chúng tôi có giải pháp cho bạn!

Sau lớp học lập trình này, bạn sẽ tạo một tiện ích của Chrome để thông báo khi người tham gia đầu tiên tham gia cuộc gọi.

Bạn sẽ tìm hiểu các thành phần khác nhau trong một tiện ích Chrome, sau đó đi sâu vào từng phần của tiện ích đó. Bạn sẽ tìm hiểu về các hàm tiện ích như tập lệnh nội dung, trình chạy dịch vụ và cách truyền thông báo.

Bạn cần tuân thủ bản phát hành tệp kê khai v3 để có thể nhận được thông báo bất cứ khi nào người tham gia tham gia cuộc gọi trên Meet.

2. Trước khi bắt đầu

Điều kiện tiên quyết

Mặc dù lớp học lập trình này phù hợp với người mới bắt đầu, nhưng nếu hiểu rõ kiến thức cơ bản về JavaScript thì bạn có thể nâng cao trải nghiệm của mình đáng kể.

Thiết lập/Yêu cầu

  • Trình duyệt Chrome
  • Thiết lập IDE/Editor trên hệ thống cục bộ của bạn.
  • Cài đặt gcloud cli nếu bạn muốn bật Gemini API bằng gcloud.

Bật 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. Bắt đầu chơi

Cài đặt tiện ích cơ bản

Hãy tạo một thư mục mà chúng ta sẽ dùng làm thư mục gốc của dự án.

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

Trước khi bắt đầu đặt câu hỏi cụ thể cho Gemini, hãy đặt một số câu hỏi về cấu trúc chung của một tiện ích của Chrome.

Lời nhắc:

What are the important parts to build a chrome extension?

Chúng ta nhận được phản hồi nêu rõ các thông tin chi tiết nhỏ về tệp manifest, background script và thông tin chi tiết về giao diện người dùng. Hãy cùng tìm hiểu chi tiết hơn về các tệp cụ thể này.

Lời nhắc:

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

Bạn có thể sử dụng tên mong muốn và email của mình trong trường tác giả.

Gemini trả về nội dung của tệp kê khai mà chúng ta cần, nhưng chúng ta sẽ nhận được một số trường bổ sung mà chúng ta không cần đến, chẳng hạn như trường action. Ngoài ra, chúng tôi cần có thành phần mô tả. Hãy khắc phục vấn đề đó.

Lời nhắc:

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

Hãy đặt nội dung này vào tệp manifest.json trong thư mục gốc của dự án.

Ở giai đoạn này, tệp kê khai sẽ có dạng như sau.

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

Xoá mọi trường bổ sung khác được tạo trong tệp kê khai vì lớp học lập trình này giả định các trường này trong tệp kê khai của bạn.

Bây giờ, làm cách nào để chúng ta kiểm thử xem tiện ích này có hoạt động không? Hãy hỏi bạn Gemini, chúng ta sẽ làm được như thế nào?

Lời nhắc:

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

Trang này sẽ hướng dẫn tôi một số bước về cách kiểm tra trang web đó. Hãy chuyển đến "Extensions Page" bằng cách chuyển đến chrome://extensions và nhớ bật nút "Developer Mode". Nút này sẽ hiển thị nút "Load unpacked". Chúng ta có thể dùng nút này để điều hướng đến thư mục chứa các tệp tiện ích trên thiết bị. Sau khi làm như vậy, chúng ta sẽ thấy tiện ích này trong "Extensions Page".

3d802a497ce0cfc2.png.

92db1999a1800ecd.pngS

Tuyệt vời! Chúng ta có thể thấy tiện ích, nhưng hãy bắt đầu thêm một số chức năng.

4. Thêm tập lệnh nội dung

Chúng ta chỉ muốn chạy một số mã JavaScript trên https://meet.google.com (có thể thực hiện bằng cách sử dụng tập lệnh nội dung). Hãy hỏi Gemini về cách đạt được điều đó trong tiện ích của chúng ta.

Lời nhắc:

How to add a content script in our chrome extension?

Hoặc cụ thể hơn:

Lời nhắc:

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

Hoặc phiên bản khác:

Lời nhắc:

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 cung cấp cho chúng ta những thay đổi chính xác mà chúng ta cần thực hiện trong tệp manifest.json và cả javascript chúng ta cần trong tệp content.js.

Khi thêm content_scripts, tệp kê khai sẽ trở thành:

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

Thao tác này sẽ yêu cầu Chrome chèn tập lệnh nội dung content.js mỗi khi chúng ta chuyển đến một trang trong miền con " https://meet.google.com". Hãy thêm tệp này và kiểm thử nó.

Hãy thêm mã này vào tệp content.js.

console.log("Hello Gemini");

Chắc chắn rồi! Khi truy cập vào meet.google.com, chúng tôi sẽ thấy thông báo "Xin chào Gemini" trên bảng điều khiển 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("Xin chào Gemini!");

🥰 6216bab627c31e6c.png.

d61631cd9962ffe5.png

Tuyệt vời! Bây giờ, chúng ta đã ở vị thế có thể thêm một số chức năng javascript cụ thể vào ứng dụng của mình. Hãy dành một chút thời gian và nghĩ về mục tiêu mà chúng tôi đang cố gắng đạt được.

Cải thiện kịch bản nội dung

Chúng ta muốn nhận được thông báo khi có người tham gia một cuộc họp khi chúng ta đang ở trên trang cuộc họp(Khi chúng ta có lựa chọn tham gia cuộc họp). Để đạt được điều này, hãy quan sát cách màn hình thay đổi về mặt hình ảnh khi cuộc họp trống so với khi có người tham gia cuộc họp.

Đây là giao diện khi không có ai trong cuộc họp.

fe5a0c95b20e7f72.png

Trong khi đó, đây là hình ảnh khi có một số người tham gia cuộc họp.

7a5ef60521d961cc.png.

Chúng ta có thể thấy 2 điểm khác biệt đáng chú ý ngay lập tức:

  1. Nội dung trạng thái thay đổi từ "Không có ai ở đây" với "[Người dùng] đang tham gia cuộc gọi này".
  2. Chúng ta có thể thấy hình ảnh của những người dùng đã tham gia cuộc gọi.

Cả hai thay đổi này đều mang lại hiệu quả cho chúng ta nếu chúng ta muốn biết liệu có ai tham gia cuộc họp hay không. Tuy nhiên, thay đổi sau có một số khả năng lấy thông tin về những người dùng đã tham gia. Vì vậy, hãy thử sử dụng các thay đổi đó.

Mở "Trình kiểm tra phần tử" trong Chrome bằng phím nóng ( Mac: Cmd + Opt + C / Win: Ctrl + Shift + C), sau đó nhấp vào hình ảnh của người dùng đã tham gia.

Chúng ta có thể nhận thấy rằng một hình ảnh có ít chuỗi lớp và thuộc tính tiêu đề của hình ảnh đó có tên của người dùng đã tham gia cuộc họp. Hơn nữa, thẻ hình ảnh này được gói trong một div có lớp U04fid. Sau khi thêm một số người tham gia vào cuộc họp thử nghiệm, chúng ta có thể thấy rằng div mẹ này lưu trữ nhiều hình ảnh(tương ứng với những người dùng khác nhau).

Vì vậy, chúng tôi cân nhắc một phần chiến lược:

  1. Phát hiện thời điểm div với lớp U04fid chứa phần tử bất kỳ.
  2. Nếu có thì điều đó có nghĩa là chúng ta có người tham gia trong cuộc họp.
  3. Thông báo cho người dùng.

Hãy quay lại với Gemini và tìm hiểu cách chúng ta có thể từng bước đạt được mục tiêu này.

Lời nhắc:

How to detect for element changes in the HTML page?

API này cung cấp cho chúng ta một giải pháp liên quan đến MutationObserver, nhưng không cụ thể gì cho yêu cầu của chúng ta. Hãy thử sửa đổi câu lệnh.

Lời nhắc:

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

Lần này, chúng ta nhận được một giải pháp không bao gồm MutationObserver nhưng là giải pháp để kiểm tra các tham gia bằng cách sử dụng div mẹ.

Dưới đây là những gì chúng tôi đã nhận được:

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

Hãy thử sửa đổi phương pháp tiếp cận của chúng ta nhiều hơn nữa:

Lời nhắc:

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.

Trường này sẽ trả về cùng với đoạn mã sau:

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

Sao chép mã này vào tệp content.js, tải lại tiện ích(sau đó tải lại trang cuộc họp).

Giờ đây, khi có người tham gia cuộc họp, chúng ta có thể xem câu lệnh nhật ký trong bảng điều khiển.

5. Gửi thông báo cho người dùng

Giờ đây, khi chúng ta có thể phát hiện khi một người tham gia đã tham gia cuộc họp, hãy thử thêm phần thông báo vào tiện ích của Chrome. Chúng ta có thể duyệt qua tài liệu về tiện ích của Chrome hoặc thậm chí là điều chỉnh lời nhắc để biết nội dung chúng ta đang tìm kiếm, nhưng về cơ bản, chúng ta cần sử dụng API chrome.notifications.create và lệnh gọi đến phương thức này phải được thực hiện từ một trình chạy dịch vụ nền.

Lời nhắc:

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

Chúng ta sẽ thấy một số bước chi tiết với những điểm nổi bật chính như sau:

  • Thêm quyền notifications vào tệp kê khai.
  • Gọi đến chrome.notifications.create
  • Cuộc gọi phải ở trong một tập lệnh nền.

Để thêm tập lệnh nền vào một tiện ích của Chrome trong manifest version 3, chúng ta cần khai báo background.service_worker trong tệp manifest.json.

Vì vậy, chúng ta tạo một tệp có tên background.js và thêm đoạn mã sau vào tệp manifest.json.

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

Với những bổ sung trên, tệp kê khai của chúng ta sẽ trở thành:

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

Lời nhắc:

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

Lưu hình ảnh này vào gốc của thư mục rồi đổi tên thành success.png.

b2c22f064a3f2d9c.png

Sau đó, hãy thêm đoạn mã sau vào background.js.

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

Bây giờ, hãy tải lại tiện ích từ trang tiện ích và bạn sẽ thấy ngay một cửa sổ thông báo bật lên.

6. Thêm lệnh truyền thông báo vào tiện ích của Chrome

Bây giờ, bước quan trọng cuối cùng chúng ta cần là kết nối tính năng phát hiện người tham gia của tập lệnh nội dung và phương thức sendNotification trong tập lệnh nền. Đối với các tiện ích của Chrome, bạn có thể thực hiện việc này thông qua một kỹ thuật có tên là message passing.

Điều này cho phép giao tiếp giữa các phần khác nhau của tiện ích Chrome, trong trường hợp của chúng ta là từ tập lệnh nội dung đến trình chạy dịch vụ nền. Hãy hỏi người bạn Gemini của chúng ta cách đạt được điều đó.

Lời nhắc:

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

Gemini trả lời bằng các cuộc gọi liên quan đến chrome.runtime.sendMessagechrome.runtime.onMessage.addListener.

Về cơ bản, chúng ta sẽ sử dụng sendMessage để gửi thông báo từ tập lệnh nội dung mà ai đó đã tham gia cuộc gọi Meet và onMessage.addListener làm trình nghe sự kiện để phản ứng với thông báo do tập lệnh nội dung gửi. Trong trường hợp này, chúng ta sẽ kích hoạt lệnh gọi đến phương thức sendNotification từ trình nghe sự kiện này.

Chúng ta sẽ truyền nội dung thông báo và thuộc tính action đến trình chạy dịch vụ nền. Thuộc tính action mô tả nội dung mà tập lệnh nền đang phản hồi.

Dưới đây là mã content.js của chúng tôi:

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

Và đây là mã background.js của chúng ta:

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

Hãy thử tuỳ chỉnh nội dung thông báo và nhận mã thông báo duy nhất. Đối với nội dung thông báo, chúng ta có thể bao gồm tên của người dùng. Nếu nhớ lại từ bước trước, chúng ta có thể thấy tên của người dùng trong thuộc tính tiêu đề của hình ảnh. Vì vậy, chúng ta có thể tìm nạp tên người tham gia bằng document.querySelector('div.U04fid > img').getAttribute('title').

Đối với mã thông báo, chúng ta có thể tìm nạp mã thẻ của tập lệnh nội dung và sử dụng mã đó làm mã thông báo. Bạn có thể thực hiện việc này bên trong trình nghe sự kiện chrome.runtime.onMessage.addListener bằng cách sử dụng sender.tab.id.

Cuối cùng, các tệp của chúng ta sẽ có dạng như sau:

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. Xin chúc mừng

Chỉ trong một thời gian ngắn, chúng tôi đã có thể phát triển một tiện ích của Chrome với sự trợ giúp của Gemini. Cho dù bạn là một nhà phát triển tiện ích của Chrome có kinh nghiệm hay chỉ mới biết đến thế giới tiện ích, Gemini đều có thể giúp bạn thực hiện mọi công việc mà bạn muốn đạt được.

Bạn nên hỏi về những việc mà bạn có thể làm với tiện ích của Chrome. Có nhiều API đáng để bạn duyệt xem như chrome.storage, alarms, v.v. Bất cứ khi nào bạn gặp khó khăn, hãy sử dụng Gemini hoặc tài liệu để biết mình đang làm gì sai hoặc để thu thập nhiều cách giải quyết vấn đề.

Thông thường, bạn sẽ phải sửa đổi câu lệnh để nhận được sự trợ giúp cần thiết, nhưng chúng ta có thể thực hiện việc này từ một thẻ giúp lưu giữ toàn bộ hành trình theo ngữ cảnh.