Starting child too long after parent handshake causes handshake message to be missed
cmawhorter opened this issue · comments
Describe the bug
Initiating parent handshake before child causes bot handshakes to wait indefinitely.
To Reproduce
const parentOrigin = 'https://parent.example.com';
const childOrigin = 'https://child.example.com';
const [parentWindow, childWindow] = makeWindows(parentOrigin, childOrigin);
let parentConnection: Promise<Connection>,
childConnection: Promise<Connection>;
// kick off parent handshake
parentConnection = ParentHandshake(
{},
childWindow,
childWindow.origin,
parentWindow
);
// force a delay so problem always happens
await (new Promise(resolve => setTimeout(resolve, 100));
childConnection = ChildHandshake({}, parentWindow.origin, childWindow);
// never succeeds because both connections miss their message
await Promise.all([parentConnection, childConnection]);
Expected behavior
Both parent and child should continuously retry their handshake message until it succeeds or there is a hard error.
Yep, I can see how we could end up in a deadlock in this example.
Do you think something like this could also happen in the real world?
For example, in the little demo app, I only start the parent side of the handshake after the iframe onload
callback (https://github.com/alesgenova/post-me/blob/main/demo/parent.js#L53), so that I can assume (or at least I hope) that the child is already listening for the handshake.
Is my assumption that it's enough to just put the handshake code in the onload callback wrong?
But even so, it may be good to do at least a few retries, to save the users from themselves :)
Do you think something like this could also happen in the real world?
Yes I do. This is the rule and not exception when working with iframes because iframe events don't fire cross origin so it's not possible to do onload.
Additionally -- no assumptions can be made about the child. Maybe the child handshake starts when a user clicks a button, for example, and not onload.
Because of that, the parent handshake would have to retry continuously until a connection is made (or probably a configurable timeout is hit).
Great, thanks for the explanation, then I will be merging your commit, and maybe build a little further on top of it