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_SECOND, 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
189
190 @Test
191 @Alerts({"data: hello", "source: true false"})
192 public void postMessageFromClick() throws Exception {
193 final String html = DOCTYPE_HTML
194 + "<html>\n"
195 + "<head></head>\n"
196 + "<body>\n"
197 + "<script>\n"
198 + LOG_TITLE_FUNCTION
199 + " function receiveMessage(event) {\n"
200 + " log('data: ' + event.data);\n"
201 + " var win = document.getElementById('myFrame').contentWindow;\n"
202 + " log('source: ' + (event.source === win) + ' ' + (event.source === window));\n"
203 + " }\n"
204
205 + " window.addEventListener('message', receiveMessage, false);\n"
206 + "</script>\n"
207 + " <iframe id='myFrame' src='" + URL_THIRD + "'></iframe>\n"
208 + "</body></html>";
209
210 final String iframe = "<html><body>\n"
211 + " <button id='clickme' onclick='top.postMessage(\"hello\", \"*\");'>Click me</a>\n"
212 + "</body></html>";
213
214 getMockWebConnection().setResponse(URL_THIRD, iframe);
215 final WebDriver driver = loadPage2(html);
216 driver.switchTo().frame("myFrame");
217 driver.findElement(By.id("clickme")).click();
218
219 verifyTitle2(driver, getExpectedAlerts());
220 }
221
222
223
224
225 @Test
226 @Alerts("sync: false")
227 public void postMessageSyncOrAsync() throws Exception {
228 final String html = DOCTYPE_HTML
229 + "<html>\n"
230 + "<head></head>\n"
231 + "<body>\n"
232 + "<script>\n"
233 + LOG_TITLE_FUNCTION
234 + " var sync = true;\n"
235 + " function receiveMessage(event) {\n"
236 + " log('sync: ' + sync);\n"
237 + " }\n"
238 + " window.addEventListener('message', receiveMessage, false);\n"
239 + "</script>\n"
240 + " <iframe src='" + URL_SECOND + "'></iframe>\n"
241 + "</body></html>";
242
243 final String iframe = DOCTYPE_HTML
244 + "<html><body><script>\n"
245 + " top.postMessage('hello', '*');\n"
246 + " top.sync = false;\n"
247 + "</script></body></html>";
248
249 getMockWebConnection().setResponse(URL_SECOND, iframe);
250 loadPageVerifyTitle2(html);
251 }
252
253
254
255
256 @Test
257 @Alerts("received")
258 public void postMessage_exactURL() throws Exception {
259 postMessage(URL_FIRST.toExternalForm());
260 }
261
262
263
264
265 @Test
266 @Alerts({})
267 public void postMessage_slash() throws Exception {
268 postMessage("/");
269 }
270
271
272
273
274 @Test
275 @Alerts("received")
276 public void postMessageSameOrigin_slash() throws Exception {
277 postMessageSameOrigin("/");
278 }
279
280
281
282
283 @Test
284 @Alerts({})
285 public void postMessage_otherHost() throws Exception {
286 postMessage("http://127.0.0.1:" + PORT + "/");
287 }
288
289
290
291
292 @Test
293 @Alerts({})
294 public void postMessageSameOrigin_otherHost() throws Exception {
295 postMessageSameOrigin("http://127.0.0.1:" + PORT + "/");
296 }
297
298
299
300
301 @Test
302 @Alerts({})
303 public void postMessage_otherPort() throws Exception {
304 postMessage("http://localhost:" + (PORT + 1) + "/");
305 }
306
307
308
309
310 @Test
311 @Alerts({})
312 public void postMessageSameOrigin_otherPort() throws Exception {
313 postMessageSameOrigin("http://localhost:" + (PORT + 1) + "/");
314 }
315
316
317
318
319 @Test
320 @Alerts({})
321 public void postMessage_otherProtocol() throws Exception {
322 postMessage("https://localhost:" + PORT + "/");
323 }
324
325
326
327
328 @Test
329 @Alerts({})
330 public void postMessageSameOrigin_otherProtocol() throws Exception {
331 postMessageSameOrigin("https://localhost:" + PORT + "/");
332 }
333
334 private void postMessage(final String url) throws Exception {
335 final String html = DOCTYPE_HTML
336 + "<html>\n"
337 + "<head></head>\n"
338 + "<body>\n"
339 + "<script>\n"
340 + LOG_TITLE_FUNCTION
341 + " function receiveMessage(event) {\n"
342 + " log('received');\n"
343 + " }\n"
344 + " window.addEventListener('message', receiveMessage, false);\n"
345 + "</script>\n"
346 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
347 + "</body></html>";
348
349 final String iframe = DOCTYPE_HTML
350 + "<html><body><script>\n"
351 + " top.postMessage('hello', '" + url + "');\n"
352 + "</script></body></html>";
353
354 getMockWebConnection().setResponse(URL_THIRD, iframe);
355 loadPageVerifyTitle2(html, getExpectedAlerts());
356 }
357
358 private void postMessageSameOrigin(final String url) throws Exception {
359 final String html = DOCTYPE_HTML
360 + "<html>\n"
361 + "<head></head>\n"
362 + "<body>\n"
363 + "<script>\n"
364 + LOG_TITLE_FUNCTION
365 + " function receiveMessage(event) {\n"
366 + " log('received');\n"
367 + " }\n"
368 + " window.addEventListener('message', receiveMessage, false);\n"
369 + "</script>\n"
370 + " <iframe src='" + URL_SECOND + "'></iframe>\n"
371 + "</body></html>";
372
373 final String iframe = DOCTYPE_HTML
374 + "<html><body><script>\n"
375 + " top.postMessage('hello', '" + url + "');\n"
376 + "</script></body></html>";
377
378 getMockWebConnection().setResponse(URL_SECOND, iframe);
379 loadPageVerifyTitle2(html, getExpectedAlerts());
380 }
381
382
383
384
385 @Test
386 @Alerts("SyntaxError/DOMException")
387 public void postMessageTargetOriginNotUrl() throws Exception {
388 postMessageInvalidTargetOrigin("abcd");
389 }
390
391
392
393
394 @Test
395 @Alerts("SyntaxError/DOMException")
396 public void postMessageTargetOriginEmpty() throws Exception {
397 postMessageInvalidTargetOrigin("");
398 }
399
400
401
402
403 @Test
404 @Alerts("SyntaxError/DOMException")
405 public void postMessageTargetOriginSubpath() throws Exception {
406 postMessageInvalidTargetOrigin("/abc");
407 }
408
409 private void postMessageInvalidTargetOrigin(final String targetOrigin) throws Exception {
410 final String html = DOCTYPE_HTML
411 + "<html>\n"
412 + "<head></head>\n"
413 + "<body>\n"
414 + "<script>\n"
415 + LOG_TITLE_FUNCTION
416 + " try {\n"
417 + " window.postMessage('hello', '" + targetOrigin + "');\n"
418 + " } catch(e) {\n"
419 + " logEx(e);\n"
420 + " }\n"
421 + "</script>\n"
422 + "</body></html>";
423
424 loadPageVerifyTitle2(html);
425 }
426
427
428
429
430 @Test
431 @Alerts("data: 2")
432 public void postMessage_jsonPayload() throws Exception {
433 final String html = DOCTYPE_HTML
434 + "<html>\n"
435 + "<head></head>\n"
436 + "<body>\n"
437 + "<script>\n"
438 + LOG_TITLE_FUNCTION
439 + " function receiveMessage(event) {\n"
440 + " log('data: ' + event.data.outer);\n"
441 + " }\n"
442
443 + " window.addEventListener('message', receiveMessage, false);\n"
444 + "</script>\n"
445 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
446 + "</body></html>";
447
448 final String iframe = DOCTYPE_HTML
449 + "<html><body><script>\n"
450 + " top.postMessage({outer: 2}, '*');\n"
451 + "</script></body></html>";
452
453 getMockWebConnection().setResponse(URL_THIRD, iframe);
454 loadPageVerifyTitle2(html);
455 }
456
457
458
459
460 @Test
461 @Alerts("data: innerProperty")
462 public void postMessage_jsonPayloadWithNestedObjects() throws Exception {
463 final String html = DOCTYPE_HTML
464 + "<html>\n"
465 + "<head></head>\n"
466 + "<body>\n"
467 + "<script>\n"
468 + LOG_TITLE_FUNCTION
469 + " function receiveMessage(event) {\n"
470 + " log('data: ' + event.data.inner.property);\n"
471 + " }\n"
472
473 + " window.addEventListener('message', receiveMessage, false);\n"
474 + "</script>\n"
475 + " <iframe src='" + URL_THIRD + "'></iframe>\n"
476 + "</body></html>";
477
478 final String iframe = DOCTYPE_HTML
479 + "<html><body><script>\n"
480 + " top.postMessage({inner: {property: 'innerProperty'}}, '*');\n"
481 + "</script></body></html>";
482
483 getMockWebConnection().setResponse(URL_THIRD, iframe);
484 loadPageVerifyTitle2(html);
485 }
486
487 }