Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome extension message passing between content and background not working

I am developing a chrome extension, here are the main files:

background.js

getPageDimension = function (){
    chrome.tabs.getSelected(null, function(tab) {
        chrome.tabs.sendMessage(tab.id, { message: "DIMENSION" }, function(response){
            if (response != null) {
                console.log(response.x);
                console.log(response.y);
                console.log(response.w);
                console.log(response.h);
            }else{
                console.log('Response is null');
            }
        });
    }); 
};

content.js

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {        
    if (msg.message && (msg.message == "DIMENSION")) {                          
        var dimension = getPageDiemension(document.documentElement);        
        console.log(dimension.x);
        console.log(dimension.y);
        console.log(dimension.w);
        console.log(dimension.h);
        sendResponse({x: dimension.x, y: dimension.y,w: dimension.w,h: dimension.h});       
    }
});

getPageDiemension = function(currentDom){
    var dimension = new Object();
    dimension.x = 0;
    dimension.y = 0;
    dimension.w = currentDom.scrollWidth;
    dimension.h = currentDom.scrollHeight;
    return dimension;
}

So my aim is to get the full height and width of page loaded in current active tab. When I debug my content script, I get the proper response in my background.js, but if run the script without debugging, I get an undefined response in my background.js.

Here is the declaration of my cotent.js in my manifest.json file:

"content_scripts": [{
    "all_frames": true,
    "matches": [
        "http://*/*", "https://*/*"
    ],
        "js": ["content.js"]
}],

Kindly help me, where am I going wrong?. Let me know if you need any further data.

like image 585
Priyank Thakkar Avatar asked Jan 07 '15 16:01

Priyank Thakkar


1 Answers

Issues

There are two little problems in your code, which I found after a wile, since that it looks perfectly working (when it isn't at all).

  1. You're using the deprecated chrome.tabs.getSelected(...) method, which you should avoid. Use chrome.tabs.query({active: true, highlighted: true}, ...) instead.
  2. In your chrome.runtime.onMessage listener, in the content script, you are doing some calculations before sending the response: this makes the message channel close before you can send a response, and will result in a null response.

    Quoting from the official documentation:

    This function (sendResponse) becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).

Solution

Now that you know what the problems are, you can easily replace the old tabs.getSelected() with tabs.query(), and add a return true; statement in the handler of the runtime.onMessage event in your content script. The solution is the following, I also lightened the code a bit.

Your background.js:

getPageDimension = function (){
    chrome.tabs.query({active: true, highlighted: true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, { message: "DIMENSION" }, function(response){
            if (response !== null) console.log('Response:', response);
            else console.log('Response is null');
        });
    }); 
};

Your content.js:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {        
    if (msg.message && (msg.message == "DIMENSION")) {                          
        var dimension = getPageDiemension(document.documentElement); 
        console.log('Dimension:', dimension);
        sendResponse(dimension);       
    }
    return true;
});

getPageDiemension = function(currentDom){
    return { x: 0, y: 0,
        w: currentDom.scrollWidth,
        h: currentDom.scrollHeight
    }
}

Working example

You can find a working example I made for testing HERE.

Documentation links

Just for clarity, I'm leaving you some documentation links regarding the APIs involved in this extension that you may find helpful:

  • chrome.tabs API
    • chrome.tabs.query method
  • Chrome extension message passing
    • chrome.tabs.sendMessage method
    • chrome.runtime.onMessage event
like image 86
Marco Bonelli Avatar answered Sep 30 '22 08:09

Marco Bonelli