1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host;
16
17 import org.htmlunit.WebDriverTestCase;
18 import org.htmlunit.junit.annotation.Alerts;
19 import org.junit.jupiter.api.Test;
20 import org.openqa.selenium.By;
21 import org.openqa.selenium.WebDriver;
22
23
24
25
26
27
28
29
30
31 public class WindowPostMessageTest extends WebDriverTestCase {
32
33
34
35
36 @Test
37 @Alerts({"type: message", "bubbles: false", "cancelable: false", "data: hello",
38 "origin: ", "source: true false", "lastEventId: "})
39 public void postMessage() throws Exception {
40 final String[] expectedAlerts = getExpectedAlerts();
41 expectedAlerts[4] += "http://127.0.0.1:" + PORT;
42 setExpectedAlerts(expectedAlerts);
43
44 final String html = DOCTYPE_HTML
45 + "<html>\n"
46 + "<head></head>\n"
47 + "<body>\n"
48 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
49 + "<script>\n"
50 + LOG_TITLE_FUNCTION
51 + " var win = document.getElementById('myFrame').contentWindow;\n"
52
53 + " function receiveMessage(event) {\n"
54 + " log('type: ' + event.type);\n"
55 + " log('bubbles: ' + event.bubbles);\n"
56 + " log('cancelable: ' + event.cancelable);\n"
57 + " log('data: ' + event.data);\n"
58 + " log('origin: ' + event.origin);\n"
59 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
60 + " log('lastEventId: ' + event.lastEventId);\n"
61 + " }\n"
62
63 + " window.addEventListener('message', receiveMessage, false);\n"
64 + "</script>\n"
65 + "</body></html>";
66
67 final String iframe = DOCTYPE_HTML
68 + "<html><body><script>\n"
69 + " top.postMessage('hello', '*');\n"
70 + "</script></body></html>";
71
72 getMockWebConnection().setResponse(URL_THIRD, iframe);
73 loadPageVerifyTitle2(html);
74 }
75
76
77
78
79 @Test
80 @Alerts({"type: message", "bubbles: false", "cancelable: false", "data: hello",
81 "origin: ", "source: false true", "lastEventId: "})
82 public void postMessageFromIframe() throws Exception {
83 final String[] expectedAlerts = getExpectedAlerts();
84 expectedAlerts[4] += "http://localhost:" + PORT;
85 setExpectedAlerts(expectedAlerts);
86
87 final String html = DOCTYPE_HTML
88 + "<html>\n"
89 + "<head></head>\n"
90 + "<body>\n"
91 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
92
93 + "<script>\n"
94 + LOG_TITLE_FUNCTION
95 + " var win = document.getElementById('myFrame').contentWindow;\n"
96
97 + " function receiveMessage(event) {\n"
98 + " log('type: ' + event.type);\n"
99 + " log('bubbles: ' + event.bubbles);\n"
100 + " log('cancelable: ' + event.cancelable);\n"
101 + " log('data: ' + event.data);\n"
102 + " log('origin: ' + event.origin);\n"
103 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
104 + " log('lastEventId: ' + event.lastEventId);\n"
105 + " }\n"
106
107 + " win.addEventListener('message', receiveMessage, false);\n"
108 + " win.postMessage('hello', '*');\n"
109 + "</script>\n"
110 + "</body></html>";
111
112 final String iframe = DOCTYPE_HTML
113 + "<html><body><p>inside frame</p></body></html>";
114
115 getMockWebConnection().setResponse(URL_THIRD, iframe);
116 loadPageVerifyTitle2(html);
117 }
118
119
120
121
122 @Test
123 @Alerts("TypeError")
124 public void postMessageMissingParameters() throws Exception {
125 final String html = DOCTYPE_HTML
126 + "<html>\n"
127 + "<head></head>\n"
128 + "<body>\n"
129 + "<script>\n"
130 + LOG_TITLE_FUNCTION
131 + " try {\n"
132 + " window.postMessage();\n"
133 + " } catch(e) {\n"
134 + " logEx(e);\n"
135 + " }\n"
136 + "</script>\n"
137 + "</body></html>";
138
139 loadPageVerifyTitle2(html);
140 }
141
142
143
144
145 @Test
146 @Alerts({"type: message", "bubbles: false", "cancelable: false", "data: hello",
147 "origin: ", "source: false true", "lastEventId: "})
148 public void postMessageWithoutTargetOrigin() throws Exception {
149 final String[] expectedAlerts = getExpectedAlerts();
150 expectedAlerts[4] += "http://localhost:" + PORT;
151 setExpectedAlerts(expectedAlerts);
152
153 final String html = DOCTYPE_HTML
154 + "<html>\n"
155 + "<head></head>\n"
156 + "<body>\n"
157 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
158
159 + "<script>\n"
160 + LOG_TITLE_FUNCTION
161 + " var win = document.getElementById('myFrame').contentWindow;\n"
162
163 + " function receiveMessage(event) {\n"
164 + " log('type: ' + event.type);\n"
165 + " log('bubbles: ' + event.bubbles);\n"
166 + " log('cancelable: ' + event.cancelable);\n"
167 + " log('data: ' + event.data);\n"
168 + " log('origin: ' + event.origin);\n"
169 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
170 + " log('lastEventId: ' + event.lastEventId);\n"
171 + " }\n"
172
173 + " win.addEventListener('message', receiveMessage, false);\n"
174 + " win.postMessage('hello');\n"
175 + "</script>\n"
176 + "</body></html>";
177
178 final String iframe = DOCTYPE_HTML
179 + "<html><body><p>inside frame</p></body></html>";
180
181 getMockWebConnection().setResponse(URL_THIRD, iframe);
182 loadPageVerifyTitle2(html);
183 }
184
185
186
187
188 @Test
189 @Alerts({"type: message", "bubbles: false", "cancelable: false", "data: hello",
190 "origin: ", "source: false true", "lastEventId: "})
191 public void postMessageWithTransferableOnly() throws Exception {
192 final String[] expectedAlerts = getExpectedAlerts();
193 expectedAlerts[4] += "http://localhost:" + PORT;
194 setExpectedAlerts(expectedAlerts);
195
196 final String html = DOCTYPE_HTML
197 + "<html>\n"
198 + "<head></head>\n"
199 + "<body>\n"
200 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
201
202 + "<script>\n"
203 + LOG_TITLE_FUNCTION
204 + " var win = document.getElementById('myFrame').contentWindow;\n"
205
206 + " function receiveMessage(event) {\n"
207 + " log('type: ' + event.type);\n"
208 + " log('bubbles: ' + event.bubbles);\n"
209 + " log('cancelable: ' + event.cancelable);\n"
210 + " log('data: ' + event.data);\n"
211 + " log('origin: ' + event.origin);\n"
212 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
213 + " log('lastEventId: ' + event.lastEventId);\n"
214 + " }\n"
215
216 + " win.addEventListener('message', receiveMessage, false);\n"
217
218 + " uInt8Array = new Uint8Array(1);\n"
219 + " win.postMessage('hello', [uInt8Array.buffer]);\n"
220 + "</script>\n"
221 + "</body></html>";
222
223 final String iframe = DOCTYPE_HTML
224 + "<html><body><p>inside frame</p></body></html>";
225
226 getMockWebConnection().setResponse(URL_THIRD, iframe);
227 loadPageVerifyTitle2(html);
228 }
229
230
231
232
233
234
235 @Test
236 @Alerts({"data: hello", "source: true false"})
237 public void postMessageFromClick() throws Exception {
238 final String html = DOCTYPE_HTML
239 + "<html>\n"
240 + "<head></head>\n"
241 + "<body>\n"
242 + "<script>\n"
243 + LOG_TITLE_FUNCTION
244 + " function receiveMessage(event) {\n"
245 + " log('data: ' + event.data);\n"
246 + " var win = document.getElementById('myFrame').contentWindow;\n"
247 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
248 + " }\n"
249
250 + " window.addEventListener('message', receiveMessage, false);\n"
251 + "</script>\n"
252 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
253 + "</body></html>";
254
255 final String iframe = "<html><body>\n"
256 + " <button id='clickme' onclick='top.postMessage(\"hello\", \"*\");'>Click me</a>\n"
257 + "</body></html>";
258
259 getMockWebConnection().setResponse(URL_THIRD, iframe);
260 final WebDriver driver = loadPage2(html);
261 driver.switchTo().frame("myFrame");
262 driver.findElement(By.id("clickme")).click();
263
264 verifyTitle2(driver, getExpectedAlerts());
265 }
266
267
268
269
270 @Test
271 @Alerts("sync: false")
272 public void postMessageSyncOrAsync() throws Exception {
273 final String html = DOCTYPE_HTML
274 + "<html>\n"
275 + "<head></head>\n"
276 + "<body>\n"
277 + "<script>\n"
278 + LOG_TITLE_FUNCTION
279 + " var sync = true;\n"
280 + " function receiveMessage(event) {\n"
281 + " log('sync: ' + sync);\n"
282 + " }\n"
283 + " window.addEventListener('message', receiveMessage, false);\n"
284 + "</script>\n"
285 + " <iframe src='" + URL_SECOND + "'></iframe>\n"
286 + "</body></html>";
287
288 final String iframe = DOCTYPE_HTML
289 + "<html><body><script>\n"
290 + " top.postMessage('hello', '*');\n"
291 + " top.sync = false;\n"
292 + "</script></body></html>";
293
294 getMockWebConnection().setResponse(URL_SECOND, iframe);
295 loadPageVerifyTitle2(html);
296 }
297
298
299
300
301 @Test
302 @Alerts("received")
303 public void postMessage_exactURL() throws Exception {
304 postMessage(URL_FIRST.toExternalForm());
305 }
306
307
308
309
310 @Test
311 @Alerts({})
312 public void postMessage_slash() throws Exception {
313 postMessage("/");
314 }
315
316
317
318
319 @Test
320 @Alerts("received")
321 public void postMessageSameOrigin_slash() throws Exception {
322 postMessageSameOrigin("/");
323 }
324
325
326
327
328 @Test
329 @Alerts({})
330 public void postMessage_otherHost() throws Exception {
331 postMessage("http://127.0.0.1:" + PORT + "/");
332 }
333
334
335
336
337 @Test
338 @Alerts({})
339 public void postMessageSameOrigin_otherHost() throws Exception {
340 postMessageSameOrigin("http://127.0.0.1:" + PORT + "/");
341 }
342
343
344
345
346 @Test
347 @Alerts({})
348 public void postMessage_otherPort() throws Exception {
349 postMessage("http://localhost:" + (PORT + 1) + "/");
350 }
351
352
353
354
355 @Test
356 @Alerts({})
357 public void postMessageSameOrigin_otherPort() throws Exception {
358 postMessageSameOrigin("http://localhost:" + (PORT + 1) + "/");
359 }
360
361
362
363
364 @Test
365 @Alerts({})
366 public void postMessage_otherProtocol() throws Exception {
367 postMessage("https://localhost:" + PORT + "/");
368 }
369
370
371
372
373 @Test
374 @Alerts({})
375 public void postMessageSameOrigin_otherProtocol() throws Exception {
376 postMessageSameOrigin("https://localhost:" + PORT + "/");
377 }
378
379 private void postMessage(final String url) throws Exception {
380 final String html = DOCTYPE_HTML
381 + "<html>\n"
382 + "<head></head>\n"
383 + "<body>\n"
384 + "<script>\n"
385 + LOG_TITLE_FUNCTION
386 + " function receiveMessage(event) {\n"
387 + " log('received');\n"
388 + " }\n"
389 + " window.addEventListener('message', receiveMessage, false);\n"
390 + "</script>\n"
391 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
392 + "</body></html>";
393
394 final String iframe = DOCTYPE_HTML
395 + "<html><body><script>\n"
396 + " top.postMessage('hello', '" + url + "');\n"
397 + "</script></body></html>";
398
399 getMockWebConnection().setResponse(URL_THIRD, iframe);
400 loadPageVerifyTitle2(html, getExpectedAlerts());
401 }
402
403 private void postMessageSameOrigin(final String url) throws Exception {
404 final String html = DOCTYPE_HTML
405 + "<html>\n"
406 + "<head></head>\n"
407 + "<body>\n"
408 + "<script>\n"
409 + LOG_TITLE_FUNCTION
410 + " function receiveMessage(event) {\n"
411 + " log('received');\n"
412 + " }\n"
413 + " window.addEventListener('message', receiveMessage, false);\n"
414 + "</script>\n"
415 + " <iframe src='" + URL_SECOND + "'></iframe>\n"
416 + "</body></html>";
417
418 final String iframe = DOCTYPE_HTML
419 + "<html><body><script>\n"
420 + " top.postMessage('hello', '" + url + "');\n"
421 + "</script></body></html>";
422
423 getMockWebConnection().setResponse(URL_SECOND, iframe);
424 loadPageVerifyTitle2(html, getExpectedAlerts());
425 }
426
427
428
429
430 @Test
431 @Alerts("SyntaxError/DOMException")
432 public void postMessageTargetOriginNotUrl() throws Exception {
433 postMessageInvalidTargetOrigin("abcd");
434 }
435
436
437
438
439 @Test
440 @Alerts("SyntaxError/DOMException")
441 public void postMessageTargetOriginEmpty() throws Exception {
442 postMessageInvalidTargetOrigin("");
443 }
444
445
446
447
448 @Test
449 @Alerts("SyntaxError/DOMException")
450 public void postMessageTargetOriginSubpath() throws Exception {
451 postMessageInvalidTargetOrigin("/abc");
452 }
453
454 private void postMessageInvalidTargetOrigin(final String targetOrigin) throws Exception {
455 final String html = DOCTYPE_HTML
456 + "<html>\n"
457 + "<head></head>\n"
458 + "<body>\n"
459 + "<script>\n"
460 + LOG_TITLE_FUNCTION
461 + " try {\n"
462 + " window.postMessage('hello', '" + targetOrigin + "');\n"
463 + " } catch(e) {\n"
464 + " logEx(e);\n"
465 + " }\n"
466 + "</script>\n"
467 + "</body></html>";
468
469 loadPageVerifyTitle2(html);
470 }
471
472
473
474
475 @Test
476 @Alerts("data: 2")
477 public void postMessage_jsonPayload() throws Exception {
478 final String html = DOCTYPE_HTML
479 + "<html>\n"
480 + "<head></head>\n"
481 + "<body>\n"
482 + "<script>\n"
483 + LOG_TITLE_FUNCTION
484 + " function receiveMessage(event) {\n"
485 + " log('data: ' + event.data.outer);\n"
486 + " }\n"
487
488 + " window.addEventListener('message', receiveMessage, false);\n"
489 + "</script>\n"
490 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
491 + "</body></html>";
492
493 final String iframe = DOCTYPE_HTML
494 + "<html><body><script>\n"
495 + " top.postMessage({outer: 2}, '*');\n"
496 + "</script></body></html>";
497
498 getMockWebConnection().setResponse(URL_THIRD, iframe);
499 loadPageVerifyTitle2(html);
500 }
501
502
503
504
505 @Test
506 @Alerts("data: innerProperty")
507 public void postMessage_jsonPayloadWithNestedObjects() throws Exception {
508 final String html = DOCTYPE_HTML
509 + "<html>\n"
510 + "<head></head>\n"
511 + "<body>\n"
512 + "<script>\n"
513 + LOG_TITLE_FUNCTION
514 + " function receiveMessage(event) {\n"
515 + " log('data: ' + event.data.inner.property);\n"
516 + " }\n"
517
518 + " window.addEventListener('message', receiveMessage, false);\n"
519 + "</script>\n"
520 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
521 + "</body></html>";
522
523 final String iframe = DOCTYPE_HTML
524 + "<html><body><script>\n"
525 + " top.postMessage({inner: {property: 'innerProperty'}}, '*');\n"
526 + "</script></body></html>";
527
528 getMockWebConnection().setResponse(URL_THIRD, iframe);
529 loadPageVerifyTitle2(html);
530 }
531
532 }