Reputation: 93
I am stuck in a problem where i have to redirect from a popup window to a different domain and post a message to it. Here is the scenario :-
I am able to receive messages if i open fresh popup and do post message but not in the case of redirection. Here is my code:
function redirect(formData,popup) {
//popup=window ref object
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://domain_one.com")
return;
let data=event.data;
//....
}
Upvotes: 8
Views: 2807
Reputation: 1
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>
Upvotes: 0
Reputation: 1
You can pass the form data to "http://domain_two.com"
using query string parameters then parse the query string of location.href
at load
event of the second domain
popup.location.href = `http://domain_two.com?${new URLSearchParams(formData.entries()).toString()}`
Upvotes: 0