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>