25

I want to load a different content script depending on the page and tab that is currently selected. Right now, I have three content scripts. I want to use two of them for one page and the third one for another page.

Belonging to page 1:

content_script.js load_content_script.js

Belonging to page2:

newtab_content_script.js

right now my manifest looks like this

{
  "name": "A plugin for AdData express. Generate an instant excel document from the brands you check mark.",
  "version": "1.0",
  "background_page": "background.html",
  "permissions": [
    "cookies",
    "tabs", 
    "http://*/*", "https://", "*", "http://*/*", "https://*/*",
    "http://www.addataexpress.com", "http://www.addataexpress.com/*"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>","http://*/*","https://*/*"],
      "js": ["load_content_script.js", "content_script.js", "newtab_content_script.js", "jquery.min.js", "json.js"]
    }
  ],
  "browser_action": {
      "name": "AdData Express Plugin",
      "default_icon": "icon.png",
      "js": "jquery.min.js",
      "popup": "popup.html"
  }
}

how would I structure this in the manifest or elsewhere?

Chamilyan
  • 9,347
  • 10
  • 38
  • 67
  • you could also use 'chrome.declarativeContent.RequestContentScript' as mentioned in this answer: http://stackoverflow.com/a/26677279/176140 – schellmax Jan 22 '15 at 12:12
  • Have you considered making [Darin's answer](https://stackoverflow.com/a/7568862/3357935) the accepted answer? It seems to be the most direct solution. – Stevoisiak Jul 12 '18 at 20:49

3 Answers3

102

Just in the interest of completeness, the way you'd do this from the manifest is to have as many matches blocks under "content_scripts" as needed:

"content_scripts": [
  {
    "matches": ["http://www.google.com/*"],
    "css": ["mygooglestyles.css"],
    "js": ["jquery.js", "mygooglescript.js"]
  },
  {
    "matches": ["http://www.yahoo.com/*"],
    "css": ["myyahoostyles.css"],
    "js": ["jquery.js", "myyahooscript.js"]
  }
],
Darin
  • 2,071
  • 2
  • 17
  • 14
25

Rather than using content scripts that are bound to URL expressions specified in the manifest, you should use executeScript, which lets you programmatically decide when to inject a JS snippet or file:

// background.js
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  // there are other status stages you may prefer to inject after
  if (changeInfo.status === "complete") {
    const url = new URL(tab.url);
    if (url.hostname === "www.stackoverflow.com") {
    
      // this is the line which injects the script
      chrome.tabs.executeScript(tabId, {file: "content_script.js"});
    }
  }
});

Make sure to add tabs permission to manifest.json:

{
  // ...settings omitted...
  "permissions": [
    "tabs",  // add me
  ]
}
Seph Reed
  • 8,797
  • 11
  • 60
  • 125
Boris Smus
  • 8,220
  • 2
  • 36
  • 33
  • are they treated as content scripts if they are called from background pages using `executescript` ? – Chamilyan Sep 27 '11 at 02:15
  • They're injected into the page using the same mechanism, with the same restrictions. – Boris Smus Sep 27 '11 at 02:17
  • 8
    worth mentioning that this requires tabs permissions in the manifest file. – James Aug 08 '13 at 23:00
  • What is the downside of declaring it in the manifest? Why is it better to inject it with `exceuteScrip`'? I understand that `executeScript` allows you to programmatically decide when to inject the script, but what if you always want it injected at a certain url? – sbru Sep 15 '16 at 01:25
  • @sbru in that case you would use the manifest. What if you wanted to execute the script only in certain conditions when on the page. That's a case I see for executeScript. – Chamilyan Apr 01 '17 at 15:22
  • Does this go into background.js? How do we observe for new tabs and new urls for each tab? – Seph Reed Oct 05 '20 at 17:15
7

you should use Programmatic injection

chrome.tabs.executeScript(null, {file: "content_script.js"});
wukong
  • 2,430
  • 2
  • 26
  • 33