summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/portals/portals-host-post-message.sub.html
blob: d589235ec3bf9befbe8e41dd98d98134fea887a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<!DOCTYPE html>
<title>Test postMessage on PortalHost</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
  <script>
    function createPortal(portalSrc) {
      var portal = document.createElement("portal");
      portal.src = portalSrc;
      return new Promise((resolve, reject) => {
        portal.onload = () => {
          resolve(portal);
        };
        document.body.appendChild(portal);
      });
    }

    async function createPortalAndLoopMessage(portalSrc, params) {
      assert_implements("HTMLPortalElement" in self);
      var portal = await createPortal(portalSrc);
      var waitForResponse = new Promise((resolve, reject) => {
        portal.addEventListener("message", e => { resolve(e); });
      });
      portal.postMessage(params);
      return waitForResponse;
    }

    const sameOriginUrl = "resources/portal-host-post-message.html";
    const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-post-message-x-origin.html";

    promise_test(async () => {
      var {data, origin} = await createPortalAndLoopMessage(sameOriginUrl,
                                                            ["test"]);
      assert_equals(data, "test");
      assert_equals(origin, "http://{{host}}:{{ports[http][0]}}");
    }, "Message received after postMessage from portal host");

    promise_test(async () => {
      var message = {
        prop1: "value1",
        prop2: 2.5,
        prop3: [1, 2, "3"],
        prop4: {
          prop4_1: "value4_1"
        }
      };
      var {data} = await createPortalAndLoopMessage(sameOriginUrl,
                                                    [message]);
      assert_object_equals(data, message);
    }, "postMessage with object message");

    promise_test(async () => {
      assert_implements("HTMLPortalElement" in self);
      function checkPort(port) {
        return new Promise((resolve, reject) => {
          var channel = new MessageChannel();
          channel.port1.onmessage = resolve;
          port.postMessage("sending port", {transfer: [channel.port2]});
        });
      }

      var {ports} = await createPortalAndLoopMessage(sameOriginUrl, {
        type: "message-port"
      });
      await checkPort(ports[0]);
    }, "postMessage with message ports");

    promise_test(async () => {
      var {data} = await createPortalAndLoopMessage(sameOriginUrl, {
        type: "array-buffer-without-transfer",
        array: [0, 1, 2, 3, 4]
      });
      assert_array_equals([0, 1, 2, 3, 4], new Int8Array(data.arrayBuffer));
    }, "postMessage with array buffer without transfer");

    promise_test(async () => {
      var {data} = await createPortalAndLoopMessage(sameOriginUrl, {
        type: "array-buffer-with-transfer",
        array: [0, 1, 2, 3, 4]
      });
      assert_array_equals([0, 1, 2, 3, 4], new Int8Array(data.arrayBuffer));
    }, "postMessage with array buffer with transfer");

    promise_test(async () => {
      var {data} = await createPortalAndLoopMessage(sameOriginUrl, {
        type: "invalid-message"
      });
      assert_equals(data.errorType, "DataCloneError");
    }, "postMessage should throw error when serialization fails");

    promise_test(async () => {
      var {data} = await createPortalAndLoopMessage(sameOriginUrl,{
        type: "invalid-port"
      });
      assert_equals(data.errorType, "TypeError");
    }, "postMessage with invalid transferable should throw error");

    promise_test(async () => {
      assert_implements("HTMLPortalElement" in self);
       var receiveMessage = new Promise((resolve, reject) => {
         var bc = new BroadcastChannel("portal-host-post-message-after-activate");
         bc.onmessage = e => { resolve(e); };
       });
       const portalUrl = encodeURIComponent(
          "portal-host-post-message-after-activate.html");
       window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
       var message = await receiveMessage;
       assert_equals(message.data, "InvalidStateError");
    }, "Calling postMessage after receiving onactivate event should fail");

    promise_test(() => {
      assert_implements("HTMLPortalElement" in self);
      var portal = document.createElement("portal");
      portal.src = "resources/portal-host-post-message-navigate-1.html";
      var count = 0;
      var waitForMessages = new Promise((resolve, reject) => {
        portal.addEventListener("message", e => {
          count++;
          if (count == 2)
            resolve();
        });
      });
      document.body.appendChild(portal);
      return waitForMessages;
    }, "postMessage before and after portal navigation should work");

    const TIMEOUT_DURATION_MS = 1000;

    promise_test(t => new Promise((resolve, reject) => {
      const portal = document.createElement('portal');
      portal.src = crossOriginUrl;
      portal.onmessage = () => reject('should not have received message');
      document.body.appendChild(portal);
      t.step_timeout(resolve, TIMEOUT_DURATION_MS);
    }), "postMessage from portal host in cross-origin-portal should be blocked");
  </script>
</body>