5

I need to pass a message (raise an event) in a Chrome extension, and have JavaScript on a web page react to it.

In content_script.js of the extension, there should be a function like

raiseXYZevent(data);

JavaScript on the web page http://example.com/mypage.html should execute a handler

 function processXYZevent(data) { ... }

The problem is that content script within an extension cannot interact with JavaScript on the web page directly (it can only modify DOM). Is there a way to make DOM changes from the extension, somehow detect them from the web page and call processXYZevent?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
dbkk
  • 12,643
  • 13
  • 53
  • 60

2 Answers2

6

Since the content script and the webpage share the same DOM, you can use window.postMessage() to send messages between them. The Chrome API documentation explains this in detail with examples:

Posting a message from the page to the extension

Inside the content script, waiting to receive the message:

var port = chrome.runtime.connect();

window.addEventListener("message", (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: " + event.data.text);
  }
}, false);

Inside the page (this also includes code you have injected into the page via chrome.scripting.executeScript() or similar), sending a message when a button is clicked:

button.addEventListener("click", () => {
  window.postMessage({
    type : "FROM_PAGE", 
    text : "Hello from the webpage!"
  }, "*");
}, false);

Posting a message from the extension to the page

The docs above mention:

The reverse is possible through similar means.

To do this, simply swap the content script code and the page code in the examples above.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Matthew Gertner
  • 4,487
  • 2
  • 32
  • 54
1

From content script inject this:

$('html').append(`
    <script>

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

        if (event.data.type && (event.data.type == "FROM_CONTENT")) {
          console.log("Page script received: " + event.data.text)
          console.log(event.data.text) // "Something message here"
        }
      }, false)
    <\/script>`)

In content script you can execute this:

window.postMessage({ type: "FROM_CONTENT", text: "Something message here"}, "*")
Hender
  • 343
  • 2
  • 10