I'm establishing cross-domain communication with JS's postMessage method. An embedded iframe is sending the message and the parent window is receiving it. The issue is that even after checking for origin in receiveMessage (which reduced the number of messages received by a large amount), I'm still receiving two messages, one that I'm posting, and another which was written quite some time ago for a different purpose. So, I can't really modify this other (unwanted) message's postMessage method. Is there a way in the postMessage method or receiveMessage, for that matter, which can help in identifying which one is mine? Maybe some extra parameter or configuration I'm missing here?
Code for postMessage (in the embedded iframe):
window.parent.postMessage("Hello world!", "*");
Code for receiveMessage (in the parent window):
window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
var secureHost = "https" + reliableHost;
var notSecureHost = "http" + reliableHost;
if (e.origin.indexOf(secureHost) != -1 || e.origin.indexOf(notSecureHost) != -1) {
var data = e.data;
console.log(data);
console.log(e.source);
// filter the other event
}
}
Since the data parameter is entirely under your control and can be an object, you can use a convention within the data parameter to ensure you're only handling the messages you care about. Also note that indexOf(...) != -1 may not be quite right, you probably want indexOf(...) == 0 (or startsWith) instead, to avoid matches later in the string.
So on receipt (see *** lines [you have to scroll right with SO's display]):
window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
var secureHost = "https" + reliableHost;
var notSecureHost = "http" + reliableHost;
if ( (e.origin.indexOf(secureHost) == 0 || e.origin.startsWith(notSecureHost) == 0) && // ***
(e.data && e.data.type === "whatever") // ***
) { // ***
var payload = e.data.payload; // ***
console.log(payload); // ***
console.log(e.source);
// filter the other event
}
}
on sending:
postMessage({type: "whatever", payload: /*...*/});
I always use this mechanism with distinct type values so that different channels of communication with the same overall page/app doing interfere with each other.
Yes: instead of passing in a string, e.g. "Hello world!", pass in an object instead, and perform checks against that. You can first check if e.data is typeof object, and then check what properties the object has. You can set any kind of custom properties that allows you to identify the postMessage of interest. For example, the iframe can execute the following line:
window.parent.postMessage({
source: 'my-custom-app',
message: 'Hello world!'
}, '*');
And then when receiving the post message, you can simply check if:
data parameter) is an object, andsource and its value is my-custom-appExample code on the parent page:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
var secureHost = "https" + reliableHost;
var notSecureHost = "http" + reliableHost;
// Guard clause to catch unwanted messages from other hosts
if (e.origin.indexOf(secureHost) === -1 && e.origin.indexOf(notSecureHost) === -1)
return;
var data = e.data;
if (typeof data === 'object' && data.source === 'my-custom-app') {
// Filtered event handling here
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With