I use postMessage
to send events from an iframe to it's parent document. I have control over both sides but the content comes from two different domains.
My simple problem is, that i can not identify the iFrame inside of it's parent callback method. The implementation looks like this:
In the iFrame:
parent.postMessage(JSON.stringify({action: "closeView" }),'*');
In the parent window:
window.addEventListener('message',function(event) {
if(event.origin !== 'https://example.com')
return;
// Parse message back to json
var messageObject = JSON.parse(event.data);
var source = event.source;
/* this is returning: Window -URL- */
console.log( source );
/* This will throw Permission denied, although this code is inside of "parent" */
console.log(source.parentNode);
},false);
I want to identify a certain parent element of the iframe, which is (logically) inside of the parent document.
When i try to use event.source.parentNode
or some jQuery on said object, Firefox says, i can not do this to prevent XSS, error: Error: Permission denied to access property 'parentNode'
How can i get the parent element of the iFrame, that triggered the postMessage
event listener?
to select the iframe with querySelector . Then we define the canAccessIFrame function that checks if the iframe has the contentDocument property defined. If it's defined then it's not a cross-domain iframe or it's cross domain and cross domain is allowed. Otherwise, false is returned.
PostMessage() is a global method that safely enables cross-origin communication. It's a lot like Ajax but with cross-domain capability. We'll give it a whirl by setting up two-way communication between a web page and an iframe whose content resides on another server.
To access cross-domain iframe, the best approach is to use Javascript's postMessage() method. This method provides a way to securely pass messages across domains.
you can use window names for this, as they pass from iframe tag to iframe context.
parent doc:
<iframe name=fr2 src="data:text/html,%3Chtml%3E%0A%20%3Cscript%3E%20parent.postMessage%28%7Bname%3A%20window.name%7D%2C%20%22*%22%29%3B%3C/script%3E%0A%3C/html%3E"></iframe>
<iframe name=fr3 src="data:text/html,%3Chtml%3E%0A%20%3Cscript%3E%20parent.postMessage%28%7Bname%3A%20name%7D%2C%20%22*%22%29%3B%3C/script%3E%0A%3C/html%3E"></iframe>
<script>onmessage = function(e){ // use real event handlers in production
alert("from frame: " + e.data.name);
};</script>
iframe doc:
<html>
<script> parent.postMessage({name: name}, "*");</script>
</html>
which alerts "fr2", then "fr3". you can then easily use the name attrib to find the iframe in the parent DOM using attrib CSS selectors.
illustrative demo of window.name+iframe concept: http://pagedemos.com/namingframes/
this painfully simple approach is also immune to issues arising from same-url iframes.
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