【问题标题】:What are the alternatives to window.postMessage for sending a message between the page and content script?在页面和内容脚本之间发送消息的 window.postMessage 的替代方法是什么?
【发布时间】:2017-03-10 10:27:27
【问题描述】:

我正在使用 Firefox WebExtension,它在网页和本机可执行文件之间建立链接(使用本机消息 API)。

到目前为止,我一直在使用一对内容/背景脚本,并使用window.PostMessage 发送/接收消息,如下所示:

页面脚本

// Method used to communicate with content sript of the Firefox WebExtension

var callExtension = function(JSONmessage, timeout, callbackFnk) {

    var promiseRequest = new Promise((resolve, reject) => {
      const listener = (event) => {
        if (
          event.source == window && event.data.direction
          && event.data.direction == "my-extension-from-content-script"
        ) {
          resolve(event.data.message);
        }
      }

      setTimeout(() => {
        window.removeEventListener("message", listener);
        resolve(false); // Timeout 
      }, timeout);

      window.addEventListener("message", listener);

      window.postMessage({
        direction: "my-extension-from-page-script",
        message: JSONmessage
        }, "*");
    });

    promiseRequest.then((result) => { 

         // now we are calling our own callback function
          if(typeof callbackFnk == 'function'){
            callbackFnk.call(this, result);
          }

    });

};

// Checks the presence of the extension

callExtension("areYouThere", 200, function(result) { 
    if(result) {
        $("#result").text("Extension installed");
    } else {
        $("#result").text("Extension not installed");
    }
});

内容脚本

window.addEventListener("message", function(event) {
  if (event.source == window &&
      event.data.direction &&
      event.data.direction == "my-extension-from-page-script") {

    if(event.data.message == "areYouThere") { 

        /** Checks the presence of the extension **/

        window.postMessage({
        direction: "my-extension-from-content-script",
        message: "OK"
      }, "*");
    } 
  } 
});

代码在一个简单的网页上运行良好,但是当我尝试让它在已经使用 window.postMessagewindow.addEventListener ("message", ...) 的页面上运行时,扩展程序不会捕获从页面发送的消息,并且所以我的扩展程序无法工作。

  1. 有没有办法将消息从页面脚本发送到不使用window.postMessagewindow.addEventListener 的内容脚本?

  2. 如果不是,如何确保从页面从window.postMessage 发送的消息将仅发送到我的扩展程序并且不会被其他侦听器捕获?

【问题讨论】:

  • 为了能够回答这个问题(不只是猜测它发生的原因),我们需要一个 complete minimal reproducible example(包括一个 manifset .json 文件)以及您尝试完成此操作的实际 URL,但它失败了。

标签: javascript jquery firefox postmessage firefox-addon-webextensions


【解决方案1】:

您正在使用的网页似乎与window.postMessage 不兼容。这是可以理解的,因为这样的网页通常会期望成为页面中唯一使用它的东西。

您有四种选择:

  1. 在网页脚本安装任何侦听器之前,在window 上安装message 事件侦听器,以便您首先收到事件。这很可能通过注入document_start 并在加载页面的脚本之前安装您的侦听器来完成。除了您对.addEventListener() 的调用在页面上的任何脚本执行之前(即在document_start 注入),您应该指出您的听众将useCapture。这将导致在页面脚本添加的任何侦听器之前调用您的侦听器。您将需要在消息内容中唯一标识消息发往/来自您的分机代码。对于属于您的消息,您需要取消事件(.stopImmediatePropagation().stopPropagation()),并允许事件传播给不属于您的消息。
  2. 只为您的扩展使用custom event
  3. 通过插入额外的<script> 元素,在页面上下文中直接操作变量/函数和/或调用函数。
  4. 动态更改网页脚本的代码,使其运行良好。这仅适用于单个页面/域,并且如果网页更改其代码,则很容易中断。虽然可能,但这不是一个好的选择。

【讨论】:

  • 非常感谢您快速而详尽的回答!
  • @Makyen 我尝试了 1 号来解决我遇到的另一个问题,但它不起作用。应该是?我认为 webextension 是沙盒的,只有一个干净的 DOM 视图,但无法访问它的 javascript?
  • @SebastianBlask #1 不依赖于访问页面的 JavaScript,只依赖于 DOM。如果你需要访问页面的 JavaScript,你必须insert a script into the page's context。如果不查看代码并知道要运行的页面,我无法回答您的问题。
  • @Makyen 对我来说,stopImmediatePropagationstopPropagation 不起作用。我认为由于沙盒,它们不会影响页面的脚本。但他们确实如此。它对我不起作用,因为该页面的代码在我之前运行。在addListener 中使用document_startuseCapture 解决了这个问题。
  • @SebastianBlask,是的,您需要在捕获阶段而不是冒泡阶段安装侦听器。感谢您指出我已将该要求保留为隐含而不是明确说明该需求。如果您没有在捕获阶段安装您的侦听器,那么它将在所有其他添加的侦听器之后调用,除了那些也在window 和在您之后添加的冒泡阶段的侦听器。我已更新此答案以明确声明您需要使用捕获(使用捕获是我的一般默认假设)。
【解决方案2】:

从您的内容脚本中导出一个函数,然后可以从页面调用它。

内容脚本

var myContentScriptFunction = function(myVariable) {
    alert(myVariable);
}

exportFunction(myContentScriptFunction, window, {defineAs: 'myContentScriptFunction'});

页面脚本

if (window.myContentScriptFunction) window.myContentScriptFunction('Working');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-25
    • 2023-03-14
    • 2016-11-13
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多