0

I'm trying to inject a JS code into a website, where the code gets executed on all of its pages. I found out that this could be done using the chrome content scripts. Therefore, I've done the following:

  1. I've created "contentscript.js".

    var x = []
    s.src = 'AN EXTERNAL JS FILE';
    (document.getElementsByTagName('head')[0] || document.body).appendChild(s);
    
  2. I've created "manifest.json".

    {
       "name": "Sample",
       "version": "1.0",
       "manifest_version": 2,
       "permissions": [
           "tabs",
           "*://*/*"
       ],
       "icons": { "128":"logo.png" },
       "content_scripts": [{
           "js": ["contentscript.js"],
           "matches": ["<all_urls>"]
       }]
    }
    
  3. Both files exist in the same folder.

  4. I've loaded them into the chrome extensions.

  5. The script gets executed as expected.

The script I'm injecting loads an external JS file into the page and places a script element under the head tag. This JS also uses the x variable I defined in the injected JS script. But the problem that it can't read it. In the console, it throws an error that the x variable is not defined.

How can I define the variable in a way it makes it accessible to the external JS file, mentioning that I don't have access neither to the website nor to the external JS file?

Thanks,

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
Bilal
  • 111
  • 2
  • 9

1 Answers1

2

Content scripts live in an isolated world. You define x outside the context of the page, and as such it's invisible to scripts running in it. See this answer for more details, too.

Adding a script through a <script> tag, however, places the script into the page's context. As such, it does not see the variable.

You have 3 possible solutions.

  1. Work with x entirely in the page's context. So you need to define it in a <script> tag:

    script = document.createElement("script");
    script.textContent = 'x = [];';
    (document.getElementsByTagName('head')[0] || document.body).appendChild(script);
    
  2. Let the page-level script and the content script communicate (and, say, pass x around).

    One way to achieve this is via custom DOM events. Another is described in the docs (with postMessage). Finally, as suggested by xwhyLikeThis, you can store a value in a hidden DOM node.

  3. Load the external script in the content script context. This will require fetching it with XHR from the background script and injecting it programmatically. Or, if you can include a static version of the file with the extension - just inject it the usual way along with your content script.

Personally, I would recommend 2.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206