3

I'd like to add a custom style sheet in a page without a content script. My CSS is OK, but the code below, using the onUpdated and onCreated event listeners do not work.

Part of manifest.json:

"permissions": [
      "http://www.site_domain.com/*",
      "tabs"],

background.html:

chrome.tabs.onUpdated.addListener(function (tab) {
    var tabUrl = tab.url;
    if (tabUrl.indexOf("site_domain") != -1) {
        changeBgkColor();
    }
});

chrome.tabs.onCreated.addListener(function (tab) {
    var tabUrl = tab.url;
    if (tabUrl.indexOf("site_domain") != -1) {
        changeBgkColor();
    }
});

function changeBgkColor(){
    chrome.tabs.insertCSS(null, {file:"css/styles.css"})
};
Rob W
  • 341,306
  • 83
  • 791
  • 678
arathunku
  • 1,139
  • 1
  • 13
  • 14

2 Answers2

7

chrome.tabs.onCreate has to be replaced with chrome.tabs.onCreated (with a d!).

After fixing this, you'd better pass a tabId to the chrome.tabs.insertCSS method. Also, reduce the code repetition by merging the event listeners:

chrome.tabs.onCreated.addListener(do_something);
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
    if (info.status == 'complete') do_something(tab);
});

function do_something(tab) {
    var tabUrl = tab.url;
    if (tabUrl && tabUrl.indexOf("site_domain") != -1) {
        // changeBgkColour() here:
        chrome.tabs.insertCSS(tab.id, {
            file: "css/styles.css"
        });
    }
}

Since these events are called right after the creation of the tabs. each rule might have to be sufficed with !important, to prevent the rules from being overwritten by style sheets on the page.

According to the documentation of onCreated, the url property may not be set when the event is fired, so add tabUrl && in the condition, to prevent possible errors.

Also, your domain check is insufficient. .indexOf('google.com') would also match http://stackoverflow.com/q/x/what-is-google.com?.

Rob W
  • 341,306
  • 83
  • 791
  • 678
  • I've edited "onCreate" while you were writing answer, sorry. Now it works correctly however after the loading is completed the tab.url is undefined somehow and I can't use indexOf/match. – arathunku Mar 20 '12 at 22:41
  • @arathunku Updated answer. The event listener of [`chrome.tabs.onCreated`](http://code.google.com/chrome/extensions/tabs.html#event-onCreated) gets only one argument (tab), while [`chrome.tabs.onUpdated`](http://code.google.com/chrome/extensions/tabs.html#event-onUpdated) receives 3: tabId, updateInfo, tab. – Rob W Mar 20 '12 at 22:47
3

I'm pretty much doing the same with Chrome 23 (late 2012) and to me it seems that

  1. onCreate is not needed anymore (onUpdated will be fired perfectly even with a cold start and a tab not selected)
  2. changeInfo status "loading" injects the script pretty fast, but it may end up injected twice, even worse, way too early (it shows up in the inspector, but most rules will be overwritten by the page's rules; importants are mandatory)
  3. with changeInfo status "complete" the script is inserted much later (sometimes with bigger load times this can be quite annoying), but it's more stable and for some reason it's not shown in the inspector.
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    if (changeInfo.status === "complete") {
        chrome.tabs.insertCSS(tabId, {code: "body{border:1px solid red}"});
    }
})

(I'm not really sure if it is an answer per se, unfortunately this post is too long to be a comment - for the url checking I myself use regexp of course, but this has already been noted above)