从网页向 chrome 扩展发送消息

Posted

技术标签:

【中文标题】从网页向 chrome 扩展发送消息【英文标题】:sending message to chrome extension from a web page 【发布时间】:2012-07-10 23:50:27 【问题描述】:

我想从随机网页的控制台向我的 chrome 扩展程序发送消息。 chrome.extension.sendMessage 似乎不起作用。

【问题讨论】:

【参考方案1】:

根据the official docs,您应该在发送方使用postMessage,在接收方使用message 事件监听器。

这是一个例子:

您网站的 page.html

var data =  type: "FROM_PAGE", text: "Hello from the webpage!" ;
window.postMessage(data, "*");

内容脚本:(使用chrome.tabs.executeScript(tabid, code:...注入)

window.addEventListener("message", function(event) 
    // We only accept messages from ourselves
    if (event.source != window)
        return;

    if (event.data.type && (event.data.type == "FROM_PAGE")) 
        console.log("Content script received message: " + event.data.text);
    
);

这里page.html(不是扩展的一部分)向自己发布消息,内容脚本会拦截和检查这些消息。反过来也可以通过类似的方式。

要从内容脚本传递到扩展,您必须使用one of the available message-passing techniques。

它看起来很复杂,也有点复杂,但是所有这些大杂烩都是非常安全的。

【讨论】:

我可以尝试在网站的 html 中插入代码以通过“chrome.tabs.executeScript()”命令调度事件吗?我厌倦了它,它不工作......它说,“端口错误:无法建立连接:接收端不存在: 谢谢。我想知道如何比 window.postMessage 更安全地执行此操作。这肯定会产生更少的副作用,但不幸的是仍然可能被恶意网页篡改。我很期待chrome.runtime.onMessageExternal,这将允许一个更安全(希望)的沟通渠道 @kzahel 内容脚本在它们自己的上下文中运行,因此它与网页上下文隔离。内容脚本可以访问 DOM(HTML 元素),基本上,如果你想在上下文之间传递数据,你可以附加监听器,你可以通过事件来做到这一点。请注意,有 3 种不同的上下文:扩展、自定义脚本和网页脚本。 第一个链接提到使用 windows.postMessage(...) 所以显然你甚至不需要自定义 myCustomEventDiv,因为它是...... 很高兴在搜索了一个小时后找到了这个。感谢您的写作!【参考方案2】:

这里引用最新的http://developer.chrome.com/extensions/messaging.html,现在支持这种功能要简单得多,方法如下:

从网页发送消息

与跨扩展消息传递类似,您的应用或扩展可以 接收和回复来自常规网页的消息。要使用这个 功能,您必须首先在您的manifest.json 中指定哪个网站 您想与之交流的网站。例如:

"externally_connectable": 
  "matches": ["*://*.example.com/*"]

这会将消息传递 API 公开给与 URL 匹配的任何页面 您指定的模式。 URL 模式必须至少包含一个 二级域 - 即主机名模式,如“”、“.com”、 禁止使用“.co.uk”、“.appspot.com”和 。 在网页中,使用 runtime.sendMessage 或 runtime.connect API 向特定的应用程序或扩展程序发送消息。例如:

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, openUrlInEditor: url,
  function(response) 
    if (!response.success)
      handleError(url);
  );

通过您的应用或扩展程序,您可以收听来自网页的消息 通过 runtime.onMessageExternal 或 runtime.onConnectExternal API, 类似于跨扩展消息传递。只有网页可以发起一个 联系。这是一个例子:

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) 
    if (sender.url == blacklistedWebsite)
      return;  // don't allow this web page access
    if (request.openUrlInEditor)
      openUrl(request.openUrlInEditor);
  );

【讨论】:

@user1311069 扩展ID生成机制在这里解释:***.com/a/21500707/258772 chrome.runtime.onMessageExternal.addListener()收听事件 请注意,从 FF 54 开始,此方法目前在 Firefox 中不起作用。请参阅此以获得可能的解决方案:***.com/questions/44592605/… 无法从未知域的脚本发送消息,因为它必须在 manifest.json 中定义 糟糕的文档,真的【参考方案3】:

详细说明,一个更具体的示例:chrome.runtime.sendMessage(...) 样式的一个问题是您必须将您所在的页面指定为 externally_connectable ,它不采用像“https:// 这样的全局通配符/”。所以如果你想要那种能力,你必须使用postMessagestyle通信。将消息从窗口捕获到contentscript,然后从contentscript,您可以将其发送到其他地方(如果需要,可以发送到background.js 等)

所以在普通网页中,或者在你嵌入到普通页面的注入源中,从你的contentscript.js,发送这样的消息:

window.postMessage( type: "FROM_PAGE_TO_CONTENT_SCRIPT", 
     text: "Hello from the webpage!" , "*");

例如,您可以将其添加到这样的按钮中:

document.getElementById("theButton").addEventListener("click",
    function() 
       window.postMessage( type: "FROM_PAGE_TO_CONTENT_SCRIPT", 
                            text: "Hello from the webpage!" , "*");
, false);

然后要在 contentscript.js 中捕获它并将其“发送到”扩展程序的其余部分,唯一需要注意的是您只想“选择”似乎是您关心的消息:

window.addEventListener("message", function(event) 
  // We only accept messages from this window to itself [i.e. not from any iframes]
  if (event.source != window)
    return;

  if (event.data.type && (event.data.type == "FROM_PAGE_TO_CONTENT_SCRIPT"))         
    chrome.runtime.sendMessage(event.data); // broadcasts it to rest of extension, or could just broadcast event.data.payload...
   // else ignore messages seemingly not sent to yourself
, false);

【讨论】:

【参考方案4】:

您可以使用页面开发者 JS 控制台底部的 <page context> 菜单切换到内容脚本的 JS 执行上下文,然后像在内容脚本中一样使用 chrome.runtime.sendMessage 和其他 chrome.* API .

【讨论】:

如果屏幕截图中显示的执行上下文切换菜单没有出现,可能是什么原因(Chrome v 39.0.2171.95 m,Windows 7)? 仅供参考 - 我可以通过打开扩展页面 (chrome://extensions) 并单击 Inspect views: background page 链接来访问扩展上下文控制台,因此缺少上下文切换菜单真的不是什么大问题。 在最近的版本中,Chrome 将执行上下文菜单与框架菜单结合在一起。如果您的扩展程序在页面中有内容脚本,您现在应该会在<top frame> 下看到它。 感谢您的提示。不幸的是,当我单击下拉菜单时,我只看到<top frame>,即使页面脚本能够毫无问题地与扩展程序通信。但由于我可以使用扩展页面中的背景页面链接,这只是一个表面问题。 @mrts 后台脚本!= 内容脚本。这里有 3 个独立的 JS 执行上下文:页面脚本(默认情况下您在控制台中看到的内容)、后台脚本(您在检查后台页面时看到的内容,并且是所有 Chrome 选项卡的通用 [一个实例])和内容脚本,它在 manifest.json 中定义的给定选项卡 + 给定 url 内运行。如果您将window.foo = 'bar'; 放在内容脚本中,您将不会在后台页面检查控制台中看到它。 afaics 只能通过 jaredjacobs 在此处指出的下拉列表(现在位于“顶部”下方)查看。【参考方案5】:

除了@hewigovens,我没有足够的积分来评论...... 我在解释@renatoargh 和@sbichenko 如果从默认网页发送消息 -

1) 网页需要在 manifest 中引用。例如:

"externally_connectable": 
  "matches": ["http://abcde/abcde/main.aspx*"]

2) background.js(背景页面) 使用 onMessageExternal 的调用除外,例如(呼叫分机):

var host_name = "com.my_chrome_extension.com";
 chrome.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) 
    chrome.runtime.sendNativeMessage(host_name, "run":message);
    sendResponse("success": "success");
    return true;
);

【讨论】:

以上是关于从网页向 chrome 扩展发送消息的主要内容,如果未能解决你的问题,请参考以下文章

为啥从 WatchKit 扩展向 iOS 发送消息并得到回复如此缓慢?

通过 POST 请求向 Discord 频道发送消息会导致代码 401

是否可以向 Chrome 中的现有 websocket 连接发送消息?

在弹出窗口中从 iframe 向后台脚本发送消息

尝试从扩展包中的 html 窗口向内容脚本发送消息

如何在 chrome 扩展本机消息传递和 c# 应用程序之间发送/接收消息