Sankeeth Ganeswaran
Sankeeth Ganeswaran

Reputation: 477

How to update HTML in inactive chrome tab with extension

I'm currently trying to make a Chrome extension, and I've ran into a problem where I don't know how to update HTML from an inactive tab. I'm trying to periodically access the HTML of a Google Meet in an inactive tab, to detect when people leave or join the call. However, document.querySelector only works when the tab is focused, as if it's not, it will just keep giving the same info from the last time it was focused, even if people have left or joined the call since then. Is there any way to detect these changes without having to focus the tab? Here is what I've tried in my code:

background.js

meetTab = []
// check for google meet tabs
function query()
{
    meetTab = []
    chrome.tabs.query({url: "https://meet.google.com/*-*"},function(tabs)
    {
        tabs.forEach(function(tab)
        {
            meetTab.push(tab)
        });
    })
}
chrome.tabs.onCreated.addListener(query)
chrome.tabs.onRemoved.addListener(query)
chrome.runtime.onStartup.addListener(query)
setInterval(send, 3000)
// execute script for each google meet tab every 3 sec
function send()
{

    meetTab.forEach(function(tab)
    {
        chrome.tabs.executeScript(tab.id, {file: "check.js"})
    })
}
// this part only prints updated info when meet tab is active
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    console.log(message)
});

check.js

// element to be tracked
thing = document.querySelector("#ow3 > div.T4LgNb > div > div:nth-child(9) > div.crqnQb > div.rG0ybd.xPh1xb.P9KVBf.LCXT6 > div.TqwH9c > div.SZfyod > div > div > div:nth-child(2) > div > div")
chrome.runtime.sendMessage({msg:thing.innerText})

manifest.json

{
  "manifest_version": 2,
  "name": "Meet Kicker",
  "version": "1.0",
  "icons": {"128": "bigicon.png"},
  "browser_action": {
    "default_icon": "smallicon.png",
    "default_popup": "popup.html"
  },
  "permissions": ["storage", "tabs", "<all_urls>"],

  "background":
  {
    "scripts": [
      "background.js"
    ]
  }
}

Updated check.js trying to use MutationObserver

thing = document.querySelector("#ow3 > div.T4LgNb > div > div:nth-child(9) > div.crqnQb > div.rG0ybd.xPh1xb.P9KVBf.LCXT6 > div.TqwH9c > div.SZfyod > div > div > div:nth-child(2) > div > div")

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
            chrome.runtime.sendMessage({msg:thing.innerText})

      });
    });

observer.observe(thing, { characterData: true, attributes: false, childList: false, subtree: true });

Upvotes: 2

Views: 725

Answers (1)

Robbi
Robbi

Reputation: 1507

I'd review things a little.

Doing a bit of order may perhaps solve the problem.

First thing I'd remove the "onRemoved" event handler which I don't see how it can serve the purpose.

Then I'd review the "onCreated" event handler so as not to re-inject the content script (CS) into all tabs which contain Google Meet (GM) but only to the newly opened tab (only if GM is obviously loaded in this latter).

I'd add the onUpdate event handler because if a tab is updated by loading GM inside it then it's good to inject the CS where it was not there before.

Let's talk now about the setInterval (which could be the cause of all\many of your problems).
Here we need to understand one thing (I state that I do not know much GM).
Q1: Does the node you want to check through querySelector lies in the page where you have already injected the CS or stays in a (i)frame?
Q2: Does the page or (i)frame containing that node reload over time? (you can see this with devtools Network panel or by using event handler such as tabs.onUpdate or webNavigation.onComplete)

If the monitored node belongs to a page that is reloaded periodically then it is right to re-inject the CS periodically. (which you can manage inside the onUpdate event handler and not with setInterval).

If, on the other hand, the page that contains (or will contain) the node is not reloaded and therefore the node appears in a moment that cannot be determined a priori then you don't have to re-inject but "observe" the mutations of the DOM (in practice you have to use the MutationObsever object).

Lastly, I advise you to check if you have installed extensions that optimize the CPU and memory and that could somehow interfere with your code.

Upvotes: 1

Related Questions