Google chrome extension Chrome扩展:如何将消息从后台发送到新页面的内容脚本

Google chrome extension Chrome扩展:如何将消息从后台发送到新页面的内容脚本,google-chrome-extension,background,sendmessage,content-script,Google Chrome Extension,Background,Sendmessage,Content Script,对不起我的英语,我会尽力的 我需要创建一个扩展,其中弹出窗口包含一个字段和一个按钮 我们的目标是,一旦单击按钮,就会打开一个新窗口(另一个网站),您必须在此新窗口中发送popin字段信息 这是我的manifest.json { "name": "Webrelief extension", "version": "1", "browser_action": { "default_icon": "webrelief.ico", "default_popup": "po

对不起我的英语,我会尽力的

我需要创建一个扩展,其中弹出窗口包含一个字段和一个按钮

我们的目标是,一旦单击按钮,就会打开一个新窗口(另一个网站),您必须在此新窗口中发送popin字段信息

这是我的manifest.json

{
  "name": "Webrelief extension",
  "version": "1",
  "browser_action":
  {
    "default_icon": "webrelief.ico",
    "default_popup": "popup.html",
    "default_title": "Webrelief extension - Iello"
  },
  "background":
  {
    "scripts": ["background.js"],
    "persistent": true
  },
  "content_scripts": [
    {
      "run_at": "document_end",
      "matches": [
        "https://www.iello.pro/iello-c102x3259540",
        "https://www.google.com/"
      ],
      "js": ["jquery.min.js","content.js"]
    }
  ],
  "permissions": ["tabs","activeTab","<all_urls>"],
  "manifest_version": 2,
  "content_security_policy": "script-src 'self' https://www.iello.pro/iello-c102x3259540; object-src 'self'"
}
My content.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        console.log(sender.tab ?
        "from a content script:" + sender.tab.url :
            "from the extension");
        if (request.greeting == "hello")
            sendResponse({farewell: "goodbye"});
    });
还有我的popup.html

<!doctype html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Webrelief Extension</title>
    <link href="css/main.css" rel="stylesheet">
</head>
<body>
<img width="400px" src="webrelief_logo.svg" alt="Bannière webrelief">
<hr>
<div>
    <textarea placeholder="Veuillez saisir le json ici ..." name="json" id="json_iello" cols="30" rows="10"></textarea>
</div>
<button id="validate">Go !</button>
<script src="background.js"></script>
</body>
</html>

Webrelief扩展

走!

当前,如果我按下按钮,我的新窗口将打开,但我没有收到新窗口上的消息

你能告诉我我的错误吗


谢谢

这里有三个主要问题

向选项卡发送消息的时间 这个问题没有很好的重复(是最接近的候选人),但你面临的主要问题是时机

打开选项卡后,在充分加载页面之前调用
create
的回调。您的内容脚本可能根本不在那里,无法收听消息。对于
document\u end
定时,几乎可以肯定情况并非如此

唯一安全的方法是反向通信:让内容脚本请求数据,这样您就知道它已经准备好了

这就引出了下一个问题

打开消息时弹出关闭窗口 创建焦点选项卡时,会导致弹出窗口失去焦点并关闭

当这种情况发生时,在那里运行的脚本将被终止,就像您关闭了页面的选项卡一样

因此,您的代码的其余部分甚至都没有运行(与前面的问题无关)。这里有两个选项:

  • 您可以使用
    active:false
    设置。这不会失去焦点,因此弹出窗口保持活动状态,但对用户来说不太方便,尽管之后您仍然可以将其激活

    另一个不相关的注意事项是,当像
    tabs.create
    这样的函数在其回调中显式返回
    tab
    对象时,您不应该
    query

  • 更好的选择是:你应该把开场白和交流委派给你的背景页面。它不受弹出关闭的影响,通常更适合作为“通信路由器”

  • 这就引出了最后一个问题

    对后台页面体系结构的误解 您在清单中声明了一个
    background.js
    脚本作为后台脚本。这是什么意思

    这意味着将创建一个单独的、不可见的空页面,并在该脚本运行时加载该页面

    如果在扩展中的其他位置包含一个
    background.js
    脚本,它将不是脚本的“那个”实例。它将是一个独立的副本,并受其新上下文的所有限制

    非常强烈的建议:不要试图在代码中重用整个脚本。有一些共享代码(比如,
    utils.js
    包含一些常用函数,并包含在各自的脚本之前)是可以的,但要注意以描述性的方式调用脚本并单独编写代码

    要与“真实”背景页面交互,您需要(使用
    chrome.runtime.sendMessage


    总而言之,你的逻辑应该是:

  • 在弹出窗口中(使其成为一个单独的
    popup.js
    脚本),监听您的UI事件
  • 当这种情况发生时,要么发送到后台(via),要么存储(in)用户数据
  • 然后,通过消息传递,要求您的后台页面执行该操作。准备弹出窗口,以便在此时关闭
  • 此时,您的背景可以打开请求的页面。它会杀死弹出窗口,但你不在乎
  • 内容脚本初始化后,可以直接从
    chrome.storage
    获取用户数据,也可以从后台页面请求(通过
    runtime.sendMessage

  • 有一个问题是,每次打开目标页面时都会启动内容脚本,即使您不想使用用户数据。您可以实施某种机制,只使用一次数据(例如,使用后清除/标记数据),也可以仅使用一次(尽管在
    选项卡。创建
    )后仍有时间问题要处理)

    添加与后台页面和弹出窗口(分开)逻辑相同的脚本通常会指向逻辑错误。把代码分开。
    <!doctype html>
    <html lang="fr">
    <head>
        <meta charset="UTF-8">
        <title>Webrelief Extension</title>
        <link href="css/main.css" rel="stylesheet">
    </head>
    <body>
    <img width="400px" src="webrelief_logo.svg" alt="Bannière webrelief">
    <hr>
    <div>
        <textarea placeholder="Veuillez saisir le json ici ..." name="json" id="json_iello" cols="30" rows="10"></textarea>
    </div>
    <button id="validate">Go !</button>
    <script src="background.js"></script>
    </body>
    </html>