1. Introdução
Você vai participar de uma chamada do Meet, mas não quer ser o primeiro? Se for o caso, temos a solução para você.
Neste codelab, você vai criar uma extensão do Chrome que alerta quando o primeiro participante entra na chamada.
Você vai aprender os diferentes elementos de uma extensão do Chrome e, em seguida, se aprofundar em cada parte dela. Você vai aprender sobre funções de extensão, como scripts de conteúdo, service workers e passagem de mensagens.
É necessário seguir a versão 3 do manifesto para receber uma notificação sempre que um participante entrar em uma chamada do Meet.
2. Antes de começar
Pré-requisitos
Embora este codelab seja adequado para iniciantes, ter um conhecimento básico de JavaScript pode melhorar muito sua experiência.
Configuração/requisitos
- O navegador Chrome
- Uma configuração de IDE/editor no seu sistema local.
- Instale a CLI gcloud se quiser ativar a API Gemini usando o gcloud.
Ativar a API Gemini
- No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Confira se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto.
- Acesse a página do Gemini Marketplace para ativar a API. Você também pode usar o gcloud para ativar a API:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID - Acesse a página do console do Gemini para o Cloud em uma nova guia e clique em "Iniciar conversa".
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. Que a diversão comece
Instalação básica da extensão
Vamos criar um diretório que será usado como raiz do nosso projeto.
mkdir gemini-chrome-ext
cd gemini-chrome-ext
Antes de começar a fazer perguntas específicas ao Gemini, vamos fazer algumas perguntas sobre a estrutura genérica de uma extensão do Chrome.
Comando:
What are the important parts to build a chrome extension?
Recebemos uma resposta que especifica detalhes menores sobre o arquivo manifest, o background script e detalhes sobre a interface do usuário. Vamos entrar em mais detalhes sobre esses arquivos específicos.
Comando:
Create a manifest.json file to build a chrome extension. Make the name of the extension "Meet Joinees Notifier" and the author "<YOUR_EMAIL>"
Você pode usar um nome desejado e seu e-mail no campo do autor.
O Gemini retorna o conteúdo do arquivo de manifesto de que precisamos, mas recebemos alguns campos extras que não serão necessários, como o campo action. Além disso, precisamos de uma descrição. Vamos corrigir isso.
Comando:
Remove the "action" field and make the description as "Adds the ability to receive a notification when a participant joins a Google meet".
Vamos colocar esse conteúdo no arquivo manifest.json na raiz do seu projeto.
Nessa fase, o arquivo de manifesto deve ser semelhante a este.
{
"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>"
}
Remova todos os outros campos adicionais gerados no arquivo de manifesto por enquanto, já que este codelab pressupõe esses campos no arquivo de manifesto.
Agora, como testamos se a extensão funciona? Vamos perguntar ao nosso amigo Gemini.
Comando:
Guide me on the steps needed to test a chrome extension on my local filesystem.
Ele me dá algumas etapas sobre como testar. Vamos navegar até a "Extensions Page" acessando chrome://extensions e ativar o botão "Developer Mode", que deve revelar o botão "Load unpacked", que podemos usar para navegar até a pasta que contém os arquivos de extensão localmente. Depois disso, poderemos ver a extensão na "Extensions Page".


Ótimo! Podemos ver nossa extensão, mas vamos começar a adicionar algumas funcionalidades.
4. Adicionar um script de conteúdo
Queremos executar algum código JavaScript apenas em https://meet.google.com, o que podemos fazer usando scripts de conteúdo. Vamos perguntar ao Gemini como fazer isso na nossa extensão.
Comando:
How to add a content script in our chrome extension?
Ou mais especificamente:
Comando:
How to add a content script to run on meet.google.com subdomain in our chrome extension?
Ou outra versão:
Comando:
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".
O Gemini nos dá as mudanças exatas que precisamos fazer no arquivo manifest.json e também o JavaScript de que precisamos no arquivo content.js.
Com a adição de content_scripts, nosso arquivo de manifesto se torna:
{
"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"]
}
]
}
Isso informa ao Chrome para injetar o script de conteúdo content.js sempre que navegamos para uma página no subdomínio " https://meet.google.com". Vamos adicionar esse arquivo e testá-lo.
Vamos adicionar esse código ao arquivo content.js.
console.log("Hello Gemini");
Com certeza! Quando acessamos meet.google.com, vemos "Hello Gemini" no console 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!");


Ótimo! Agora estamos em uma posição em que podemos adicionar algumas funcionalidades específicas de JavaScript ao nosso app. Vamos pensar um pouco sobre o que estamos tentando alcançar.
Melhorar o script de conteúdo
Queremos receber uma notificação quando alguém entrar em uma reunião na página da reunião(onde temos uma opção para participar da reunião). Para isso, vamos observar como a tela muda visualmente quando a reunião está vazia e quando alguém participa da reunião.
É assim que aparece quando não há ninguém na reunião.

Esses são os recursos visuais quando há alguns participantes na reunião.

Podemos ver duas diferenças notáveis:
- O texto de status muda de "Ninguém mais está aqui" para "[Usuário] está nesta chamada".
- Podemos ver as imagens dos usuários que participaram da chamada.
Essas duas mudanças vão funcionar para nós se quisermos saber se alguém participou da reunião, mas a última tem algumas possibilidades de receber informações sobre os usuários que já participaram. Então, vamos tentar usar isso.
Abra o "Elements Inspector" no Chrome com a tecla de atalho ( Mac: Cmd + Opt + C / Win: Ctrl + Shift + C) e clique na imagem do usuário que participou.
Podemos notar que há uma imagem com algumas strings de classe e o atributo de título da imagem tem o nome do usuário que participou da reunião. Além disso, essa tag de imagem está envolvida em uma div com a classe U04fid. Depois de adicionar alguns participantes à nossa reunião de teste, podemos ver que essa div pai hospeda várias imagens(correspondentes a diferentes usuários).
Então, temos uma estratégia parcial em mente:
- Detectar quando a div com a classe
U04fidcontém elementos. - Se isso acontecer, significa que temos participantes na nossa reunião.
- Notificar o usuário.
Vamos voltar ao Gemini e perguntar como podemos fazer isso passo a passo.
Comando:
How to detect for element changes in the HTML page?
Ele nos dá uma solução que envolve MutationObserver, mas nada específico para nossa exigência. Vamos tentar modificar o comando.
Comando:
How can I detect if an element "div.U04fid" has any child images in the HTML page?
Desta vez, recebemos uma solução que não inclui o MutationObserver, mas uma solução que verifica os participantes usando a div pai.
Isso é o que recebemos:
const divU04fid = document.querySelector('div.U04fid');
const childImages = divU04fid.querySelectorAll('img');
if (childImages.length > 0) {
// div.U04fid has at least one child image.
}
Vamos tentar modificar nossa abordagem ainda mais:
Comando:
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.
Ele retorna com o seguinte snippet de código:
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
});
Copie esse código para o arquivo content.js, recarregue a extensão(e recarregue a página do Meet).
Agora, quando alguém participa da nossa reunião, podemos ver a instrução de registro no console.
5. Enviar uma notificação ao usuário
Agora que podemos detectar quando um participante entrou na reunião, vamos tentar adicionar a parte de notificação na nossa extensão do Chrome. Podemos navegar pela documentação da extensão do Chrome ou até mesmo ajustar os comandos para saber o que estamos procurando, mas essencialmente precisamos usar a API chrome.notifications.create, e a chamada para esse método precisa ser de um service worker em segundo plano.
Comando:
Using the documentation for chrome notifications tell me how to use the chrome.notifications.create method.
Vemos algumas etapas detalhadas com os principais destaques:
- Adicione a permissão
notificationsno arquivo de manifesto. - Faça uma chamada para chrome.notifications.create
- A chamada precisa estar em um script em segundo plano.
Para adicionar um script em segundo plano a uma extensão do Chrome na manifest version 3, precisamos da declaração background.service_worker no nosso arquivo manifest.json.
Então, criamos um arquivo chamado background.js e adicionamos o seguinte ao nosso arquivo manifest.json.
"background": {
"service_worker": "background.js"
},
"permissions": [
"notifications"
]
Com as adições acima, nosso arquivo de manifesto se torna:
{
"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"
]
}
Comando:
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
Salve essa imagem na raiz da pasta e renomeie-a para success.png.

Em seguida, adicione o seguinte snippet de código ao 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");
Agora, recarregue a extensão na página de extensões e você vai receber um pop-up de notificação imediatamente.
6. Adicionar passagem de mensagens na extensão do Chrome
Agora, a última etapa principal de que precisamos é conectar a detecção de um participante do script de conteúdo e o método sendNotification no script em segundo plano. No contexto das extensões do Chrome, a maneira de fazer isso é por meio de uma técnica chamada message passing.
Isso permite a comunicação entre diferentes partes de uma extensão do Chrome, no nosso caso, do script de conteúdo para o service worker em segundo plano. Vamos perguntar ao nosso amigo Gemini como fazer isso.
Comando:
How to send a message from the content script to the background script in a chrome extension
O Gemini responde com chamadas relevantes para chrome.runtime.sendMessage e chrome.runtime.onMessage.addListener.
Essencialmente, vamos usar sendMessage para enviar uma mensagem do script de conteúdo de que alguém participou da chamada do Meet e o onMessage.addListener como um listener de eventos para reagir à mensagem enviada pelo script de conteúdo. Nesse caso, vamos acionar a chamada para o método sendNotification desse listener de eventos.
Vamos transmitir a mensagem de notificação e uma propriedade action para o service worker em segundo plano. A propriedade action descreve a resposta do script em segundo plano.
Então, aqui está nosso código 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) {
// 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"
});
}
E este é o nosso código background.js:
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"
});
}
Vamos tentar personalizar a mensagem de notificação e receber um ID de notificação exclusivo. Para a mensagem de notificação, podemos incluir o nome do usuário. Se nos lembrarmos de uma etapa anterior, poderemos ver o nome do usuário no atributo de título da imagem. Assim, podemos buscar o nome do participante usando document.querySelector('div.U04fid > img').getAttribute('title').
Em relação ao ID de notificação, podemos buscar o ID da guia do script de conteúdo e usá-lo como um ID de notificação. Isso pode ser feito no nosso listener de eventos chrome.runtime.onMessage.addListener usando sender.tab.id..
Por fim, nossos arquivos devem ser semelhantes a este:
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. Parabéns
Em pouco tempo, conseguimos criar uma extensão do Chrome com a ajuda do Gemini. Se você é um desenvolvedor de extensões do Chrome experiente ou novo no mundo das extensões, o Gemini pode ajudar você com todas as tarefas que quiser realizar.
Recomendamos que você pergunte sobre as diferentes coisas que podem ser feitas com uma extensão do Chrome. Há muitas APIs que valem a pena navegar, como chrome.storage, alarms etc. Sempre que você se sentir preso, use o Gemini ou a documentação para saber o que está fazendo de errado ou para reunir diferentes maneiras de resolver o problema.
Muitas vezes, é necessário modificar o comando para receber a ajuda necessária, mas podemos fazer isso em uma guia que mantém toda a nossa jornada contextual.