将JS代码注入网站的所有页面

Injecting a JS code into all pages of a website

我正在尝试将 JS 代码注入网站,该代码会在其所有页面上执行。我发现这可以使用 chrome 内容脚本来完成。因此,我做了以下事情:

  1. 我创建了 "contentscript.js"。

    var x = []
    s.src = 'AN EXTERNAL JS FILE';
    (document.getElementsByTagName('head')[0] || document.body).appendChild(s);
    
  2. 我创建了 "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. 两个文件都在同一个文件夹中。

  4. 我已将它们加载到 chrome 扩展中。

  5. 脚本按预期执行。

我正在注入的脚本将一个外部 JS 文件加载到页面中,并将一个脚本元素放在 head 标签下。这个JS也使用了我在注入的JS脚本中定义的x变量。但问题是它无法读取它。在控制台中,它抛出 x 变量未定义的错误。

我如何定义变量使其可以访问外部 JS 文件,提到我既无法访问网站也无法访问外部 JS 文件?

谢谢,

内容脚本也存在于 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 中以获取更多详细信息。

但是,通过 <script> 标记添加脚本会将脚本放入页面的上下文中。因此,它看不到变量。

您有 3 种可能的解决方案。

  1. 完全在页面上下文中使用 x。所以你需要在<script>标签中定义它:

    script = document.createElement("script");
    script.textContent = 'x = [];';
    (document.getElementsByTagName('head')[0] || document.body).appendChild(script);
    
  2. 让页面级脚本和内容脚本进行通信(例如,传递 x)。

    实现此目的的一种方法是通过 custom DOM events. Another is described in the docs(使用 postMessage)。最后,正如 xwhyLikeThis 所建议的,您可以在隐藏的 DOM 节点中存储一个值。

  3. 在内容脚本上下文中加载外部脚本。这将需要使用 XHR from the background script and injecting it programmatically 获取它。或者,如果您可以包含带有扩展名的文件的静态版本 - 只需将其与您的内容脚本一起以通常的方式注入即可。

就我个人而言,我会推荐 2。