Chrome 扩展:在网页中的任何其他 JS 之前运行可访问窗口的自定义 JS

问题描述 投票:0回答:1

我正在编写 Chrome 扩展(manifest v3),主要目的是覆盖一些 Window 本机函数并在任何其他网页脚本可以访问它们之前替换它们。

我有

contentscript.js
,它有
run_at = document_start
contentscript.js
成功地将我的
script.js
注入到网页DOM中,或者注入
<html>
<head>
标签(通过突变观察者)。但是(!)我不能强制并保证我的
script.js
将在任何其他网站之前首先运行脚本。

当我调试

contentscript.js
时,页面的DOM仅包含
<html>
和我新注入的加载
<script>
script.js
元素。因此
run_at
工作得很好。但是,当我在最后一行之后使用调试器时,我不是进入
script.js
,而是进入网站脚本(即使我的 script.js 引用是标题中所有其他引用之上的第一个)。如果 contentscript.js 可以直接写入网页,那么一切就很容易解决了
window
,但它不能。

我尝试在

contentscript.js
中添加变异观察器,我能够检测到 DOM 中添加的标签,并且我能够编辑/删除它们而不(?)让它们执行,但我需要页面工作。

我尝试过的:

  1. debugger;
    命令添加到任何
    <script>
    中,这样我就可以看到哪个脚本首先运行 -- 每次都是网站脚本,不是我的。
  2. 向所有脚本添加
    async=false
    defer=false
    -- 失败,
  3. 通过重写或智能禁用任何
    <script>
    来禁用它们,然后在我的
    script.js
    注册为已读后重新运行它们。我正在重新启用脚本,以便观察者观察脚本(a)或(b)通过 document.querySelectorAll 中的 DOM 顺序观察脚本。这种方法适用于某些网站,但有些网站会在“不存在的对象引用”上抛出错误,然后当我在控制台中检查它们时,这些错误都会被定义——对我来说,这似乎很奇怪,因为我按顺序评估原始脚本并且看起来像一些网站作者的竞争条件(?)。

编辑:我还尝试使用直接

<script>
添加自定义
script.text = ... code ...
但这被拒绝,因为 CSP 需要哈希、随机数或不安全内联(但是,我将尝试编辑 HTTP 标头以包含现在不安全内联)。

是否有希望让我的脚本在有保证的情况下首先运行? 谢谢你

javascript google-chrome dom google-chrome-extension firefox-addon
1个回答
0
投票

您的内容脚本无法直接写入网页的窗口对象的原因是由于执行世界。默认情况下,内容脚本在“孤立的世界”中工作,这意味着它们无法直接修改主网页上下文中的对象。 要直接写入网页的

window

(主世界),您需要将脚本注入主世界。

第一个解决方法:通过manifest.json注入脚本

您可以通过在

manifest.json

中指定来将内容脚本配置为在主世界中运行:

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["src/my_content_script.js"],
      "run_at": "document_start",
      "world": "MAIN"
    }
  ]

第二种解决方法:通过来自孤立世界的内容脚本将脚本元素注入到 DOM 中

如果第一种方法不起作用(例如,由于某些开发工具的限制),您可以将脚本元素直接插入到 DOM 中以在主世界中执行。

contentScript.js:

const scriptEl = document.createElement("script"); scriptEl.type = 'module'; // Use 'module' if you're working with ES modules scriptEl.src = chrome.runtime.getURL('./main-world.js'); (document.head || document.documentElement).appendChild(scriptEl);

现在,您可以直接写入网页的
window

:

main-world.js:

// Example: It will directly modify the alert function of the webpage window const alertFn = window.alert; window.alert = function(msg) { console.log(msg); // Do something with the message alertFn(msg); // Pass the message to the original alert };

	
© www.soinside.com 2019 - 2024. All rights reserved.