Change HTML Content out of chrome.tabs.onUpdated

I'm working on a Chrome Extension, my first one.

Everything works as it should, except one part.

My manifest.json includes the background.js:

"content_scripts": [
{
  "matches": ["http://*/*","https://*/*"],
  "css": ["ui.css"],
  "js": ["jq.js","background.js"]
}
]

When i try to append html with jQuery like this:

$("body").before("<code>");

it runs perfectly. But when I wanna do this like this:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
var pageUrl = changeInfo.url;
$.ajax({
    url: "URL",
    data: {DATA},
    datatype: "json",
    type: "POST",
    success: function(data) {
       $("body").before("<code>");
    }
 });
});

Nothing happens.. Any ideas? Thanks..

Upvotes: 1

Views: 1340

Answers (1)

gkalpak
gkalpak

Reputation: 48211

The problem:
You are injecting background.js as a content script. (Chrome does not care what you name it, just that you put it in content_scripts's js array) So, basicaly, you can use jQuery to directly manipulate a web-pages DOM (like in your first attempt) - because content scripts can do that, but you cannot use chrome.tabs.* (like in your second attempt) - because content scripts cannot do that.

The solution: Since you cannot manipulate a web-pages DOM from a background page, you have to do it through a content script:

  1. Define background.js as a background page (or better yet event page).
  2. Define a new file (e.g. content.js as your content script).
  3. From your chrome.tabs.onUpdated listener (in the background page), send a message to the corresponding tab's content script, using chrome.tabs.sendMessage.
  4. In your content script, listen for messages from the background page (using chrome.runtime.onMessage) and then execute $("body").before("<code>");

(Note: There plenty of alternative approaches and you should pick one that better fits your specific requirements.)


For the sake of completeness, below is a code of a sample extension, based on what I described above:

In manifest.json:

{
    "manifest_version": 2,
    "name":    "Test Extension",
    "version": "0.0",

    "background": {
        "persistent": false,
        "scripts": ["./bg/background.js"]
    },
    "content_scripts": [{
        "matches": ["*://*/*"],
        "js":         ["./fg/content.js"],
        "run_at":     "document_start",
    }],
    "permissions": ["tabs"]
}

In background.js:

chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
    console.log("One of my tabs updated: ", info);
    if (info.url) {   // <-- Not all `info` objects contain a `url` field
                      //     (Also, if a tab is refreshed, the URL is not changed,
                      //      so you will never get and `info` object with a `url` field)
        console.log("...pretending to make an AJAX request...");
        var pageURL = info.url;
        setTimeout(function() {
            // ...let's simulate an AJAX request...
            // ...now let's pretend out data arrived...
            chrome.tabs.sendMessage(tabId, {
                cmd: "doYourStuff",
                kind: "fancy"
            });
            console.log("Message sent !");
        }, 2000);
    }
});

In content.js:

chrome.runtime.onMessage.addListener(function(msg) {
    console.log("Someone sent us this: ", msg);
    if (msg.cmd && (msg.cmd == "doYourStuff")) {
        alert("Watch me doing " + kind + " stuff !");
    }
});

Upvotes: 3

Related Questions