In q-comm Kris attempts to reconcile the JSON-based messaging solutions:
MessagePort
same-domain iframes
Web Sockets
Web Workers
Bizarrely or perhaps "as you expect", these all use --almost-- identical APIs.
I've extended his code to cross-domain iframes. But I'm unsure if my changes will work of the other cases. I'm going to try to describe the multiple iframe cross-domain solution. I've read a lot of partial or inaccurate discussions. Hopefully I'll add not subtract....
The fundamental issue, or the lowest common denominator, is that in the cross-domain case the *only* operation you can perform on your communicating partner is "postMessage()". In fact you can't even attempt another operation without getting errors. Especially of interest, there is no way to know the load state of your messaging partner, except through postMessage events. (One special case I have exploited is to dynamically load the iframe to know for sure the order; this constraint I'd like to avoid).
The reciprocal operation to otherWindow.postMessage() is myWindow.addEventListener('message', handler, false). As the messaging theoretically asynchronous, you have to be prepared for replies before you issue postMessage() . So the fundamental starting point has to be a pair of calls:
myWindow.addEventListener('message', handler, false);
otherWindow.postMessage(...introduction...);
This pair of calls will be issued in two different frames with no way to know which will be first. Who ever goes first will issue a postMessage that cannot be heard by the intended recipient. The second caller will succeed, but it has no way to know that it is has been successful.
Thus we have to follow the above ...introduction... with an ...ack... message. The first caller will get ...introduction...; it must send ...ack... back to the second caller. Then both ends will know that the communications channel is up and ready for normal traffic.
However we also have to deal with multiple iframes using only the 'postMessage' and 'addEventListener'. We can direct postMessage messages to a window but we must accept all inputs via the |handler|, without being able to distinguish them with out-of-band info. A second iframe of the main window or an iframe in an iframe must use the same |handler| we already have bound above: we must de-multiplex multiple frames.
(Well we have event.origin, but it means iframes from the same site would all be mixed up. I have also used removeEventListener to detach the introduction channel, but this does not work for multiple iframes).
Since the same handler must be used for our q-comm traffic and for the introduction/ack sequence from different iframes, I conclude that
1) the introduction/ack sequence must be part of the q-comm protocol, and
2) identifiers for the endpoints must be sent in-band and the routing must be part of q-comm.
This way we are always ready for another iframe whenever it arrives and we just dispatch the events internally.
All of this is rather more complex than I would like, so I'm hoping someone will just say "Oh, no you just need to ....".
This hand shake business does not seem to be required for WebWorkers. The worker object allows operations like onmessage or port.addEventListener that allow a unique handler to be associated with each WebWorker. No hand shake/ no demultiplexing.
This hand shake business does seem to be required for MessagePorts since the only way to get one is via a postMessage. (My attempts to use this feature have failed, I guess because they don't in browser extensions). However, the demultiplexing would not be needed.
Same-domain iframes have more API, but if q-comm worked with cross-domain frames it would still work with same-domain iframes.
WebSockets already have an elaborate introduction ceremony API to solve these issues. Plus the issue of 'who's on first' is baked in: the server is first.
Any inputs?
jjb