1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.xml;
16
17 import static java.nio.charset.StandardCharsets.ISO_8859_1;
18 import static java.nio.charset.StandardCharsets.UTF_8;
19
20 import java.io.IOException;
21 import java.io.Writer;
22 import java.net.URL;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.servlet.Servlet;
29 import javax.servlet.http.HttpServlet;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.htmlunit.HttpHeader;
34 import org.htmlunit.WebDriverTestCase;
35 import org.htmlunit.junit.annotation.Alerts;
36 import org.htmlunit.util.MimeType;
37 import org.htmlunit.util.NameValuePair;
38 import org.junit.jupiter.api.Test;
39 import org.openqa.selenium.WebDriver;
40
41
42
43
44
45
46
47
48
49 public class XMLHttpRequestCORSTest extends WebDriverTestCase {
50
51
52
53
54 @Test
55 @Alerts({"error [object ProgressEvent]", "error", "false", "0", "false"})
56 public void noCorsHeaderCallsErrorHandler() throws Exception {
57 final String html = DOCTYPE_HTML
58 + "<html><head>\n"
59 + "<script>\n"
60 + LOG_TITLE_FUNCTION
61 + "var xhr = new XMLHttpRequest();\n"
62 + "function test() {\n"
63 + " try {\n"
64 + " var url = '" + URL_THIRD + "';\n"
65 + " xhr.open('GET', url, true);\n"
66 + " xhr.onerror = function(event) {\n"
67 + " log('error ' + event);\n"
68 + " log(event.type);\n"
69 + " log(event.lengthComputable);\n"
70 + " log(event.loaded);\n"
71 + " log(event.total > 0);\n"
72 + " };\n"
73 + " xhr.send();\n"
74 + " } catch(e) { logEx(e); }\n"
75 + "}\n"
76 + "</script>\n"
77 + "</head>\n"
78 + "<body onload='test()'></body></html>";
79 getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
80
81 loadPage2(html);
82 verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
83 }
84
85
86
87
88 @Test
89 @Alerts({"4", "200", "<root><origin>§§URL§§</origin><cookie>null</cookie></root>"})
90 public void simple() throws Exception {
91 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
92
93 final String html = DOCTYPE_HTML
94 + "<html><head>\n"
95 + "<script>\n"
96 + LOG_TITLE_FUNCTION
97 + "var xhr = new XMLHttpRequest();\n"
98 + "function test() {\n"
99 + " try {\n"
100 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/simple2';\n"
101 + " xhr.open('GET', url, false);\n"
102 + " xhr.send();\n"
103 + " log(xhr.readyState);\n"
104 + " log(xhr.status);\n"
105 + " log(xhr.responseText);\n"
106 + " } catch(e) { log(e) }\n"
107 + "}\n"
108 + "</script>\n"
109 + "</head>\n"
110 + "<body onload='test()'></body></html>";
111
112 SimpleServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "*";
113 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
114 servlets2.put("/simple2", SimpleServerServlet.class);
115 startWebServer2(".", null, servlets2);
116
117 final List<NameValuePair> responseHeader = new ArrayList<>();
118 responseHeader.add(new NameValuePair("Set-Cookie", "cookie=sweet"));
119
120 final URL url = new URL(URL_FIRST, "/simple1");
121 getMockWebConnection().setResponse(url, html,
122 200, "OK", "text/html;charset=ISO-8859-1", ISO_8859_1, responseHeader);
123
124 loadPage2(url, null);
125 verifyTitle2(getWebDriver(), getExpectedAlerts());
126 }
127
128
129
130
131 @Test
132 @Alerts({"4", "200", "null"})
133 public void simpleHead() throws Exception {
134 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
135
136 final String html = DOCTYPE_HTML
137 + "<html><head>\n"
138 + "<script>\n"
139 + LOG_TITLE_FUNCTION
140 + "var xhr = new XMLHttpRequest();\n"
141 + "function test() {\n"
142 + " try {\n"
143 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/simple2';\n"
144 + " xhr.open('HEAD', url, false);\n"
145 + " xhr.send();\n"
146 + " log(xhr.readyState);\n"
147 + " log(xhr.status);\n"
148 + " log(xhr.responseXML);\n"
149 + " } catch(e) { log(e) }\n"
150 + "}\n"
151 + "</script>\n"
152 + "</head>\n"
153 + "<body onload='test()'></body></html>";
154
155 SimpleServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "*";
156 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
157 servlets2.put("/simple2", SimpleServerServlet.class);
158 startWebServer2(".", null, servlets2);
159
160 loadPage2(html, new URL(URL_FIRST, "/simple1"));
161 verifyTitle2(getWebDriver(), getExpectedAlerts());
162 }
163
164
165
166
167 @Test
168 @Alerts({"4", "200", "<root><origin>§§URL§§</origin><cookie>null</cookie></root>"})
169 public void simplePost() throws Exception {
170 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
171
172 final String html = DOCTYPE_HTML
173 + "<html><head>\n"
174 + "<script>\n"
175 + LOG_TITLE_FUNCTION
176 + "var xhr = new XMLHttpRequest();\n"
177 + "function test() {\n"
178 + " try {\n"
179 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/simple2';\n"
180 + " xhr.open('POST', url, false);\n"
181 + " xhr.send('');\n"
182 + " log(xhr.readyState);\n"
183 + " log(xhr.status);\n"
184 + " log(xhr.responseText);\n"
185 + " } catch(e) { log(e) }\n"
186 + "}\n"
187 + "</script>\n"
188 + "</head>\n"
189 + "<body onload='test()'></body></html>";
190
191 SimpleServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "*";
192 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
193 servlets2.put("/simple2", SimpleServerServlet.class);
194 startWebServer2(".", null, servlets2);
195
196 loadPage2(html, new URL(URL_FIRST, "/simple1"));
197 verifyTitle2(getWebDriver(), getExpectedAlerts());
198 }
199
200
201
202
203 @Test
204 @Alerts("NetworkError/DOMException")
205 public void simplePut() throws Exception {
206 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
207
208 final String html = DOCTYPE_HTML
209 + "<html><head>\n"
210 + "<script>\n"
211 + LOG_TITLE_FUNCTION
212 + "var xhr = new XMLHttpRequest();\n"
213 + "function test() {\n"
214 + " try {\n"
215 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/simple2';\n"
216 + " xhr.open('PUT', url, false);\n"
217 + " xhr.send('');\n"
218 + " log(xhr.readyState);\n"
219 + " log(xhr.status);\n"
220 + " log(xhr.responseXML.firstChild.firstChild.nodeValue);\n"
221 + " } catch(e) { logEx(e) }\n"
222 + "}\n"
223 + "</script>\n"
224 + "</head>\n"
225 + "<body onload='test()'></body></html>";
226
227 SimpleServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "*";
228 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
229 servlets2.put("/simple2", SimpleServerServlet.class);
230 startWebServer2(".", null, servlets2);
231
232 loadPage2(html, new URL(URL_FIRST, "/simple1"));
233 verifyTitle2(getWebDriver(), getExpectedAlerts());
234 }
235
236
237
238
239 public static class SimpleServerServlet extends HttpServlet {
240 private static String ACCESS_CONTROL_ALLOW_ORIGIN_;
241
242
243
244
245 @Override
246 protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
247 if (ACCESS_CONTROL_ALLOW_ORIGIN_ != null) {
248 response.setHeader("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN_);
249 }
250 response.setCharacterEncoding(UTF_8.name());
251 response.setContentType(MimeType.TEXT_XML);
252
253 String origin = request.getHeader(HttpHeader.ORIGIN);
254 if (origin == null) {
255 origin = "No Origin!";
256 }
257 final String cookie = request.getHeader(HttpHeader.COOKIE);
258 response.getWriter().write("<root><origin>" + origin + "</origin><cookie>" + cookie + "</cookie></root>");
259 }
260
261
262
263
264 @Override
265 protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
266 doGet(request, response);
267 }
268
269
270
271
272 @Override
273 protected void doPut(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
274 doGet(request, response);
275 }
276 }
277
278
279
280
281 @Test
282 @Alerts({"NetworkError/DOMException", "4", "0", ""})
283 public void noAccessControlAllowOrigin() throws Exception {
284 incorrectAccessControlAllowOrigin(null);
285 }
286
287 private void incorrectAccessControlAllowOrigin(final String header) throws Exception {
288 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
289
290 final String html = DOCTYPE_HTML
291 + "<html><head>\n"
292 + "<script>\n"
293 + LOG_TITLE_FUNCTION
294 + "var xhr = new XMLHttpRequest();\n"
295 + "function test() {\n"
296 + " try {\n"
297 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/simple2';\n"
298 + " xhr.open('GET', url, false);\n"
299 + " xhr.send();\n"
300 + " } catch(e) { logEx(e) }\n"
301 + " log(xhr.readyState);\n"
302 + " log(xhr.status);\n"
303 + " log(xhr.responseText);\n"
304 + "}\n"
305 + "</script>\n"
306 + "</head>\n"
307 + "<body onload='test()'></body></html>";
308
309 SimpleServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = header;
310 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
311 servlets2.put("/simple2", SimpleServerServlet.class);
312 startWebServer2(".", null, servlets2);
313
314 loadPage2(html, new URL(URL_FIRST, "/simple1"));
315 verifyTitle2(getWebDriver(), getExpectedAlerts());
316 }
317
318
319
320
321 @Test
322 @Alerts({"NetworkError/DOMException", "4", "0", ""})
323 public void nonMatchingAccessControlAllowOrigin() throws Exception {
324 incorrectAccessControlAllowOrigin("http://www.sourceforge.net");
325 }
326
327
328
329
330 @Test
331 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
332 public void preflight() throws Exception {
333 doPreflightTestAllowedMethods("POST, GET, OPTIONS", MimeType.TEXT_PLAIN, null);
334
335 releaseResources();
336 shutDownAll();
337 }
338
339
340
341
342 @Test
343 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
344 public void preflight_cookie() throws Exception {
345 doPreflightTestAllowedMethods("POST, GET, OPTIONS", MimeType.TEXT_PLAIN, "cookie=sweet");
346
347 releaseResources();
348 shutDownAll();
349 }
350
351
352
353
354 @Test
355 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
356
357 public void preflight_contentTypeWithCharset() throws Exception {
358 doPreflightTestAllowedMethods("POST, GET, OPTIONS", MimeType.TEXT_PLAIN + ";charset=utf-8", null);
359
360 releaseResources();
361 shutDownAll();
362 }
363
364
365
366
367 @Test
368 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
369
370 public void preflightUrlEncoded() throws Exception {
371 doPreflightTestAllowedMethods("POST, GET, OPTIONS", "application/x-www-form-urlencoded", null);
372
373 releaseResources();
374 shutDownAll();
375 }
376
377
378
379
380 @Test
381 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
382
383 public void preflightUrlEncoded_contentTypeWithCharset() throws Exception {
384 doPreflightTestAllowedMethods("POST, GET, OPTIONS", "application/x-www-form-urlencoded;charset=utf-8", null);
385
386 releaseResources();
387 shutDownAll();
388 }
389
390
391
392
393 @Test
394 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
395
396 public void preflightMultipart() throws Exception {
397 doPreflightTestAllowedMethods("POST, GET, OPTIONS", "multipart/form-data", null);
398
399 releaseResources();
400 shutDownAll();
401 }
402
403
404
405
406 @Test
407 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
408
409 public void preflightMultipart_contentTypeWithCharset() throws Exception {
410 doPreflightTestAllowedMethods("POST, GET, OPTIONS", "multipart/form-data;charset=utf-8", null);
411
412 releaseResources();
413 shutDownAll();
414 }
415
416
417
418
419
420
421 @Test
422 @Alerts({"4", "200", "§§URL§§", "§§URL§§", "GET", "x-pingother", "null"})
423
424 public void preflight_incorrect_methods() throws Exception {
425 doPreflightTestAllowedMethods(null, MimeType.TEXT_PLAIN, null);
426
427 releaseResources();
428 shutDownAll();
429 }
430
431 private void doPreflightTestAllowedMethods(final String allowedMethods,
432 final String contentType, final String cookie)
433 throws Exception {
434 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT)); // url without trailing "/"
435
436 final String html = DOCTYPE_HTML
437 + "<html><head>\n"
438 + "<script>\n"
439 + LOG_TITLE_FUNCTION
440 + "var xhr = new XMLHttpRequest();\n"
441 + "function test() {\n"
442 + " try {\n"
443 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/preflight2';\n"
444 + " xhr.open('GET', url, false);\n"
445 + " xhr.setRequestHeader('X-PINGOTHER', 'pingpong');\n"
446 + " xhr.setRequestHeader('Content-Type' , '" + contentType + "');\n"
447 + " xhr.send();\n"
448 + " log(xhr.readyState);\n"
449 + " log(xhr.status);\n"
450 + " log(xhr.responseXML.firstChild.childNodes[0].firstChild.nodeValue);\n"
451 + " log(xhr.responseXML.firstChild.childNodes[1].firstChild.nodeValue);\n"
452 + " log(xhr.responseXML.firstChild.childNodes[2].firstChild.nodeValue);\n"
453 + " log(xhr.responseXML.firstChild.childNodes[3].firstChild.nodeValue);\n"
454 + " log(xhr.responseXML.firstChild.childNodes[4].firstChild.nodeValue);\n"
455 + " } catch(e) { log(e) }\n"
456 + "}\n"
457 + "</script>\n"
458 + "</head>\n"
459 + "<body onload='test()'></body></html>";
460
461 PreflightServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "http://localhost:" + PORT;
462 PreflightServerServlet.ACCESS_CONTROL_ALLOW_METHODS_ = allowedMethods;
463 PreflightServerServlet.ACCESS_CONTROL_ALLOW_HEADERS_ = "X-PINGOTHER";
464 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
465 servlets2.put("/preflight2", PreflightServerServlet.class);
466 startWebServer2(".", null, servlets2);
467
468 final URL url = new URL(URL_FIRST, "/preflight1");
469
470 List<NameValuePair> responseHeader = null;
471 if (cookie != null) {
472 responseHeader = new ArrayList<>();
473 responseHeader.add(new NameValuePair("Set-Cookie", cookie));
474 }
475
476 getMockWebConnection().setResponse(url, html,
477 200, "OK", "text/html;charset=ISO-8859-1", ISO_8859_1, responseHeader);
478 loadPage2(url, null);
479
480 verifyTitle2(getWebDriver(), getExpectedAlerts());
481 }
482
483
484
485
486 public static class PreflightServerServlet extends HttpServlet {
487 private static String ACCESS_CONTROL_ALLOW_ORIGIN_;
488 private static String ACCESS_CONTROL_ALLOW_METHODS_;
489 private static String ACCESS_CONTROL_ALLOW_HEADERS_;
490 private String options_origin_;
491 private String options_method_;
492 private String options_headers_;
493 private String options_cookie_;
494
495
496
497
498 @Override
499 protected void doOptions(final HttpServletRequest request, final HttpServletResponse response) {
500 if (ACCESS_CONTROL_ALLOW_ORIGIN_ != null) {
501 response.setHeader("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN_);
502 }
503 if (ACCESS_CONTROL_ALLOW_METHODS_ != null) {
504 response.setHeader("Access-Control-Allow-Methods", ACCESS_CONTROL_ALLOW_METHODS_);
505 }
506 if (ACCESS_CONTROL_ALLOW_HEADERS_ != null) {
507 response.setHeader("Access-Control-Allow-Headers", ACCESS_CONTROL_ALLOW_HEADERS_);
508 }
509 options_origin_ = request.getHeader(HttpHeader.ORIGIN);
510 options_method_ = request.getHeader("Access-Control-Request-Method");
511 options_headers_ = request.getHeader("Access-Control-Request-Headers");
512 options_cookie_ = request.getHeader(HttpHeader.COOKIE);
513 }
514
515
516
517
518 @Override
519 protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
520 if (ACCESS_CONTROL_ALLOW_ORIGIN_ != null) {
521 response.setHeader("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN_);
522 }
523 response.setCharacterEncoding(UTF_8.name());
524 response.setContentType(MimeType.TEXT_XML);
525 final Writer writer = response.getWriter();
526
527 final String origin = request.getHeader(HttpHeader.ORIGIN);
528 writer.write("<result>"
529 + "<origin>" + origin + "</origin>"
530 + "<options_origin>" + options_origin_ + "</options_origin>"
531 + "<options_method>" + options_method_ + "</options_method>"
532 + "<options_headers>" + options_headers_ + "</options_headers>"
533 + "<options_cookie>" + options_cookie_ + "</options_cookie>"
534 + "</result>");
535 }
536 }
537
538
539
540
541 @Test
542 @Alerts({"NetworkError/DOMException", "4", "0"})
543
544 public void preflight_incorrect_headers() throws Exception {
545 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
546
547 final String html = DOCTYPE_HTML
548 + "<html><head>\n"
549 + "<script>\n"
550 + LOG_TITLE_FUNCTION
551 + "var xhr = new XMLHttpRequest();\n"
552 + "function test() {\n"
553 + " try {\n"
554 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/preflight2';\n"
555 + " xhr.open('GET', url, false);\n"
556 + " xhr.setRequestHeader('X-PINGOTHER', 'pingpong');\n"
557 + " xhr.send();\n"
558 + " } catch(e) { logEx(e) }\n"
559 + " log(xhr.readyState);\n"
560 + " log(xhr.status);\n"
561 + "}\n"
562 + "</script>\n"
563 + "</head>\n"
564 + "<body onload='test()'></body></html>";
565
566 PreflightServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "http://localhost:" + PORT;
567 PreflightServerServlet.ACCESS_CONTROL_ALLOW_METHODS_ = "POST, GET, OPTIONS";
568 PreflightServerServlet.ACCESS_CONTROL_ALLOW_HEADERS_ = null;
569 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
570 servlets2.put("/preflight2", PreflightServerServlet.class);
571 startWebServer2(".", null, servlets2);
572
573 loadPage2(html, new URL(URL_FIRST, "/preflight1"));
574 verifyTitle2(getWebDriver(), getExpectedAlerts());
575 }
576
577
578
579
580 @Test
581 @Alerts({"4", "200", "options_headers", "x-ping,x-pong"})
582 public void preflight_many_header_values() throws Exception {
583 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
584
585 final String html = DOCTYPE_HTML
586 + "<html><head>\n"
587 + "<script>\n"
588 + LOG_TITLE_FUNCTION
589 + "var xhr = new XMLHttpRequest();\n"
590 + "function test() {\n"
591 + " try {\n"
592 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/preflight2';\n"
593 + " xhr.open('GET', url, false);\n"
594 + " xhr.setRequestHeader('X-PING', 'ping');\n"
595 + " xhr.setRequestHeader('X-PONG', 'pong');\n"
596 + " xhr.send();\n"
597 + " } catch(e) { logEx(e) }\n"
598 + " log(xhr.readyState);\n"
599 + " log(xhr.status);\n"
600 + " log(xhr.responseXML.firstChild.childNodes[3].tagName);\n"
601 + " log(xhr.responseXML.firstChild.childNodes[3].firstChild.nodeValue);\n"
602 + "}\n"
603 + "</script>\n"
604 + "</head>\n"
605 + "<body onload='test()'></body></html>";
606
607 PreflightServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = "http://localhost:" + PORT;
608 PreflightServerServlet.ACCESS_CONTROL_ALLOW_METHODS_ = "POST, GET, OPTIONS";
609 PreflightServerServlet.ACCESS_CONTROL_ALLOW_HEADERS_ = "X-PING, X-PONG";
610 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
611 servlets2.put("/preflight2", PreflightServerServlet.class);
612 startWebServer2(".", null, servlets2);
613
614 loadPage2(html, new URL(URL_FIRST, "/preflight1"));
615 verifyTitle2(getWebDriver(), getExpectedAlerts());
616 }
617
618
619
620
621 @Test
622 @Alerts("false")
623 public void withCredentials_defaultValue() throws Exception {
624 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
625
626 final String html = DOCTYPE_HTML
627 + "<html><head>\n"
628 + "<script>\n"
629 + LOG_TITLE_FUNCTION
630 + "var xhr = new XMLHttpRequest();\n"
631 + "function test() {\n"
632 + " try {\n"
633 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/withCredentials2';\n"
634 + " xhr.open('GET', url, true);\n"
635 + " log(xhr.withCredentials);\n"
636 + " } catch(e) { log(e) }\n"
637 + "}\n"
638 + "</script>\n"
639 + "</head>\n"
640 + "<body onload='test()'></body></html>";
641
642 loadPage2(html, new URL(URL_FIRST, "/withCredentials1"));
643 verifyTitle2(getWebDriver(), getExpectedAlerts());
644 }
645
646
647
648
649 @Test
650 @Alerts({"false", "true", "false", "true"})
651 public void withCredentials_setBeforeOpenSync() throws Exception {
652 final String html = DOCTYPE_HTML
653 + "<html><head>\n"
654 + "<script>\n"
655 + LOG_TITLE_FUNCTION
656 + "var xhr = new XMLHttpRequest();\n"
657 + "function test() {\n"
658 + " try {\n"
659 + " log(xhr.withCredentials);\n"
660
661 + " try {\n"
662 + " xhr.withCredentials = true;\n"
663 + " log(xhr.withCredentials);\n"
664 + " } catch(e) { log('ex: withCredentials=true') }\n"
665
666 + " try {\n"
667 + " xhr.withCredentials = false;\n"
668 + " log(xhr.withCredentials);\n"
669 + " } catch(e) { log('ex: withCredentials=false') }\n"
670
671 + " try {\n"
672 + " xhr.withCredentials = true;\n"
673 + " } catch(e) { log('ex: withCredentials=true') }\n"
674
675 + " try {\n"
676 + " xhr.open('GET', '/foo.xml', false);\n"
677 + " } catch(e) { log('ex: open') }\n"
678 + " log(xhr.withCredentials);\n"
679 + " } catch(ex) { log(ex) }\n"
680 + "}\n"
681 + "</script>\n"
682 + "</head>\n"
683 + "<body onload='test()'></body></html>";
684
685 loadPageVerifyTitle2(html);
686 }
687
688
689
690
691 @Test
692 @Alerts({"false", "true", "false", "true"})
693 public void withCredentials_setBeforeOpenAsync() throws Exception {
694 final String html = DOCTYPE_HTML
695 + "<html><head>\n"
696 + "<script>\n"
697 + LOG_TITLE_FUNCTION
698 + "var xhr = new XMLHttpRequest();\n"
699 + "function test() {\n"
700 + " try {\n"
701 + " log(xhr.withCredentials);\n"
702
703 + " try {\n"
704 + " xhr.withCredentials = true;\n"
705 + " log(xhr.withCredentials);\n"
706 + " } catch(e) { log('ex: withCredentials=true') }\n"
707
708 + " try {\n"
709 + " xhr.withCredentials = false;\n"
710 + " log(xhr.withCredentials);\n"
711 + " } catch(e) { log('ex: withCredentials=false') }\n"
712
713 + " try {\n"
714 + " xhr.withCredentials = true;\n"
715 + " } catch(e) { log('ex: withCredentials=true') }\n"
716
717 + " try {\n"
718 + " xhr.open('GET', '/foo.xml', true);\n"
719 + " } catch(e) { log('ex: open') }\n"
720 + " log(xhr.withCredentials);\n"
721 + " } catch(ex) { log(ex) }\n"
722 + "}\n"
723 + "</script>\n"
724 + "</head>\n"
725 + "<body onload='test()'></body></html>";
726
727 loadPage2(html);
728 verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
729 }
730
731
732
733
734 @Test
735 @Alerts({"false", "false", "true", "false"})
736 public void withCredentials_setAfterOpenSync() throws Exception {
737 final String html = DOCTYPE_HTML
738 + "<html><head>\n"
739 + "<script>\n"
740 + LOG_TITLE_FUNCTION
741 + "var xhr = new XMLHttpRequest();\n"
742 + "function test() {\n"
743 + " try {\n"
744 + " log(xhr.withCredentials);\n"
745 + " xhr.open('GET', '/foo.xml', false);\n"
746 + " log(xhr.withCredentials);\n"
747
748 + " try {\n"
749 + " xhr.withCredentials = true;\n"
750 + " log(xhr.withCredentials);\n"
751 + " } catch(e) { log('ex: withCredentials=true') }\n"
752
753 + " try {\n"
754 + " xhr.withCredentials = false;\n"
755 + " log(xhr.withCredentials);\n"
756 + " } catch(e) { log('ex: withCredentials=false') }\n"
757 + " } catch(ex) { log(ex) }\n"
758 + "}\n"
759 + "</script>\n"
760 + "</head>\n"
761 + "<body onload='test()'></body></html>";
762
763 loadPageVerifyTitle2(html);
764 }
765
766
767
768
769 @Test
770 @Alerts({"false", "false", "true", "false"})
771 public void withCredentials_setAfterOpenAsync() throws Exception {
772 final String html = DOCTYPE_HTML
773 + "<html><head>\n"
774 + "<script>\n"
775 + LOG_TITLE_FUNCTION
776 + "var xhr = new XMLHttpRequest();\n"
777 + "function test() {\n"
778 + " try {\n"
779 + " log(xhr.withCredentials);\n"
780 + " xhr.open('GET', '/foo.xml', false);\n"
781 + " log(xhr.withCredentials);\n"
782
783 + " try {\n"
784 + " xhr.withCredentials = true;\n"
785 + " log(xhr.withCredentials);\n"
786 + " } catch(e) { log('ex: withCredentials=true') }\n"
787
788 + " try {\n"
789 + " xhr.withCredentials = false;\n"
790 + " log(xhr.withCredentials);\n"
791 + " } catch(e) { log('ex: withCredentials=false') }\n"
792 + " } catch(ex) { log(ex) }\n"
793 + "}\n"
794 + "</script>\n"
795 + "</head>\n"
796 + "<body onload='test()'></body></html>";
797
798 loadPageVerifyTitle2(html);
799 }
800
801
802
803
804 @Test
805 @Alerts({"1", "0", "4", "0", ""})
806 public void withCredentials() throws Exception {
807 testWithCredentials("*", "true");
808 }
809
810
811
812
813 @Test
814 @Alerts({"1", "0", "4", "200", "<root><origin>§§URL§§</origin><cookie>cookie=sweet</cookie></root>"})
815 public void withCredentialsServer() throws Exception {
816 testWithCredentials("http://localhost:" + PORT, "true");
817 }
818
819
820
821
822 @Test
823 @Alerts({"1", "0", "4", "0", ""})
824 public void withCredentialsServerSlashAtEnd() throws Exception {
825 testWithCredentials(URL_FIRST.toExternalForm(), "true");
826 }
827
828
829
830
831 @Test
832 @Alerts({"1", "0", "4", "0", ""})
833 public void withCredentials_no_header() throws Exception {
834 testWithCredentials("*", null);
835 }
836
837
838
839
840 @Test
841 @Alerts({"1", "0", "4", "0", ""})
842 public void withCredentials_no_header_Server() throws Exception {
843 testWithCredentials("http://localhost:" + PORT, null);
844 }
845
846
847
848
849 @Test
850 @Alerts({"1", "0", "4", "0", ""})
851 public void withCredentials_no_header_ServerSlashAtEnd() throws Exception {
852 testWithCredentials(URL_FIRST.toExternalForm(), null);
853 }
854
855 private void testWithCredentials(final String accessControlAllowOrigin,
856 final String accessControlAllowCredentials) throws Exception {
857 expandExpectedAlertsVariables(new URL("http://localhost:" + PORT));
858
859 final String html = DOCTYPE_HTML
860 + "<html><head>\n"
861 + "<script>\n"
862 + LOG_TITLE_FUNCTION
863 + "var xhr = new XMLHttpRequest();\n"
864 + "function test() {\n"
865 + " try {\n"
866 + " var url = 'http://' + window.location.hostname + ':" + PORT2 + "/withCredentials2';\n"
867 + " xhr.open('GET', url, true);\n"
868 + " xhr.withCredentials = true;\n"
869 + " xhr.onreadystatechange = onReadyStateChange;\n"
870 + " xhr.send();\n"
871 + " } catch(e) { logEx(e) }\n"
872 + " log(xhr.readyState);\n"
873 + " try {\n"
874 + " log(xhr.status);\n"
875 + " } catch(e) { log('ex: status not available') }\n"
876
877 + " function onReadyStateChange() {\n"
878 + " if (xhr.readyState == 4) {\n"
879 + " log(xhr.readyState);\n"
880 + " log(xhr.status);\n"
881 + " log(xhr.responseText);\n"
882 + " }\n"
883 + " }\n"
884 + "}\n"
885 + "</script>\n"
886 + "</head>\n"
887 + "<body onload='test()'>\n"
888 + "</body></html>";
889
890 WithCredentialsServerServlet.ACCESS_CONTROL_ALLOW_ORIGIN_ = accessControlAllowOrigin;
891 WithCredentialsServerServlet.ACCESS_CONTROL_ALLOW_CREDENTIALS_ = accessControlAllowCredentials;
892 final Map<String, Class<? extends Servlet>> servlets2 = new HashMap<>();
893 servlets2.put("/withCredentials2", WithCredentialsServerServlet.class);
894 startWebServer2(".", null, servlets2);
895
896 final List<NameValuePair> responseHeader = new ArrayList<>();
897 responseHeader.add(new NameValuePair("Set-Cookie", "cookie=sweet"));
898
899 final URL url = new URL(URL_FIRST, "/withCredentials1");
900 getMockWebConnection().setResponse(url, html,
901 200, "OK", "text/html;charset=ISO-8859-1", ISO_8859_1, responseHeader);
902
903 final WebDriver driver = loadPage2(url, null);
904 verifyTitle2(DEFAULT_WAIT_TIME, driver, getExpectedAlerts());
905 }
906
907
908
909
910 @Test
911 @Alerts("done 200")
912 public void testWithCredentialsIFrame() throws Exception {
913 final String html = DOCTYPE_HTML
914 + "<html><head>\n"
915 + "<script>\n"
916 + LOG_WINDOW_NAME_FUNCTION
917
918 + "function load() {\n"
919 + " try {\n"
920 + " var myContent = '<!DOCTYPE html><html><head></head><body>"
921 + "<script src=\"get.js\"><\\/script><p>tttttt</p></body></html>';\n"
922 + " window.asyncLoadIFrame = document.createElement('iframe');\n"
923 + " asyncLoadIFrame.id = 'asyncLoadIFrame';\n"
924 + " asyncLoadIFrame.src = 'about:blank';\n"
925 + " document.body.appendChild(asyncLoadIFrame);\n"
926
927 + " asyncLoadIFrame.contentWindow.document.open('text/html', 'replace');\n"
928 + " asyncLoadIFrame.contentWindow.document.write(myContent);\n"
929 + " asyncLoadIFrame.contentWindow.document.close();\n"
930 + " } catch(e) { log(e) }\n"
931 + "}\n"
932 + "</script>\n"
933 + "</head>\n"
934 + "<body onload='load()'>\n"
935 + "</body></html>";
936
937 final String js =
938 LOG_WINDOW_NAME_FUNCTION
939 + "var xhr = new XMLHttpRequest();\n"
940 + " try {\n"
941 + " var url = '/data';\n"
942 + " xhr.open('GET', url, true);\n"
943 + " xhr.withCredentials = true;\n"
944 + " xhr.onreadystatechange = onReadyStateChange;\n"
945 + " xhr.send();\n"
946 + " } catch(e) { log(e) }\n"
947
948 + " function onReadyStateChange() {\n"
949 + " if (xhr.readyState == 4) {\n"
950 + " log('done ' + xhr.status);\n"
951 + " }\n"
952 + " }\n";
953
954 getMockWebConnection().setDefaultResponse(js, MimeType.TEXT_JAVASCRIPT);
955 final String xml = "<xml><content>blah</content></xml>";
956
957 getMockWebConnection().setResponse(new URL(URL_FIRST, "/data"), xml, MimeType.TEXT_XML);
958
959 loadPage2(html);
960 verifyWindowName2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
961 }
962
963
964
965
966 public static class WithCredentialsServerServlet extends HttpServlet {
967 private static String ACCESS_CONTROL_ALLOW_ORIGIN_;
968 private static String ACCESS_CONTROL_ALLOW_CREDENTIALS_;
969
970
971
972
973 @Override
974 protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
975 if (ACCESS_CONTROL_ALLOW_ORIGIN_ != null) {
976 response.setHeader("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN_);
977 }
978 if (ACCESS_CONTROL_ALLOW_CREDENTIALS_ != null) {
979 response.setHeader("Access-Control-Allow-Credentials", ACCESS_CONTROL_ALLOW_CREDENTIALS_);
980 }
981 response.setCharacterEncoding(UTF_8.name());
982 response.setContentType(MimeType.TEXT_XML);
983
984 String origin = request.getHeader(HttpHeader.ORIGIN);
985 if (origin == null) {
986 origin = "No Origin!";
987 }
988 final String cookie = request.getHeader(HttpHeader.COOKIE);
989 response.getWriter().write("<root><origin>" + origin + "</origin><cookie>" + cookie + "</cookie></root>");
990 }
991 }
992
993 }