One issue with the code at the question is that .postMessage() is called immediately following setting a new .location.href at popup without waiting for the load event of window at
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
To achieve the expected result you can control the process from the original window ('index.html'). Each window.name is set to a unique value. When the <form> is submitted at "http://domain_one.com" the resulting FormData can be converted to an ArrayBuffer and transferred to index.html, then popup (a.html) location.href is set to "http://domain_two.com". At load event of b.html .postMessage() the name of the window to index.html. Then the FormData is passed to .postMessage() where b.html gets the FormData that was originally submitted at b.html.
(The origin checks might need to be adjusted at the below code. The code was tested at plnkr, where simulation of cross-domain messaging is not 1:1, though should provide a pattern for how to accomplish the requirement).
index.html (opener)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
// open `popup`
const popup = window.open('a.html');
// create random values to assign to `name` at `a.html` and `b.html`
const [firstName, lastName] = [...Array(2)].map(_ => new Uint32Array(16));
[firstName, lastName].forEach(buffer => window.crypto.getRandomValues(buffer));
const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];
const [first, last] = [firstName, lastName].map(buffer => decoder.decode(buffer));
// set `name` of `popup` (`a.html`) to `first`
popup.name = first;
let data;
window.addEventListener("message", e => {
// check `name` of `source`
if (e.source.name === first) {
console.log(e.source.name);
// store `formData`
data = decoder.decode(e.data);
console.log(e, JSON.parse(decoder.decode(e.data)));
// set `name` of `popup` to `last`
popup.name = last;
// redirect `popup` to `b.html`
popup.location.href = "b.html";
}
// check if `name` of `source` (`b.html`) is `last`
if (e.source.name === last) {
// encode the stored `formData`
let curr = encoder.encode(data);
console.log(e.source.name, e.data);
// transfer `formData` to `b.html`
e.source.postMessage(curr.buffer, e.source.location.href, [curr.buffer]);
// data = void 0;
}
})
</script>
</body>
</html>
a.html (popup, "http://domain_one.com")
<!DOCTYPE html>
<html>
<head>
</head>
<body>
a
<form>
<input name="input">
<input type="submit">
</form>
<script>
document.forms[0].onsubmit = e => {
// prevent default `form` submission
e.preventDefault();
// pass `form` to `FormData`
const formData = new FormData(e.target);
// encode `formData` as a `Uint8Array`
const encoded = new TextEncoder().encode(JSON.stringify([...formData.entries()]));
console.log(encoded);
// transfer `encoded` to `opener` (`index.html`)
opener.postMessage(encoded.buffer, opener.location.href, [encoded.buffer]);
}
</script>
</body>
</html>
b.html (popup, "http://domain_two.com")
<!DOCTYPE html>
<html>
<head>
</head>
<body>
b
<script>
const decoder = new TextDecoder();
let data;
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// check `origin` of `event`
if (event.origin !== opener.location.origin)
return;
console.log(event);
// process `formData` from `popup`
data = JSON.parse(decoder.decode(event.data));
// do stuff with `formData`
p.textContent = JSON.stringify(data, null, 2);
}
// wait for `load` event to be dispatched before posting message to `opener`
onload = () => {
opener.postMessage("ok", opener.location.href);
}
</script>
<pre id="p"></pre>
</body>
</html>
plnkr