1

I'm working on a Chrome extension that involves message passing from the background script to the content script via a message port. According to the documentation I have to first query for the tab where the content script I want to connect to is running and then open a port using that Tab's ID. So my background script and content script look like the following:

background.js

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    var port = chrome.tabs.connect(tabs[0].id, { name: "example" });
    port.postMessage("hello world");
});

content_script.js

chrome.runtime.onConnect.addListener(function(port) {
    port.onMessage.addListener(function(msg) {
        console.log(msg);
    });
});

And no message is printed to the console. I did some debugging first by putting break point on this line in content_script port.onMessage.addListener(function(msg) { which was never hit. This led me to believe that the port was never opened in background.js. So next, I put a break point in background.js at this line var port = chrome.tabs.connect(tabs[0].id, { name: "example" }); by using the dev tools accessed here

enter image description here

and it turns out that my query isn't actually returning any tabs into the callback so tabs[0].id raises an error. I'm guessing that once I get this tab query to work the message passing will start working, so does anyone have any idea what's going on here that I can't query for the current, active tab? I've seen this exact query used in many other StackOverflow responses and it's in an example in the message passing docs.

azrosen92
  • 8,357
  • 4
  • 26
  • 45

1 Answers1

3

Please ensure the current active tab is allowing content scripts to be injected, I mean, when you call chrome.tabs.query in background page, the active tab page is not chrome://extensions page. This usually happens when you reload the extension, in this case, after you called chrome.tabs.query({active: true, currentWindow: true}), you would get the tab with chrome://extensions url, while this page doesn't allow content scripts to be injected by default.

To avoid this, you could adjust your message passing ways:

  1. You could starting the message passing from content scripts.
  2. You could also add some other trigger point to start the message passing. For example, calling chrome.tabs.query when browserAction is clicked.
Haibara Ai
  • 10,703
  • 2
  • 31
  • 47
  • My solution was to start the message passing from the content script. Thanks! I'm still kind of curious why doing it the other way around doesn't work, and if it's not possible to do it that way, why Chrome's documentation has an example of doing it that way. – azrosen92 Sep 28 '16 at 14:08
  • 1
    @azrosen92, I'm not saying it doesn't work when starting from background page. It's just because the timing is not appropriate since the query result is `chrome://extensions` page which can't be injected with content scripts. You could try the second way, adding a specific trigger point. – Haibara Ai Sep 29 '16 at 02:31
  • In my case the problem was that I was testing my extension and the tabs I had to communicate with wouldn't receive anything unless I reloaded them after reloading the extension. The content scripts of existing tabs aren't refreshed automatically when you reload the extension. P.S.: [This answer](https://stackoverflow.com/a/23895822/3514976) explains it well. – nonzaprej Apr 02 '18 at 20:38