1<!DOCTYPE html>
2<meta charset=utf-8>
3<script src="/resources/testharness.js"></script>
4<script src="/resources/testharnessreport.js"></script>
5<!-- Pull in the with_iframe helper function from the service worker tests -->
6<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
7<body>
8<script>
9
10const BC0_FIRST_MSG = 'from BC0 - first';
11const BC1_FIRST_MSG = 'from BC1 - first';
12const BC2_FIRST_MSG = 'from BC2 - first';
13const BC3_FIRST_MSG = 'from BC3 - first';
14const BC0_SECOND_MSG = 'from BC0 - second';
15const BC1_SECOND_MSG = 'from BC1 - second';
16const BC2_SECOND_MSG = 'from BC2 - second';
17const BC3_SECOND_MSG = 'done';
18const BC0_TARGET_NAME = 'BC1';
19const BC1_TARGET_NAME = 'BC1';
20const BC2_TARGET_NAME = 'BC2';
21const BC3_TARGET_NAME = 'BC3';
22const MULTI_FRAME_ORDERING_TEST_CHANNEL_NAME = 'multi-frame-order';
23
24const bc0 = new BroadcastChannel(MULTI_FRAME_ORDERING_TEST_CHANNEL_NAME);
25const messages = [];
26
27function logReceivedMessage(targetname, e) {
28  messages.push({'target': targetname, 'data': e.data});
29}
30
31function postMessagesToChannel() {
32  return new Promise((resolve) => {
33    bc0.postMessage(BC0_FIRST_MSG);
34    bc0.postMessage(BC0_SECOND_MSG);
35    resolve();
36  });
37}
38
39// Expected flow of messages between the BroadcastChannel objects (based on
40// the requirement that messages get delivered to BroadcastChannel objects
41// "in creation order, oldest first") and comments describing the actions
42// taken in response to each event
43const EXPECTED_RESULTS = [
44  // -> BC0 sends two messages, BC1 and BC2 are connected to the channel
45
46  {'data': BC0_FIRST_MSG, 'target': BC1_TARGET_NAME},
47  // -> BC1 Creates BC3 and sends first message
48
49  {'data': BC0_FIRST_MSG, 'target': BC2_TARGET_NAME},
50  // -> BC2 sends two messages
51
52  // BC3 isn't expected to receive the messages sent before it was created, so
53  // no corresponding entries here for messages from BC0.
54
55  {'data': BC0_SECOND_MSG, 'target': BC1_TARGET_NAME},
56  // -> BC1 sends second message
57
58  {'data': BC0_SECOND_MSG, 'target': BC2_TARGET_NAME},
59  // -> BC2 closes
60
61  {'data': BC1_FIRST_MSG, 'target': BC0_TARGET_NAME},
62
63  {'data': BC1_FIRST_MSG, 'target': BC3_TARGET_NAME},
64  // -> BC3 sends first message
65
66  {'data': BC2_FIRST_MSG, 'target': BC0_TARGET_NAME},
67
68  {'data': BC2_FIRST_MSG, 'target': BC1_TARGET_NAME},
69  // -> BC1 closes
70
71  {'data': BC2_FIRST_MSG, 'target': BC3_TARGET_NAME},
72  // -> BC3 sends second message
73
74  {'data': BC2_SECOND_MSG, 'target': BC0_TARGET_NAME},
75
76  {'data': BC2_SECOND_MSG, 'target': BC3_TARGET_NAME},
77  // -> BC3 closes
78
79  {'data': BC1_SECOND_MSG, 'target': BC0_TARGET_NAME},
80
81  {'data': BC3_FIRST_MSG, 'target': BC0_TARGET_NAME},
82
83  {'data': BC3_SECOND_MSG, 'target': BC0_TARGET_NAME},
84];
85
86function testCompletion(t) {
87  return new Promise((resolve) => {
88    bc0.onmessage = t.step_func(e => {
89      logReceivedMessage(BC0_TARGET_NAME, e);
90      if (e.data == BC3_SECOND_MSG) {
91        assert_equals(messages.length, EXPECTED_RESULTS.length);
92        for(var i = 0; i < messages.length; i++) {
93          assert_equals(messages[i].target, EXPECTED_RESULTS[i].target, `Message ${i+1} has unexpected target`);
94          assert_equals(messages[i].data, EXPECTED_RESULTS[i].data, `Message ${i+1} has unexpected message contents`);
95        }
96        resolve();
97      }
98    });
99  });
100}
101
102promise_test(async t => {
103
104  const testResults = testCompletion(t);
105  // Await them sequentially because we need the BroadcastChannel object in
106  // iframe1 to be created first, we need the BroadcastChannel object in
107  // iframe2 to be created second, and then we only want to call
108  // postMessagesToChannel once both BroadcastChannels have been created.
109  await with_iframe('resources/ordering.html?id=iframe1');
110  await with_iframe('resources/ordering.html?id=iframe2');
111  await postMessagesToChannel();
112  return testResults;
113}, "Messages are delivered in port creation order across multiple frames");
114
115</script>
116</body>
117