Don't unpack posted messages bound for remote windows.

Doing so causes them to lose their transferable data and later fail
deserialization. This happens implicitly when a MessageEvent is
constructed, so don't construct a MessageEvent.

Instead, use a simple struct to pass the needed data around and then
either unpack it into a MessageEvent (local) or convert it to Mojo IPC
data (remote) as appropriate.

Bug: 1212748
Change-Id: Iab433a23f9e7db1406ccbb14ee7ef73258cf2cad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3036167
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#903506}
diff --git a/webmessaging/postMessage_crosssite.sub.htm b/webmessaging/postMessage_crosssite.sub.htm
new file mode 100644
index 0000000..25bccd9
--- /dev/null
+++ b/webmessaging/postMessage_crosssite.sub.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+async function addIframeAndReceiveMessage(path) {
+  let url = new URL('resources/transfer-arraybuffer-to-parent.html', location);
+  url.hostname = '{{hosts[alt][]}}';
+
+  let frame = document.createElement('iframe');
+  try {
+    frame.src = url;
+    document.body.appendChild(frame);
+    return await new Promise((resolve, reject) => {
+      window.addEventListener('message', e => resolve(e));
+      window.addEventListener('messageerror', e => reject(new Error('received messageerror')));
+    });
+  } finally {
+    frame.remove();
+  }
+}
+
+promise_test(async () => {
+  let messageEvent = await addIframeAndReceiveMessage('resources/transfer-arraybuffer-to-parent.html');
+  assert_class_string(messageEvent.data, 'ArrayBuffer');
+  assert_array_equals(new Uint8Array(messageEvent.data), [42, 222]);
+}, "cross-site windows can send transferred ArrayBuffer");
+</script>
+</body>
diff --git a/webmessaging/resources/transfer-arraybuffer-to-parent.html b/webmessaging/resources/transfer-arraybuffer-to-parent.html
new file mode 100644
index 0000000..97cff4d
--- /dev/null
+++ b/webmessaging/resources/transfer-arraybuffer-to-parent.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<script>
+let ab = new Uint8Array([42, 222]).buffer;
+window.parent.postMessage(ab, '*', [ab]);
+</script>