Does a web extension need to explicitly load content scripts?

Viewed 1288

I'm trying to write a simple Web Extension. Currently I'm following the various tutorials and trying to understand the architecture.

Interaction with specific tabs is done with content_scripts that are injected into the source code of a website. It seems to me, as if content_scripts are loaded automatically: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts

A tutorial on MDN makes this even more clear:

This script will be loaded into the pages that match the pattern given in the content_scripts manifest.json key. The script has direct access to the document, just like scripts loaded by the page itself.

My extension is supposed to offer a context menu on every text selection. As a starting point, I found a useful sample extension for chrome. You can find it here https://developers.chrome.com/extensions/samples, it is called "speak selection"

This extension is reading selected text with a tts engine. But one part of the sourcecode is confusing: They have an explicit function to run content_scripts in tabs. This code is executed as part of an Init() function in one of their background scripts:

function loadContentScriptInAllTabs() {
  chrome.windows.getAll({'populate': true}, function(windows) {
    for (var i = 0; i < windows.length; i++) {
      var tabs = windows[i].tabs;
      for (var j = 0; j < tabs.length; j++) {
        chrome.tabs.executeScript(
            tabs[j].id,
            {file: 'keycodes.js', allFrames: true});
        chrome.tabs.executeScript(
            tabs[j].id,
            {file: 'content_script.js', allFrames: true});
      }
    }
  });
}

As far as I can see, the code is executed as soon as the browser starts. Isn't that redundant ?

Their manifest.json should take care of the content_script execution, here is the relevant code:

"content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "all_frames": true,
      "js": [
        "keycodes.js",
        "content_script.js"
      ]
    }
  ],

What is the proper way to inject a script into every open tab?

2 Answers

You can explicitly load content (foreground) pages into any tab, or create a tab then load a content page. Do this from the background script. You don't need entries in the manifest file other than requiring active tab permission.

browser.tabs.executeScript(null,{file:"/content.js"}).then(NextAction);
function NextAction(Array of last evaluated statement of foreground script in each frame)
   {...}
Related