user1532510 user1532510 - 1 month ago 36
Javascript Question

Making Chrome Extension background function synchronous

Updated: this is @ViewSource solution which is correct, except you need a return true in background.js as shown.

I have a problem in my chrome extension design which I cant find a fix for no matter how many ways I configure it.

In my popup.js I have a button a button click event like this:

document.getElementById('btnUpload').addEventListener('click', function() {

sendDocMsg(windowUrl);

});

}

function sendDocMsg() {

chrome.runtime.sendMessage({url: decodeURIComponent(windowUrl)},
function(response){
currentHTML = response.data;

});


and in the background I have a handler for this:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
var url= message.url;
var doc = null;
script = getScript(url);
if(script!=null) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id, {action: "getDocument", data:script},
function(response) {
doc=response.data;
sendResponse({data: doc});
});
});
}
return true;


});

which should send the data from the content page back to popup.js (via background page), but for some reason, I'm getting:

Error in event handler for (unknown): TypeError: Cannot read property 'data' of undefined
at chrome-extension://kpcmhhlcnclcnahkpjpaejaccponfble/popup.js:125:31


I have set a breakpoint in the background, and the correct data is being set on the response. I initially had a function call from popup to background using
chrome.extension.getBackgroundPage()

becuase I read that this was the preferred way for popup to contact background, but this caused other issues.

Can anyone see why the data would be returned to popup.js please?

Answer

Communication within the extension works by using Message Passing. Use the background as a middleman between the content script and the popup.

  1. Call the background page from popup using chrome.runtime.sendMessage.
  2. Add a listener in the background page using chrome.runtime.onMessage.addListener.
  3. Inside the listener insert your call to content script.
  4. Send response to popup by using sendResponse() inside the callback function.

Your new code should look something like this:

popup.js:

chrome.runtime.sendMessage({url: decodeURIComponent(windowUrl)}, function(response){
  currentHTML = response.data;
});

background.js:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
     var url= message.url;
     var doc = null;
     script = getScript(url);
     if(script!=null) {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
           chrome.tabs.sendMessage(tabs[0].id, {action: "getDocument", data:script}, 
               function(response) {
                  doc=response.data;
                  sendResponse({data: doc});
           });  
        });
     }             
});
Comments