TransWikia.com

Chrome extension message passing not working (background.js to content.js)

Stack Overflow Asked by Chase Alder on October 23, 2020

I am at my wits end with trying to figure out why I can’t get message passing to work in my Chrome extension.

Keep in mind, I am absolutely brand new to javascript within the last month and I’ve been teaching myself with videos online (my coding background is exclusively java).

All I want is for my background script to be able to notify my content script of something happening and then subsequently have some code execute within the content script. As you can see below, I have set up my code identically to the documentation, and yet it’s not working!

Here are the errors that I am getting when I load the extension:

Errors

manifest.json

{
   "content_scripts": [
      {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
      }
   ],

   "background": {
      "scripts": ["background.js"],
      "persistent": true
    },

   "permissions": [
      "activeTab",
      "tabs",
      "storage"
   ],

   "manifest_version": 2,
   "name": "eSports YT Viewer",
   "version": "1.0.0",
   "description": "An eSports viewer for youtube"
}

background.js

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
   chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
      console.log(response.farewell);
   });
});

content.js

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
      console.log(sender.tab ?
      "from a content script:" + sender.tab.url :
      "from the extension");
      if (request.greeting == "hello") {
         sendResponse({farewell: "goodbye"});
      }
});

Any help is massively appreciated! Thanks.

2 Answers

Your current background script is wrong or rather doesn't do anything meaningful/useful. The background script runs in a separate hidden background page. See also Accessing console and devtools of extension's background.js.

A persistent background script runs when a) the browser profile starts, b) when the extension is re-enabled/re-loaded, or c) installed. So, your code immediately queries the tabs and sends a message to whatever tab is active, hence there's no guarantee it even contains a web page: there can be nothing (an empty new tab) or it can be an internal chrome:// page for browser settings or the tab may still be pending content script execution (see the note at the end of this answer).

Switching the background script to "persistent": false won't help you either. It will only make the script wake up on an API event or when the popup is opened, but you're not registering any API events nor have you declared a popup. You should switch to "persistent": false anyway but for a different reason: to have it running only on demand.

Solution

The usual purpose of the background script is to register handlers for chrome API events such as chrome.tabs.onUpdated or chrome.webNavigation.onHistoryStateUpdated and so on, otherwise it's highly probable you don't need the background script at all. In the event handler you can send a message to the tab. A lot of people mistakenly send it to the active tab but usually it doesn't make sense as the event may have occurred in an inactive/backgrounded tab. Usually you should send it to the tab that generated the event, look for tab or tabId in the parameter passed to the handler, refer to the documentation on those events.

Also note that the content scripts run after DOMContentLoaded by default so if you send a message while the page is still loading it'll fail. In that case you can either run them at document_start or use a different approach e.g. don't declare a content script but rather inject it programmatically. There's no universal answer, it depends on the use case.

If you really need to send a message to the content script on extension startup/restart then you'll have to reload all matching tabs first via chrome.tabs.reload (so the content scripts will run automatically) or reinject the scripts explicitly.

Correct answer by wOxxOm on October 23, 2020

Everything looks to be in order from what I can see in your post, so i'm just throwing ideas out:

I think the clue to the error here is the first error, not the second -- it looks like the communication between the scripts hasn't established correctly.

Possibly try changing the persistent setting of your background script to false:

"background": {
  "scripts": ["background.js"],
  "persistent": false
},

From the docs, that is only required if you are modifying network requests, using the chrome.webRequest API and may be causing some strange problem with the set up here.

But as I said, only an initial guess.

Good luck!

Answered by tgallacher on October 23, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP