最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin0浏览0评论

I'm using a Firefox WebExtension that makes the link between a web page and a native executable (using native messaging API).

So far, I've been using a pair of content / background scripts, and I send / receive messages using window.PostMessage like this:

Page Script

// Method used to municate 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");
    }
});

Content Script

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"
      }, "*");
    } 
  } 
});

The code works fine on a simple web page, but when I try to make it work on a page that already uses a window.postMessage and window.addEventListener ("message", ...), the message sent from the page is not captured by the extension, and so my extension cannot work.

  1. Is there a way to send a message from the page script to the content script that does not use window.postMessage and window.addEventListener?

  2. If not, how to be sure the message that is sent from window.postMessage from the page will be sent only to my extension and will not be captured by another listener?

I'm using a Firefox WebExtension that makes the link between a web page and a native executable (using native messaging API).

So far, I've been using a pair of content / background scripts, and I send / receive messages using window.PostMessage like this:

Page Script

// Method used to municate 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");
    }
});

Content Script

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"
      }, "*");
    } 
  } 
});

The code works fine on a simple web page, but when I try to make it work on a page that already uses a window.postMessage and window.addEventListener ("message", ...), the message sent from the page is not captured by the extension, and so my extension cannot work.

  1. Is there a way to send a message from the page script to the content script that does not use window.postMessage and window.addEventListener?

  2. If not, how to be sure the message that is sent from window.postMessage from the page will be sent only to my extension and will not be captured by another listener?

Share Improve this question edited Mar 10, 2017 at 17:28 Makyen 33.4k12 gold badges92 silver badges125 bronze badges asked Mar 10, 2017 at 10:27 ThordaxThordax 1,7334 gold badges29 silver badges59 bronze badges 1
  • To be able to answer this (without just guessing as to why it is occurring), we are going to need a plete minimal reproducible example (including a manifset.json file) along with the actual URL on which you are trying to acplish this and it is failing. – Makyen Commented Mar 10, 2017 at 17:00
Add a ment  | 

2 Answers 2

Reset to default 3

It appears that the web page that you are working with is not playing nice with window.postMessage. This is understandable, as such a web page would normally be expecting to be the only thing using it in the page.

You have four alternatives:

  1. Install your message event listener on the window before the web page scritps install any listeners so that you receive the event first. This will most likely be done by injecting at document_start and installing your listener prior to the scripts for the page being loaded. In addition to your call to .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()) for those messages which are yours, and allow the event to propagate for those that are not.
  2. Use a custom event just for your extension.
  3. Directly manipulate variables/functions and/or call functions in the page context by inserting additional <script> elements.
  4. Dynamically change the code of the web page's scripts so they play nice. This will only work on a single page/domain and could easily break if the web page changes its code. While possible, this is not a good option.

Export a function from your content script, and then can call that from the page.

Content Script

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

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

Page Script

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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论