0

My Flow of Extension is:

  1. User goes to options page (options.js) and adds a url (e.g. youtube.com). This url is stored in storage and sends a message 'NewURL' to background.js
  2. background.js on getting 'NewURL' message, injects JS called injected.js into all tabs where url matches (i.e. all open youtube.com tabs)
  3. This injected script is basically listening to message (message.type = StartTimer)and logging whenever the message is received
  4. popup.js has start timer button which sends message 'StartTimer' to all the listeners

I see that injected.js prints the message on getting injected but after that it does not log 'StartTimer' when popup.js start time button is clicked.

Now in code

options.js
const saveBtn = document.getElementById("save-btn")
saveBtn.addEventListener("click", () => {
    chrome.storage.local.set({
        block_urls: block_urls
    })
    chrome.runtime.sendMessage({ type: "NewURL"})
    alert('Settings Saved!')
})

background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log('chrome.runtime.onMessage.addListener: ', message)
    if (message.type === "NewURL") {
        console.log('background.js: NewURL')
        injectJS()
    }
})

function injectJS() {
    let blockUrlList = []
        
    chrome.storage.local.get(["block_urls"], async (res) => {
        blockUrlList = "block_urls" in res ? res.block_urls : []
        try {
            let qryOptions = { "url": blockUrlList.map(p => `*://*.${p}/*`)}
            let tabs = await chrome.tabs.query(qryOptions) 
            tabs.forEach((tab) => {
                console.log('injecting into tab', tab.id, tab.url)
                chrome.scripting.executeScript({
                    target: {tabId: tab.id},
                    files: ['content/injected.js']
                })
            });
        } catch(err) {
            console.log('No matching tab', err)
        }
        
    })
}

injected.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "StartTimer") {
        console.log('injected.js: start timer')
    } else if(message.type === "StopTimer"){
        console.log('injected.js: stop timer')
    }
  });

 console.log("you have been injected") 

popup.js
const startTimerBtn = document.getElementById("start-timer-btn")
startTimerBtn.addEventListener("click", () => {
    chrome.runtime.sendMessage({ type: "StartTimer"})
})

I see in console of the open tab the message "you have been injected". However, I do not see subsequently 'injected.js: start timer'

Also I have two additional questions

  1. How do I prevent injecting multiple times in one of the open tab
  2. When a new tab is opened (or this tab is refreshed), how is javascript re-injected?
Ani
  • 265
  • 1
  • 3
  • 10
  • 1
    `injected.js` is content script, so as https://developer.chrome.com/docs/extensions/reference/runtime/#method-sendMessage explicitly points out: *Note that extensions cannot send messages to content scripts using this method. To send messages to content scripts, use [`tabs.sendMessage`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-sendMessage).* – tevemadar May 06 '23 at 22:29
  • 1
    See also [Avoid dynamically injecting the same script multiple times](https://stackoverflow.com/a/23214784). – wOxxOm May 07 '23 at 04:30
  • solution if (window.contentScriptInjected !== true) {window.contentScriptInjected = true; } works, thank you. Is it the best practice? I was trying using variable if(typeof injected === 'undefined') { const init = 'injected'; chrome.runtime.onMessage.addListener()...}. However, that does not work. maybe its better to ask a separate question – Ani May 08 '23 at 09:52

0 Answers0