window.postMessage 在页面和内容脚本之间发送消息的替代方法是什么?

What are the alternatives to window.postMessage for sending a message between the page and content script?

我正在使用 Firefox WebExtension,它在网页和本机可执行文件之间创建 link(使用本机消息传递 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 发送的消息只会发送到我的分机,而不会被其他侦听器捕获?

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

您有四种选择:

  1. 在网页 scritps 安装任何侦听器之前,在 window 上安装您的 message 事件侦听器,以便您首先收到事件。这很可能是通过在 document_start 注入并在加载页面脚本之前安装监听器来完成的。除了您为那些属于您的消息而调用 .addEventListener() being prior to any script on the page acting (i.e. injecting at document_start), you should indicate that your listener will useCapture. This will cause your listener to be called prior to any listener added by page scripts. You will need to uniquely identify in the message content that messages are to/from your extension code. You will need to cancel the event (.stopImmediatePropagation() and .stopPropagation()) 之外,还允许事件为那些不是您的消息传播。
  2. 只为您的分机使用 custom event
  3. 通过插入额外的 <script> 元素,在页面上下文中直接操作 variables/functions and/or 调用函数。
  4. 动态更改网页脚本的代码,使其运行良好。这仅适用于单个 page/domain,并且如果网页更改其代码,则很容易中断。虽然可能,但这不是一个好的选择。

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

内容脚本

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

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

页面脚本

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