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