消息传递内容脚本在使用“webRequest.onBeforeRequest()”作为触发器时起作用,但在使用“webRequest.onCompleted()”时不起作用

Messaging content script works when using 'webRequest.onBeforeRequest()' as the trigger but not when using 'webRequest.onCompleted()'

提问人:Ralf_Reddings 提问时间:11/9/2023 最后编辑:Ralf_Reddings 更新时间:11/10/2023 访问量:49

问:

我完成了我的第一个扩展,它按照我的编程工作,但是完成后,我意识到我在它的设计中犯了一个错误,目前它旨在在事件发生之前提醒我(),我希望在事件发生并完成后收到警报()。webRequest.onBeforeRequest()webRequest.onCompleted()

我尝试在其他地方进行更改和必要的调整,但它只是不断抛出错误。我尽可能多地删除了不相关的代码,以保持我的示例简短。我将不胜感激任何帮助。webRequest.onBeforeRequest()webRequest.onCompleted()

清单文件:

{
    "name": "shell",
    "manifest_version": 2,
    "version": "1.0",

    "background": {"scripts": ["background.js"]},
    "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["content.js"]
        }
      ],
    "permissions": ["tabs","activeTab", "webRequest", "<all_urls>"]
}

内容.js文件:

"use strict";

browser.runtime.onMessage.addListener((request) => {
  console.log("Message from the background script:");
  console.log(request.greeting);
  return Promise.resolve({ response: "Hi from content script" });
});

background.js 文件:

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response); 
         })
         .catch(onError);
    }
// Trigger the messaging event when wiki/vihicle is visited
browser.webRequest.onBeforeRequest.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"]});  

以上工作得很好,当我访问 wiki/vehicle 时,内容脚本会在控制台上响应后台脚本:

Message from the content script:
Hi from content script

我哪里出错了

但是当我尝试返工 background.js 文件时,它使用 而不是 ,我的扩展停止工作。我收到错误:webRequest.onCompleted()webRequest.onBeforeRequest

Error: Type error for parameter tabId (Integer -1 is too small (must be at least 0)) for tabs.sendMessage.

重新设计的 background.js 文件是:

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"]});   // this is used to trigger the messaging event

编辑1

根据@wOxxOm建议,再次阅读文档后,我添加了文件如下所示的属性:types['main_frame']background.js

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"], types['main_frame']});   // this is used to trigger the messaging event

但我仍然收到此错误:Error: Type error for parameter tabId (Integer -1 is too small (must be at least 0)) for tabs.sendMessage.

javascript firefox-addon firefox-addon-webextensions web扩展

评论

1赞 wOxxOm 11/9/2023
您的代码会拦截所有请求,而不仅仅是主请求。您需要指定 ,请参阅文档。types:['main_frame']
1赞 wOxxOm 11/9/2023
实际上,webRequest 可能是错误的 API,这取决于你想要实现的目标可能是正确的选择。webNavigation.onCompleted
0赞 Ralf_Reddings 11/9/2023
@wOxxOm,我尝试了您的建议,但我继续遇到同样的错误。我对我的问题进行了编辑,报告了您的建议。请看一下。我不明白为什么正确传递选项卡 ID 但作为选项卡 ID 传递,文档状态是请求未与选项卡关联的结果。webRequest.onBeforeRequest()webRequest.onCompleted()-1
0赞 Ralf_Reddings 11/9/2023
@wOxxOm,我实际上需要.我所针对的网站是这些现代“应用程序”网站之一,因此标题栏和网址永远不会改变。我正在尝试通过在网站在后台请求资源时来定位自动发生的事件。我已经在网站上手动测试了此事件,并按我的预期工作。webRequest.onCompleted()
1赞 wOxxOm 11/10/2023
显然,该站点在其 Service Worker 中发出请求,这就是其 tabId 为 -1 的原因。您可以获取与站点 URL 匹配的所有选项卡的列表,例如 并向所有找到的选项卡发送消息。请注意,如果资源不是主页本身,那么它就不是,而是其他东西,例如 取决于该请求的提出方式。chrome.tabs.query({url: '*://site.com/*'})main_framexmlhttprequest

答:

0赞 Ralf_Reddings 11/10/2023 #1

因此,在重新阅读了所有 wOxxOm 评论之后,尤其是他的最后一条评论。我开始尝试随机 URL,例如 BBC 和麦当劳等。他们都奏效了。我什至不需要指定.我也在我的最终网站上尝试了它,它也有效。 看来,我的失败归结为使用维基百科作为示例来测试我的代码,我最初选择了 SO 的“可复制”示例约定。吸取的教训。type: ["main_frame"]

最终的背景.js为:

function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://final/web/site/here.com"]});  //This time it does not send `-1`

我只想感谢 w0xx0m,我怀疑如果没有他们的耐心来回与我来回,我会抓住,干杯