【问题标题】:Callback from background to content script after tab url changed选项卡 URL 更改后从后台回调到内容脚本
【发布时间】:2016-12-17 21:30:15
【问题描述】:

我是 chrome 扩展的新手,我遇到了一个问题。 单击我的扩展程序图标时,我会运行一个脚本:

chrome.browserAction.onClicked.addListener(function(tab) { 
    chrome.tabs.executeScript({
        "file": "enterIonis.js"
    });
});

此脚本从打开的选项卡中获取一些信息,然后更改选项卡 url 以加载新页面。然后,此脚本需要等待新页面完全加载才能与之交互。为此,它打开一个端口并向使用chrome.tabs.onUpdated 侦听器的后台页面发送消息。背景页面应该向内容脚本发送消息/回调,告诉它现在可以与选项卡交互。

background.js:

var _port;
var goodUrl;


chrome.runtime.onConnect.addListener(function(port) {
  console.assert(port.name == "enterIonis");
  port.onMessage.addListener(function(msg) {
        goodUrl = msg.url;
        _port = port; 
    });
});

chrome.tabs.onUpdated.addListener(function ( tabId, changeInfo, tab ){ 
  if ( changeInfo.status === "complete" ){

    chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
        var currentUrl = tab.url;
        if(currentUrl == goodUrl){
            //should send a callback to content script here
            _port.postMessage({result: "ok"});
        }
    }); 

  }
});

content_script.js

//interacting with DOM elements
...

// sending a message to background.js
var port = chrome.runtime.connect({name: "enterIonis"});
port.postMessage({url:href});
port.onMessage.addListener(function(msg){
    // here is where the message from the background telling the tab is ready should arrive
    alert(msg.result);
});

问题是当我尝试使用第一条消息中的端口时,我收到以下错误:Error in response to tabs.query: Error: Attempting to use a disconnected port object

如何重新连接端口?或者有没有其他方法可以实现我的目标?

【问题讨论】:

  • 不清楚为什么不能从后台脚本进行操作,而是将脚本注入页面并设置通信。
  • edit 成为主题的问题:包括一个完整 minimal reproducible example 重复问题。包括一个manifest.json,一些背景/内容/弹出脚本/HTML。寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括:►所需的行为,►特定问题或错误►必要的最短代码重现它在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:“如何创建 minimal reproducible example”、What topics can I ask about here?How to Ask
  • 虽然您已经提供了足够的信息,但我们可以很好地猜测关于可能会发生什么,而无需您提供完整minimal reproducible example在问题中,我们无法知道猜测是否正确。
  • @pvg 我需要内容脚本来与页面上的 DOM 元素进行交互

标签: javascript google-chrome google-chrome-extension tabs


【解决方案1】:

tabs.executeScript() 注入到页面,而不是持久地注入到选项卡中

您必须单独将内容脚本注入新页面。使用tabs.executeScript() 注入脚本不会将脚本注入到选项卡中,该选项卡会在加载新网页时为选项卡保留。它将脚本注入到当前显示在指定选项卡中的 page 中。一旦该页面不再显示在该选项卡中,内容脚本就不再存在。

您说您的脚本“更改标签网址以加载新页面”,然后应该做其他事情,而它没有做。一旦新页面开始加载,您注入的内容脚本的上下文就会与旧网页的上下文一起被销毁。新页面加载后,您的内容脚本无法向后台脚本发送消息,因为您的内容脚本不再存在。

【讨论】:

  • 好吧,我现在明白了,我想我可以将内容脚本用作类。但是那我该怎么办呢?因为我不想在我的chrome.tabs.onUpdated 监听器中有一个大的开关盒,告诉根据当前选项卡 url 执行哪个脚本......我想要更动态的东西
  • @DavidSeroussi,如果没有关于您想要做什么的更多信息,很难提出建议。关于如何注入脚本的两个基本选项是 manifest,json content_scripts 条目,它们在扩展中静态定义,tabs.executeScript() 是动态的,但通常更复杂。跨度>
  • 基本上,我想:在页面上找到某些 DOM 元素,与它们交互,加载新页面(根据之前的元素),然后重复该过程直到满足某个条件。要与 DOM 元素交互,我必须使用内容脚本,但我还需要完全加载页面(这就是我使用背景页面的原因)。我想我可以使用消息传递在这些内容脚本和后台页面之间进行通信。
  • @DavidSeroussi,我仍然不太了解您在做什么,无法提出具体建议。但是,听起来您可以使用tabs.executeScript() 重复将相同的内容脚本注入选项卡,直到您的内容脚本确定它完成为止。一旦确定完成,它会向后台脚本发送消息以关闭对每个新页面的注入。如果内容脚本需要来自后台脚本的信息来做出选择,反之亦然,则可以来回发送该信息。
  • 我的扩展程序将在单个网站上运行。该网站包含多个页面,扩展程序基本上会在这些页面中导航以查找视频并启动它。当视频结束时,它开始搜索新视频,并且循环重复。我不能总是在所有页面中注入相同的脚本,因为有 5-6 种不同类型的页面。页面的 URL 包含在 DOM 元素中。
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 2018-12-30
相关资源
最近更新 更多