document_start 页面上下文中的拦截器脚本在 ManifestV3 中运行得太晚

2023-12-19

我有一个 chrome 扩展,旨在拦截响应正文数据,将其处理为有用的统计信息,然后在页面上呈现这些统计信息。

问题是请求拦截器在最重要的请求已经发送/接收之后加载,因此无法抓取它们(请参阅我从 chrome 网络选项卡中附加的图像,希望这会让事情变得更清楚)。

目前,我的拦截器在与我感兴趣的网址匹配的 content.js 脚本中运行。


拦截器.JS

listenerFn = (event) => {
    console.log("Url:, ", event.target.responseURL);
    // DO OTHER STUFF
}

(
    () => {
        var XHR = XMLHttpRequest.prototype;
        var send = XHR.send;
        XHR.send = function() {
            this.addEventListener('load', listenerFn)
            return send.apply(this, arguments);
        };
    }
)();

我的清单(V3)脚本看起来像这样......


清单.JSON

{
    "manifest_version": 3,
    .....
    "background": {
        "service_worker": "background.js"
    },
    "content_scripts": [
        {
          "matches": ["URL_OF_INTEREST.com/*"],
          "js": ["interceptor.js"],
          "run_at": "document_start"
        }
    ],
    "web_accessible_resources": [
        {
            "matches": ["<all_urls>"],
            "resources": ["interceptor.js"]
        }
    ],
    "permissions": [
        "scripting",
        "activeTab",
        "declarativeContent",
        "storage",
        "tabs"
    ],
    "host_permissions": [
        "*://*/*"
      ]
}

我觉得我的选择是:

  1. 弄清楚如何更快地注入拦截器脚本
  2. 延迟页面请求,直到拦截器完全注入(不可能?)
  3. 尝试以某种方式使用 chrome.WebRequest

我不知道这些是否可行。 1 - 我不认为在当前设置中可以更快地注入拦截器(因为我认为我已经通过设置 run_at 完成了所有操作)。 2 - 我什至不知道这是否可以做到。 3 - 我相信 WebRequest 不允许访问请求正文。

有人向我提到,由于代码与页面内容无关,因此可以让此代码在background.js 脚本中运行。所以也许这是一个值得探索的好途径。

我在下面附上了两张图片,显示了 Chrome 开发工具中的网络选项卡。

在第一张图片中(仅显示 XHR),绿色箭头是我需要抓取的请求,紫色括号涵盖尚未被拦截的请求,黄色箭头是已拦截的请求。第二张图片(显示 XHR 和 JS 文件)中的颜色相似,但其中包含一个蓝色箭头,显示何时运行 Interceptor.js 文件。

任何建议或指导将不胜感激。如果有人想要/需要任何其他信息,请告诉我,

Thanks!


问题是你的注入器脚本是通过 DOM 加载的script元素的src,因此它是异步加载的,并在页面加载其他脚本之后运行。

解决方案是将注入的脚本注册在document_start直接在页面的上下文中(又名MAINworld),有两种方法可以做到这一点,如下所示。

您不需要创建内容脚本script元素。

1.manifest.json 中的“世界”[Chrome 111+]

  "content_scripts": [{
    "matches": ["*://*.example.com/*"],
    "js": ["interceptor.js"],
    "run_at": "document_start",
    "world": "MAIN"
   }]

2. chrome.scripting.registerContentScripts https://developer.chrome.com/docs/extensions/reference/scripting/#method-registerContentScripts[铬102+]

  1. Remove web_accessible_resources以及内容脚本中加载拦截器.js 的代码

  2. Add 权限和主机权限 https://developer.chrome.com/docs/extensions/mv3/match_patterns/在manifest.json中:

      "permissions": ["scripting"],
      "host_permissions": ["*://*.example.com/*"],
      "background": { "service_worker": "background.js" },
    
  3. 将以下代码添加到您的background.js:

    chrome.runtime.onInstalled.addListener(async () => {
      const scripts = [{
        id: 'interceptor',
        js: ['interceptor.js'],
        matches: ['*://*.example.com/*'],
        runAt: 'document_start',
        world: 'MAIN',
      }];
      const ids = scripts.map(s => s.id);
      await chrome.scripting.unregisterContentScripts({ids}).catch(() => {});
      await chrome.scripting.registerContentScripts(scripts).catch(() => {});
    });
    

P.S.

另一个问题是您加载相同的文件content_scripts and web_accessible_resources。您应该使用两个不同的脚本,因为它们在两个不同的上下文(“世界”)中运行。要在它们之间进行通信,您可以使用 CustomEvent 消息传递(example /a/19312198).

最后,该网站可能使用 iframe 来发出请求,在这种情况下,您需要添加"all_frames": true到你的内容脚本在manifest.json中的声明,并且可能"match_origin_as_fallback": true如果 iframe 是about:blank或者没有任何src.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

document_start 页面上下文中的拦截器脚本在 ManifestV3 中运行得太晚 的相关文章

随机推荐