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.
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).
chrome.tabs.getSelected(...)
method, which you should avoid. Use chrome.tabs.query({active: true, highlighted: true}, ...)
instead.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 returntrue
from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end untilsendResponse
is called).
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
}
}
You can find a working example I made for testing HERE.
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
methodchrome.tabs.sendMessage
methodchrome.runtime.onMessage
eventIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With