Aaronius / penpal

A promise-based library for securely communicating with iframes via postMessage.
MIT License
381 stars 56 forks source link

Question: Why does penpal use Window#postMessage instead of MessageChannel? #87

Open zetlen opened 2 years ago

zetlen commented 2 years ago

MessageChannel has the same features and support matrix as postMessage, but it has a couple of nice extra things. You may have already considered MessageChannel and opted against it; if so, I'd be curious to know why. You might have a good reason that I should avoid them too.

The difference is that a MessageChannel is an independent object that two realms can use instead of sharing the window's global message event stream.

The nice things:

The change would be an additional step in establishing the link, something like:

(simplified, with fake internal functions)

function connectToChild(child) {
  return new Promise((resolve, reject) => {
    const channel = new MessageChannel();
    channel.port1.addEventListener(function finishSetup(event) {
      try {
        validateOrigin(event.origin, child);
        validateAck(event.data);
        channel.port1.removeEventListener(finishSetup);
        resolve(channel.port1);
      } catch(e) {
        reject(e);
      }
    });
    child.postMessage(somePenpalNonce, [channel.port2);
  });
}
function connectToParent() {
  return new Promise((resolve, reject) => {
    window.addEventListener('message', function receivePort(event) {
      try {
        validateOrigin(event.origin);
        validateSyn(event.data);
        window.removeEventListener(receivePort);
        resolve(event.ports[0]);
      } catch(e) {
        reject(e);
      }
    }
  });
}
Aaronius commented 2 years ago

Hey, thanks for asking the question. I wasn't aware of MessageChannel when I was building Penpal. I learned about it in the meantime but just haven't taken the time to explore switching from postMessage. If you'd like to make a pull request, I'd be interested. Otherwise, I'll dig into it when I get the opportunity. Thanks!

tequilaNiu commented 1 year ago

I think MessageChannel is better than window.postMessage.Because it's safer and has two-way communication. But, cannot call function like (parent|child).[declare by your self function], only in the following ways: port2.postMessage({ method: yourFunction, params: { ... } }).I don't know if my understanding is wrong or not. Thanks~