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
    }
}

      

+3


source to share


1 answer


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 for chrome.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 that onUpdated

    c "complete"

    doesn't run until the script is ready.
+6


source







All Articles