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

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

对不起我的英语,我会尽我所能。

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

目标是一旦点击按钮,就会打开一个新窗口(另一个网站),你必须在这个新窗口中发送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'"
}

我的background.js

$('#validate').on('click',function(activeTab){
    var newURL = "https://www.iello.pro/iello-c102x3259540";
    chrome.tabs.create(
        {
            url: newURL
        }, function() {
            chrome.tabs.query({active: false, currentWindow: true}, function(tabs) {
                chrome.tabs.sendMessage(tabs[tabs.length - 1].id, {greeting: "hello"}, function(response) { // tabs[tabs.length - 1] to get the new windows ? I'm not sure
                    console.log(response);
                });
            });
        }
    );
});

我的内容.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>

enter image description here

目前,如果我按下按钮,我的新窗口会打开,但我在新窗口中没有收到消息。

你能告诉我我的错误吗?

谢谢 !

google-chrome-extension background sendmessage content-script
1个回答
1
投票

这里有三个主要问题。

向选项卡发送消息的时间

这个问题并没有真正重复(this是最接近的候选人),但你遇到的主要问题是时机问题。

打开选项卡后,在页面充分加载之前调用create的回调。您的内容脚本可能根本就没有收听消息。随着document_end计时,几乎可以肯定不是这样。

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

这导致下一个问题..

弹出窗口关闭消息打开

当您创建一个聚焦的选项卡时,这会导致弹出窗口失去焦点并关闭。

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

所以你的代码的其余部分甚至都没有运行(不管以前的问题)。你有两个选择:

  1. 你可以用create a tab设置active: false。这不会失去焦点,因此弹出窗口保持活动状态,但对用户来说不太方便,但在此之后仍然可以使其处于活动状态。 作为一个不相关的注释,当query这样的函数在回调中显式返回一个tabs.create对象时,你不应该使用tab
  2. 更好的选择:您应该将开放 - 然后 - 沟通委托给您的背景页面。它不受弹出闭合的影响,通常更适合作为“通信路由器”。

这给我们带来了最后一个问题..

对背景页面架构的误解

您在清单中声明了background.js脚本作为后台脚本。那是什么意思?

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

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

非常强烈的建议:不要尝试在代码中重用整个脚本。有一些共享代码(比如,utils.js持有一些常用函数,并包含在相应的脚本之前),这很好,但要注意以描述性方式调用脚本并分离代码。

要与“真实”背景页面进行交互,您需要使用send messages(使用chrome.runtime.sendMessage)。


把它们放在一起,你的逻辑应该是:

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

有人担心每次打开目标页面时都会启动内容脚本,即使您不想使用用户数据也是如此。您可以实现某种机制仅使用一次数据(例如使用后清除/标记)或仅使用inject the content script programmatically(尽管您在tabs.create之后将再次处理时序问题)

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