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 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");
}
});
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.
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
?
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?
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:
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.<script>
elements.