25

What is the proper way to send a message (and get a response) to background.js from popup.js in a Chrome extension? Every method I try ends up with an error that:

"Port: Could not establish connection. Receiving end does not exist."

I would prefer to use chrome.extension.sendMessage() over chrome.extension.connect() with port.postMessage(), but neither method seems to have worked.

What I am trying to do is wire a button in the popup.html to call into some javascript in popup.js which calls back to background.js in an effort to get info about the currentTab() that was topMost (ie:to get the current URL string to show in the popup.html)

Right now in popup.js (wired to the action of the button) I have:

function getURL()
{
   chrome.extension.sendMessage({greeting: "GetURL"}, 
          function(response) { tabURL = response.navURL });

   $("#tabURL").text(tabURL);
}

In background.js I have:

chrome.extension.onMessage.addListener( function(request,sender,sendResponse)
{
    if( request.greeting == "GetURL" )
    {
        var tabURL = "Not set yet";
        chrome.tabs.getCurrent(function(tab){
            tabURL = tab.url;
        });

        sendResponse( {navURL:tabURL} );
    }
}

Any ideas?

Dana Epp
  • 509
  • 1
  • 5
  • 13
  • see this answer on https://stackoverflow.com/questions/13546778/how-to-communicate-between-popup-js-and-background-js-in-chrome-extension/47545616#47545616 – GorvGoyl Nov 29 '17 at 05:27

1 Answers1

38

Just to clarify, we talking about communication between popup page from browserAction and background script?

Anyway you have quite a few errors in your code.

First your totally ignore the fact that all callbacks in chrome api are asynchronous.

In background page

    var tabURL = "Not set yet";
    chrome.tabs.getCurrent(function(tab){
        tabURL = tab.url;
    }); //this will be invoked somewhere in the future

    sendResponse( {navURL:tabURL} ); 
    //navUrl will be always Not set yet because callback of getCurrent hasn't been called yet

Same in popup.js

chrome.runtime.sendMessage({greeting: "GetURL"}, 
          function(response) { tabURL = response.navURL });//callback will be invoked somewhere in the future

$("#tabURL").text(tabURL)//tabURL will display something totally different from what you have been expected

Second error is that chrome.tabs.getCurrent doesn't give you the current tab selected by user in main window. The docs says:

Gets the tab that this script call is being made from. May be undefined if called from a non-tab context (for example: a background page or popup view).

So you will get undefined for all of your requests, because you call it in background page. What you need to do is to use method chrome.tabs.query to obtain currently active tabs.

So after fixing all problems new code should look something like this:

background.js

chrome.runtime.onMessage.addListener( function(request,sender,sendResponse)
{
    if( request.greeting === "GetURL" )
    {
        var tabURL = "Not set yet";
        chrome.tabs.query({active:true},function(tabs){
            if(tabs.length === 0) {
                sendResponse({});
                return;
            }
            tabURL = tabs[0].url;
            sendResponse( {navURL:tabURL} );
        });        
    }
}

popup.js

function getURL() {
    chrome.runtime.sendMessage({greeting: "GetURL"},
        function (response) {
            tabURL = response.navURL;
            $("#tabURL").text(tabURL);
        });
}
JiiB
  • 1,432
  • 1
  • 12
  • 26
jusio
  • 9,850
  • 1
  • 42
  • 57
  • 11
    Just to note, it looks like the Chrome extension API has deprecated chrome.extension.sendMessage and replaced it with chrome.runtime.sendMessage: https://developer.chrome.com/extensions/messaging – Kevin Qi Sep 27 '14 at 18:56
  • And how does it work vice-versa? From background.js to popup.js? Thanks. €dit: ok, got it, it’s basically exactly the same just the other way around.. – chitzui Oct 18 '17 at 07:55