用于在页面和内容脚本之间发送消息的window.postMessage有哪些替代方法?

时间:2017-03-10 10:27:27

标签: javascript jquery firefox postmessage firefox-webextensions

我正在使用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发送的邮件只会发送到我的扩展程序,而不会被其他收听者捕获?

2 个答案:

答案 0 :(得分:2)

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

您有四种选择:

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

答案 1 :(得分:0)

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

内容脚本

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

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

页面脚本

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