Message callback returns infrequently - Chrome extension
I am creating a chrome extension that communicates with a nodejs server via websockets. Its essence is to track your browsing history with content. Everything seems to work, but sometimes (30% of the time) the callback of the function passed to onMessage.addListener does not fire correctly. Let me show you the code:
background.js
var socket = io('http://localhost:3000/');
var tabLoad = function (tab) {
socket.emit('page load', tab);
};
var tabUpdate = function (tabid, changeinfo, tab) {
var url = tab.url;
if (url !== undefined && changeinfo.status == "complete") {
tab.user_agent = navigator.userAgent;
tab.description = '';
tab.content = '';
socket.emit('insert', tab);
}
};
socket.on('inserted', function(page){
socket.emit('event', 'Requesting page content\n');
//page = {tab: page, id: docs._id};
chrome.tabs.sendMessage(page.tab_id, {requested: "content", page: page}, function(data) {
socket.emit('content', data);
});
});
try {
chrome.tabs.onCreated.addListener(tabLoad);
chrome.tabs.onUpdated.addListener(tabUpdate);
} catch(e) {
alert('Error in background.js: ' + e.message);
}
content script - public.js
var messageHandler = function(request, sender, sendContent) {
if (request.requested == "content") {
var html = document.getElementsByTagName('html')[0].innerHTML;
var data = {
content: html,
page: request.page
};
sendContent(data);
return true;
}
};
chrome.extension.onMessage.addListener(messageHandler);
The problem is that sometimes the data in sendContent is undefined and sometimes everything is fine. Any ideas for debugging this or what I am doing wrong?
I tried replacing document.getElementsByTagName('html')[0].innerHTML
with hardcoded 'test' string but it didn't help.
Pages like youtube / wikipedia never work, but facebook / google does.
Edit: The sendContent callback fires 100% of the time when data is passed undefined to it.
Edit: Here's the manifest file
{
"manifest_version": 2,
"name": "Socket test",
"description": "sockets are cool",
"version": "1.0",
"permissions": [
"http://st-api.localhost/",
"http://localhost:3000/",
"tabs",
"background",
"history",
"idle",
"notifications"
],
"content_scripts": [{
"matches": ["*://*/"],
"js": ["public/public.js"]
//"run_at": "document_start"
}],
//"browser_action": {
// "default_icon": "logo.png",
// "default_popup": "index.html"
//},
"background": {
//"page" : "background.html",
"scripts": ["socket-io.js", "background.js"],
"persistent": true
}
}
source to share
First, your understanding of what is sendContent
done is 100% of the time wrong.
As pointed out in the comments, the callback is sendMessage
also executed when an error occurs; and this error in your case"Receiving end does not exist"
The error lies in the declaration of the script content manifest. A match pattern "*://*/"
will only match the top-level pages at http
and https
URIs. That is, it http://example.com/
will correspond, but http://example.com/test
not.
Simplest fix "*://*/*"
, but I would recommend the universal match pattern "<all_urls>"
.
With this fix, there are still several improvements in the code.
- Replace
chrome.extension.onMessage
(which is deprecated) and usechrome.runtime.onMessage
- Change the part
sendMessage
to be more elastic by checking forchrome.runtime.lastError
. Despite the wide resolution, Chrome still won't add any content scripts to some pages (e.g.chrome://
Pages, Chrome Web Store). - Make sure you use a
"run_at" : "document_start"
script in your content to make sure thatonUpdated
c"complete"
doesn't run until the script is ready.
source to share