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