Can't send messages between Popup.js and ContentScript.js

2,048 views
Skip to first unread message

Shervin Antony

unread,
Jul 22, 2023, 12:57:13 AM7/22/23
to Chromium Extensions
Hello,

I have this part of my contentscript.js that listens to messages from popup.js and if there is any, then it starts a timer for some time.

This is my contentScript.js

  chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.hasOwnProperty('focusPointsInMilliseconds')) {
      console.log('Focus points received: ', message.focusPointsInMilliseconds);
 
      if (!isNaN(timer)) {
        clearTimeout(timer);
      }
 
      const isFreeTimePeriod = true;
      const timer = setTimeout(() => {
        isFreeTimePeriod = false;
        console.log('Free time period ended.');
      }, message.focusPointsInMilliseconds * 60 * 1000);
    }
  });

The popup.js gets a value from an external server that i made in fastapi and python(that works completely fine) and if the button in the popup.html is clicked, the popup.js fetches from that server and sends that information to the content script.js shown above.

this is my popup.js
window.onload = function() {
    document.getElementById("myButton").addEventListener("click", function() {
        .then(response => response.json())
        .then(data => {
          console.log('Data: ', data)
          chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, { focusPointsInMilliseconds: data.focusPoints });
          });
        })
        .catch(error => console.error('Error:', error));
    });
  };
 

The problem is that whenever i click the button on the chrome extension, it never works or starts the timer, i have no idea why. I tried debugging it by using console.log statements around it but it never worked and always showed an empty array outputted.

Can anyone tell me or figure out the problem here and a possible solution?

Thanks and have a nice day!
Shervin


wOxxOm

unread,
Jul 22, 2023, 3:36:09 AM7/22/23
to Chromium Extensions, Shervin Antony
Generally, you need to re-inject content scripts explicitly after reloading/installing the extension in Chrome, see https://stackoverflow.com/q/10994324

A better solution in case you only need to communicate with the tab after clicking the extension icon is to inject the content script in the popup script on demand e.g. remove `content_scripts` from manifest.json, add "activeTab" and "scripting" to "permissions", then use chrome.scripting.executeScript when sendMessage fails.

document.getElementById('myButton').onclick = async () => {
  const data = await (await fetch('http://localhost:8000/focus_points/she...@gmail.com')).json();
  const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
  for (const pass of [1, 2]) {
    try {
      await chrome.tabs.sendMessage(tab.id, {focusPointsInMilliseconds: data.focusPoints});
      break;
    } catch (err) {
      await chrome.scripting.executeScript({target: {tabId}, files: ['contentScript.js']})
    }
  }
};


Shervin Antony

unread,
Jul 22, 2023, 12:47:54 PM7/22/23
to Chromium Extensions, wOxxOm, Shervin Antony
Thank you for replying and taking your time to answer,

The issue is that contentscript.js has a background task running that must happen at all times and not just when the extension icon is pressed on. Do you have an idea of how to circumvent this as well?

Thanks,
Shervin

wOxxOm

unread,
Jul 22, 2023, 12:57:04 PM7/22/23
to Chromium Extensions, Shervin Antony, wOxxOm
Yes, it's explained at the beginning of my message with a link to an example.

Rajat Paharia

unread,
Nov 17, 2023, 10:59:09 AM11/17/23
to Chromium Extensions, wOxxOm, Shervin Antony
wOxxOm - thank you for documenting how to do this! 

I implemented it yesterday and it seemed to work great. Then I woke up this morning and it looked like my Chrome had updated and now it no longer works.
Uncaught (in promise) Error: Cannot access contents of the page. Extension manifest must request permission to access the respective host.

 It doesn't appear to fail on the same tab every time. I'm trying to figure out if it's related to the new version of Chrome or whether I missed something. I tried adding the "activeTab" permission and that didn't help. Any guidance would be appreciated, thanks!

Version 119.0.6045.159 (Official Build) (arm64)

"permissions": [
"storage",
"sidePanel",
"tabs",
"scripting"
],
"content_scripts": [
{
"js": ["scripts/content.js"],
"matches": ["http://*/*", "https://*/*" ]
}
],
"host_permissions": [
"http://*/*",
"https://*/*"
],

chrome.runtime.onInstalled.addListener(async () => {
for (const cs of chrome.runtime.getManifest().content_scripts) {
for (const tab of await chrome.tabs.query({url: cs.matches})) {
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: cs.js,
});
}
}
});

wOxxOm

unread,
Nov 17, 2023, 11:09:34 AM11/17/23
to Chromium Extensions, Rajat Paharia, wOxxOm, Shervin Antony
Your code looks fine, so this could be an old error as Chrome deceptively doesn't show the timestamp. Click the "clear all" button and reload the extension.

Rajat Paharia

unread,
Nov 17, 2023, 11:18:32 AM11/17/23
to Chromium Extensions, wOxxOm, Rajat Paharia, Shervin Antony
Thank you for the fast response wOxxOm! 

I've "clear all"ed many times, and the errors reappear as soon as I hit the reload button on the extension. Only commenting out the code stops the errors from happening. I added some logging and here's what I see in the service worker console. 
Screenshot 2023-11-17 at 10.13.47 AM.png

if I highlight some other tabs or close some, then it errors at a different point. 
Screenshot 2023-11-17 at 10.15.06 AM.png

Anyway, I will comment it out for now and maybe it will fix itself later :) Thank you! 

wOxxOm

unread,
Nov 17, 2023, 11:21:50 AM11/17/23
to Chromium Extensions, Rajat Paharia, wOxxOm, Shervin Antony
You can add .catch(e => console.log(tab.url, e)) after executeScript's last })
I guess some site is forbidden via ExtensionSettings policy, which you can verify in chrome://policies
Another common cause is using the Opera browser, which forbids injection on the search page (like www.google.com) by default unless you enable it in chrome://extensions.

Rajat Paharia

unread,
Nov 17, 2023, 11:33:31 AM11/17/23
to Chromium Extensions, wOxxOm, Rajat Paharia, Shervin Antony
Oh, that's super interesting. I added that code and saw that it was catching errors on calendar.google.com and github.com
I closed those tabs and the errors went away. 
But then I reopened them (CMD-SHIFT-T) and the errors are still gone, which is... unexpected. 

Thank you for the help!

Rajat Paharia

unread,
Jan 12, 2024, 1:54:28 PM1/12/24
to Chromium Extensions, Rajat Paharia, wOxxOm, Shervin Antony
Just noticed that this problem reappears every time I quit Chrome and then reopen it. After Chrome reopens I reload my extension and in the service worker console I get something that looks like this for every tab: 
[URL] Error: Cannot access contents of the page. Extension manifest must request permission to access the respective host.
Going to each tab and reloading it removes the error. 
I'd assume it has something to do with Chrome's Memory Saver? So the tabs aren't "properly" loaded on restart until you actually click on them? 
Not a big deal, just an annoying error message...

Reply all
Reply to author
Forward
0 new messages