How do you use window.postMessage across domains?

JavascriptHtmlGoogle ChromeXss

Javascript Problem Overview


It seems like the point of window.postMessage is to allow safe communication between windows/frames hosted on different domains, but it doesn't actually seem to allow that in Chrome.

Here's the scenario:

  1. Embed an <iframe> (with a src on domain B*) in a page on domain A
  2. The <iframe> ends up being mostly a <script> tag, at the end of which's execution...
  3. I call window.postMessage( some_data, page_on_A )

The <iframe> is most definitely in the context of domain B, and I've confirmed that the embedded javascript in that <iframe> executes properly and calls postMessage with the correct values.

I get this error message in Chrome:

> Unable to post message to A. > Recipient has origin B.

Here's the code that registers a message event listener in the page on A:

window.addEventListener(
  "message",
  function (event) {
    // Do something
  },
  false);

I've also tried calling window.postMessage(some_data, '*'), but all that does is suppress the error.

Am I just missing the point here, is window.postMessage(...) not meant for this? Or am I just doing it horribly wrong?

*Mime-type text/html, which it must remain.

Javascript Solutions


Solution 1 - Javascript

Here is an example that works on Chrome 5.0.375.125.

The page B (iframe content):

<html>
	<head></head>
	<body>
		<script>
			top.postMessage('hello', 'A');
		</script>
	</body>
</html>

Note the use of top.postMessage or parent.postMessage not window.postMessage here

The page A:

<html>
<head></head>
<body>
	<iframe src="B"></iframe>
	<script>
		window.addEventListener( "message",
		  function (e) {
				if(e.origin !== 'B'){ return; } 
				alert(e.data);
		  },
		  false);
	</script>
</body>
</html>

A and B must be something like http://domain.com

EDIT:

From another question, it looks the domains(A and B here) must have a / for the postMessage to work properly.

Solution 2 - Javascript

You should post a message from frame to parent, after loaded.

frame script:

$(document).ready(function() {
    window.parent.postMessage("I'm loaded", "*");
});

And listen it in parent:

function listenMessage(msg) {
    alert(msg);
}

if (window.addEventListener) {
    window.addEventListener("message", listenMessage, false);
} else {
    window.attachEvent("onmessage", listenMessage);
}

Use this link for more info: http://en.wikipedia.org/wiki/Web_Messaging

Solution 3 - Javascript

Probably you try to send your data from mydomain.com to www.mydomain.com or reverse, NOTE you missed "www". http://mydomain.com and http://www.mydomain.com are different domains to javascript.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevin MontroseView Question on Stackoverflow
Solution 1 - JavascriptMicView Answer on Stackoverflow
Solution 2 - JavascriptGolyoView Answer on Stackoverflow
Solution 3 - JavascriptGetoriksView Answer on Stackoverflow