test_CrossSiteXHR.html (56651B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"> 5 <title>Test for Cross Site XMLHttpRequest</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 8 </head> 9 <body onload="initTest()"> 10 <p id="display"> 11 <iframe id=loader></iframe> 12 </p> 13 <div id="content" style="display: none"> 14 15 </div> 16 <pre id="test"> 17 <script class="testbody" type="application/javascript"> 18 19 const runPreflightTests = 1; 20 const runCookieTests = 1; 21 const runRedirectTests = 1; 22 23 var gen; 24 25 function initTest() { 26 SimpleTest.waitForExplicitFinish(); 27 // Allow all cookies, then do the actual test initialization 28 SpecialPowers.pushPrefEnv({ 29 "set": [ 30 ["network.cookie.cookieBehavior", 0], 31 // Bug 1617611: Fix all the tests broken by "cookies SameSite=lax by default" 32 ["network.cookie.sameSite.laxByDefault", false], 33 ["network.cors_preflight.authorization_covered_by_wildcard", false], 34 ] 35 }, initTestCallback); 36 } 37 38 function initTestCallback() { 39 window.addEventListener("message", function(e) { 40 gen.next(e.data); 41 }); 42 43 gen = runTest(); 44 45 gen.next() 46 } 47 48 async function clearCORSPreflightCacheTest() { 49 // need to be on the parent process to access cors-preflight-cache service to: 50 // send the CORS preflight cache length to the content process (before clearing) 51 // clear the CORS preflight cache 52 // and send the cache length again (after clearing) 53 let script = SpecialPowers.loadChromeScript(function() { 54 addMessageListener("start", function(principal) { 55 try { 56 let preflightCache = Cc["@mozilla.org/network/cors-preflight-cache;1"] 57 .getService(Ci.nsICORSPreflightCache); 58 let entries = preflightCache.getEntries(principal); 59 sendAsyncMessage("before", entries.length); 60 61 for (let entry of entries) { 62 preflightCache.clearEntry(entry); 63 } 64 65 let afterEntries = preflightCache.getEntries(principal); 66 sendAsyncMessage("after", afterEntries.length); 67 } catch (e) { 68 console.error("Failed to get or clear the CORS preflight cache", e); 69 sendAsyncMessage("before", -1); 70 sendAsyncMessage("after", -1); 71 } 72 }); 73 }); 74 75 // document.location.origin varies depending on --enable-xorigin-tests: 76 // .com or .org 77 // we pass the "opposite" url to the parent process (as principal) 78 let url = (document.location.origin == "https://example.org") ? 79 "https://example.com" : "https://example.org"; 80 let oa = SpecialPowers.wrap(document).nodePrincipal.originAttributes; 81 let principal = SpecialPowers.Services.scriptSecurityManager 82 .createContentPrincipal(SpecialPowers.Services.io.newURI(url), oa); 83 script.sendAsyncMessage("start", principal); 84 85 // on the content process: 86 // assert on the expected CORS preflight cache sizes, before and after 87 await script.promiseOneMessage("before").then(val => { 88 // This check depends on the number of preflight cache items created 89 // by other tests in this file. 90 // For our purposes here, it is important only that the value is valid and 91 // indicating existing entries in the CORS preflight cache (positive values) 92 ok(val > 0, "CORS preflight cache size before clearing as expected"); 93 }); 94 await script.promiseOneMessage("after").then(val => { 95 is(val, 0, "CORS preflight cache empty after clearing"); 96 }); 97 98 SimpleTest.finish(); 99 } 100 101 // eslint-disable-next-line complexity 102 function* runTest() { 103 var loader = document.getElementById('loader'); 104 var loaderWindow = loader.contentWindow; 105 loader.onload = function () { gen.next() }; 106 107 // Test preflight-less requests 108 basePath = "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?" 109 base = self.location.origin; 110 baseHost = self.location.host; 111 baseURL = base + basePath; 112 113 // Test preflighted requests 114 origin = (base == "https://example.com") ? "https://example.org" : "https://example.com"; 115 originHost = (baseHost == "example.com") ? "example.org" : "example.com"; 116 loader.src = origin + "/tests/dom/security/test/cors/file_CrossSiteXHR_inner.html"; 117 yield undefined; 118 119 tests = [// Plain request 120 { pass: 1, 121 method: "GET", 122 noAllowPreflight: 1, 123 }, 124 125 // undefined username 126 { pass: 1, 127 method: "GET", 128 noAllowPreflight: 1, 129 username: undefined 130 }, 131 132 // undefined username and password 133 { pass: 1, 134 method: "GET", 135 noAllowPreflight: 1, 136 username: undefined, 137 password: undefined 138 }, 139 140 // nonempty username 141 { pass: 1, 142 method: "GET", 143 noAllowPreflight: 1, 144 username: "user", 145 }, 146 147 // nonempty password 148 { pass: 1, 149 method: "GET", 150 noAllowPreflight: 1, 151 password: "password", 152 }, 153 154 // Default allowed headers 155 { pass: 1, 156 method: "GET", 157 headers: { "Content-Type": "text/plain", 158 "Accept": "foo/bar", 159 "Accept-Language": "sv-SE" }, 160 noAllowPreflight: 1, 161 }, 162 { pass: 0, 163 method: "GET", 164 headers: { "Content-Type": "foo/bar", 165 "Accept": "foo/bar", 166 "Accept-Language": "sv-SE" }, 167 noAllowPreflight: 1, 168 }, 169 { pass: 0, 170 method: "GET", 171 headers: { "Content-Type": "foo/bar, text/plain" }, 172 noAllowPreflight: 1, 173 }, 174 { pass: 0, 175 method: "GET", 176 headers: { "Content-Type": "foo/bar, text/plain, garbage" }, 177 noAllowPreflight: 1, 178 }, 179 180 // Custom headers 181 { pass: 1, 182 method: "GET", 183 headers: { "x-my-header": "myValue" }, 184 allowHeaders: "x-my-header", 185 }, 186 { pass: 1, 187 method: "GET", 188 headers: { "x-my-header": "myValue" }, 189 allowHeaders: "X-My-Header", 190 }, 191 { pass: 1, 192 method: "GET", 193 headers: { "x-my-header": "myValue", 194 "long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" }, 195 allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header", 196 }, 197 { pass: 1, 198 method: "GET", 199 headers: { "x-my%-header": "myValue" }, 200 allowHeaders: "x-my%-header", 201 }, 202 { pass: 0, 203 method: "GET", 204 headers: { "x-my-header": "myValue" }, 205 }, 206 { pass: 0, 207 method: "GET", 208 headers: { "x-my-header": "" }, 209 }, 210 { pass: 0, 211 method: "GET", 212 headers: { "x-my-header": "myValue" }, 213 allowHeaders: "", 214 }, 215 { pass: 0, 216 method: "GET", 217 headers: { "x-my-header": "myValue" }, 218 allowHeaders: "y-my-header", 219 }, 220 { pass: 0, 221 method: "GET", 222 headers: { "x-my-header": "myValue" }, 223 allowHeaders: "x-my-header y-my-header", 224 }, 225 { pass: 0, 226 method: "GET", 227 headers: { "x-my-header": "myValue" }, 228 allowHeaders: "x-my-header, y-my-header z", 229 }, 230 { pass: 0, 231 method: "GET", 232 headers: { "x-my-header": "myValue" }, 233 allowHeaders: "x-my-header, y-my-he(ader", 234 }, 235 { pass: 0, 236 method: "GET", 237 headers: { "myheader": "" }, 238 allowMethods: "myheader", 239 }, 240 { pass: 1, 241 method: "GET", 242 headers: { "User-Agent": "myValue" }, 243 allowHeaders: "User-Agent", 244 }, 245 { pass: 0, 246 method: "GET", 247 headers: { "User-Agent": "myValue" }, 248 }, 249 250 // Multiple custom headers 251 { pass: 1, 252 method: "GET", 253 headers: { "x-my-header": "myValue", 254 "second-header": "secondValue", 255 "third-header": "thirdValue" }, 256 allowHeaders: "x-my-header, second-header, third-header", 257 }, 258 { pass: 1, 259 method: "GET", 260 headers: { "x-my-header": "myValue", 261 "second-header": "secondValue", 262 "third-header": "thirdValue" }, 263 allowHeaders: "x-my-header,second-header,third-header", 264 }, 265 { pass: 1, 266 method: "GET", 267 headers: { "x-my-header": "myValue", 268 "second-header": "secondValue", 269 "third-header": "thirdValue" }, 270 allowHeaders: "x-my-header ,second-header ,third-header", 271 }, 272 { pass: 1, 273 method: "GET", 274 headers: { "x-my-header": "myValue", 275 "second-header": "secondValue", 276 "third-header": "thirdValue" }, 277 allowHeaders: "x-my-header , second-header , third-header", 278 }, 279 { pass: 1, 280 method: "GET", 281 headers: { "x-my-header": "myValue", 282 "second-header": "secondValue" }, 283 allowHeaders: ", x-my-header, , ,, second-header, , ", 284 }, 285 { pass: 1, 286 method: "GET", 287 headers: { "x-my-header": "myValue", 288 "second-header": "secondValue" }, 289 allowHeaders: "x-my-header, second-header, unused-header", 290 }, 291 { pass: 0, 292 method: "GET", 293 headers: { "x-my-header": "myValue", 294 "y-my-header": "secondValue" }, 295 allowHeaders: "x-my-header", 296 }, 297 { pass: 0, 298 method: "GET", 299 headers: { "x-my-header": "", 300 "y-my-header": "" }, 301 allowHeaders: "x-my-header", 302 }, 303 304 // HEAD requests 305 { pass: 1, 306 method: "HEAD", 307 noAllowPreflight: 1, 308 }, 309 310 // HEAD with safe headers 311 { pass: 1, 312 method: "HEAD", 313 headers: { "Content-Type": "text/plain", 314 "Accept": "foo/bar", 315 "Accept-Language": "sv-SE" }, 316 noAllowPreflight: 1, 317 }, 318 { pass: 0, 319 method: "HEAD", 320 headers: { "Content-Type": "foo/bar", 321 "Accept": "foo/bar", 322 "Accept-Language": "sv-SE" }, 323 noAllowPreflight: 1, 324 }, 325 { pass: 0, 326 method: "HEAD", 327 headers: { "Content-Type": "foo/bar, text/plain" }, 328 noAllowPreflight: 1, 329 }, 330 { pass: 0, 331 method: "HEAD", 332 headers: { "Content-Type": "foo/bar, text/plain, garbage" }, 333 noAllowPreflight: 1, 334 }, 335 336 // HEAD with custom headers 337 { pass: 1, 338 method: "HEAD", 339 headers: { "x-my-header": "myValue" }, 340 allowHeaders: "x-my-header", 341 }, 342 { pass: 0, 343 method: "HEAD", 344 headers: { "x-my-header": "myValue" }, 345 }, 346 { pass: 0, 347 method: "HEAD", 348 headers: { "x-my-header": "myValue" }, 349 allowHeaders: "", 350 }, 351 { pass: 0, 352 method: "HEAD", 353 headers: { "x-my-header": "myValue" }, 354 allowHeaders: "y-my-header", 355 }, 356 { pass: 0, 357 method: "HEAD", 358 headers: { "x-my-header": "myValue" }, 359 allowHeaders: "x-my-header y-my-header", 360 }, 361 362 // POST tests 363 { pass: 1, 364 method: "POST", 365 body: "hi there", 366 noAllowPreflight: 1, 367 }, 368 { pass: 1, 369 method: "POST", 370 }, 371 { pass: 1, 372 method: "POST", 373 noAllowPreflight: 1, 374 }, 375 376 // POST with standard headers 377 { pass: 1, 378 method: "POST", 379 body: "hi there", 380 headers: { "Content-Type": "text/plain" }, 381 noAllowPreflight: 1, 382 }, 383 { pass: 1, 384 method: "POST", 385 body: "hi there", 386 headers: { "Content-Type": "multipart/form-data" }, 387 noAllowPreflight: 1, 388 }, 389 { pass: 1, 390 method: "POST", 391 body: "hi there", 392 headers: { "Content-Type": "application/x-www-form-urlencoded" }, 393 noAllowPreflight: 1, 394 }, 395 { pass: 0, 396 method: "POST", 397 body: "hi there", 398 headers: { "Content-Type": "foo/bar" }, 399 }, 400 { pass: 0, 401 method: "POST", 402 headers: { "Content-Type": "foo/bar" }, 403 }, 404 { pass: 1, 405 method: "POST", 406 body: "hi there", 407 headers: { "Content-Type": "text/plain", 408 "Accept": "foo/bar", 409 "Accept-Language": "sv-SE" }, 410 noAllowPreflight: 1, 411 }, 412 { pass: 0, 413 method: "POST", 414 body: "hi there", 415 headers: { "Content-Type": "foo/bar, text/plain" }, 416 noAllowPreflight: 1, 417 }, 418 { pass: 0, 419 method: "POST", 420 body: "hi there", 421 headers: { "Content-Type": "foo/bar, text/plain, garbage" }, 422 noAllowPreflight: 1, 423 }, 424 425 // POST with custom headers 426 { pass: 1, 427 method: "POST", 428 body: "hi there", 429 headers: { "Accept": "foo/bar", 430 "Accept-Language": "sv-SE", 431 "x-my-header": "myValue" }, 432 allowHeaders: "x-my-header", 433 }, 434 { pass: 1, 435 method: "POST", 436 headers: { "Content-Type": "text/plain", 437 "x-my-header": "myValue" }, 438 allowHeaders: "x-my-header", 439 }, 440 { pass: 1, 441 method: "POST", 442 body: "hi there", 443 headers: { "Content-Type": "text/plain", 444 "x-my-header": "myValue" }, 445 allowHeaders: "x-my-header", 446 }, 447 { pass: 1, 448 method: "POST", 449 body: "hi there", 450 headers: { "Content-Type": "foo/bar", 451 "x-my-header": "myValue" }, 452 allowHeaders: "x-my-header, content-type", 453 }, 454 { pass: 0, 455 method: "POST", 456 body: "hi there", 457 headers: { "Content-Type": "foo/bar" }, 458 noAllowPreflight: 1, 459 }, 460 { pass: 0, 461 method: "POST", 462 body: "hi there", 463 headers: { "Content-Type": "foo/bar", 464 "x-my-header": "myValue" }, 465 allowHeaders: "x-my-header", 466 }, 467 { pass: 1, 468 method: "POST", 469 headers: { "x-my-header": "myValue" }, 470 allowHeaders: "x-my-header", 471 }, 472 { pass: 1, 473 method: "POST", 474 body: "hi there", 475 headers: { "x-my-header": "myValue" }, 476 allowHeaders: "x-my-header, $_%", 477 }, 478 479 // Test cases for "Access-Control-Allow-Headers" containing "*". 480 { pass: 1, 481 method: "POST", 482 body: "hi there", 483 headers: { "x-my-header": "myValue" }, 484 allowHeaders: "*", 485 }, 486 { pass: 1, 487 method: "POST", 488 body: "hi there", 489 headers: { "x-my-header": "myValue", 490 "Authorization": "12345" }, 491 allowHeaders: "*, Authorization", 492 }, 493 { pass: 1, 494 method: "POST", 495 body: "hi there", 496 headers: { "x-my-header": "myValue", 497 "Authorization": "12345" }, 498 allowHeaders: "Authorization, *", 499 }, 500 { pass: 0, 501 method: "POST", 502 body: "hi there", 503 headers: { "x-my-header": "myValue", 504 "Authorization": "12345" }, 505 allowHeaders: "*", 506 }, 507 { pass: 0, 508 method: "POST", 509 body: "hi there", 510 headers: { "x-my-header": "myValue", 511 "Authorization": "12345" }, 512 allowHeaders: "x-my-header", 513 }, 514 { pass: 1, 515 method: "POST", 516 body: "hi there", 517 headers: { "*": "myValue" }, 518 allowHeaders: "*", 519 withCred: 1, 520 allowCred: 1, 521 }, 522 { pass: 0, 523 method: "POST", 524 body: "hi there", 525 headers: { "x-my-header": "myValue" }, 526 allowHeaders: "*", 527 withCred: 1, 528 allowCred: 1, 529 }, 530 531 // Other methods 532 { pass: 1, 533 method: "DELETE", 534 allowMethods: "DELETE", 535 }, 536 { pass: 0, 537 method: "DELETE", 538 allowHeaders: "DELETE", 539 }, 540 { pass: 0, 541 method: "DELETE", 542 }, 543 { pass: 0, 544 method: "DELETE", 545 allowMethods: "", 546 }, 547 { pass: 1, 548 method: "DELETE", 549 allowMethods: "POST, PUT, DELETE", 550 }, 551 { pass: 1, 552 method: "DELETE", 553 allowMethods: "POST, DELETE, PUT", 554 }, 555 { pass: 1, 556 method: "DELETE", 557 allowMethods: "DELETE, POST, PUT", 558 }, 559 { pass: 1, 560 method: "DELETE", 561 allowMethods: "POST ,PUT ,DELETE", 562 }, 563 { pass: 1, 564 method: "DELETE", 565 allowMethods: "POST,PUT,DELETE", 566 }, 567 { pass: 1, 568 method: "DELETE", 569 allowMethods: "POST , PUT , DELETE", 570 }, 571 { pass: 1, 572 method: "DELETE", 573 allowMethods: " ,, PUT ,, , , DELETE , ,", 574 }, 575 { pass: 0, 576 method: "DELETE", 577 allowMethods: "PUT", 578 }, 579 { pass: 0, 580 method: "DELETE", 581 allowMethods: "DELETEZ", 582 }, 583 { pass: 0, 584 method: "DELETE", 585 allowMethods: "DELETE PUT", 586 }, 587 { pass: 0, 588 method: "DELETE", 589 allowMethods: "DELETE, PUT Z", 590 }, 591 { pass: 0, 592 method: "DELETE", 593 allowMethods: "DELETE, PU(T", 594 }, 595 { pass: 0, 596 method: "DELETE", 597 allowMethods: "PUT DELETE", 598 }, 599 { pass: 0, 600 method: "DELETE", 601 allowMethods: "PUT Z, DELETE", 602 }, 603 { pass: 0, 604 method: "DELETE", 605 allowMethods: "PU(T, DELETE", 606 }, 607 { pass: 0, 608 method: "MYMETHOD", 609 allowMethods: "myMethod", 610 }, 611 { pass: 0, 612 method: "PUT", 613 allowMethods: "put", 614 }, 615 616 // Progress events 617 { pass: 1, 618 method: "POST", 619 body: "hi there", 620 headers: { "Content-Type": "text/plain" }, 621 uploadProgress: "progress", 622 }, 623 { pass: 0, 624 method: "POST", 625 body: "hi there", 626 headers: { "Content-Type": "text/plain" }, 627 uploadProgress: "progress", 628 noAllowPreflight: 1, 629 }, 630 631 // Status messages 632 { pass: 1, 633 method: "GET", 634 noAllowPreflight: 1, 635 status: 404, 636 statusMessage: "nothin' here", 637 }, 638 { pass: 1, 639 method: "GET", 640 noAllowPreflight: 1, 641 status: 401, 642 statusMessage: "no can do", 643 }, 644 { pass: 1, 645 method: "POST", 646 body: "hi there", 647 headers: { "Content-Type": "foo/bar" }, 648 allowHeaders: "content-type", 649 status: 500, 650 statusMessage: "server boo", 651 }, 652 { pass: 1, 653 method: "GET", 654 noAllowPreflight: 1, 655 status: 200, 656 statusMessage: "Yes!!", 657 }, 658 { pass: 0, 659 method: "GET", 660 headers: { "x-my-header": "header value" }, 661 allowHeaders: "x-my-header", 662 preflightStatus: 400 663 }, 664 { pass: 1, 665 method: "GET", 666 headers: { "x-my-header": "header value" }, 667 allowHeaders: "x-my-header", 668 preflightStatus: 200 669 }, 670 { pass: 1, 671 method: "GET", 672 headers: { "x-my-header": "header value" }, 673 allowHeaders: "x-my-header", 674 preflightStatus: 204 675 }, 676 677 // exposed headers 678 { pass: 1, 679 method: "GET", 680 responseHeaders: { "x-my-header": "x header" }, 681 exposeHeaders: "x-my-header", 682 expectedResponseHeaders: ["x-my-header"], 683 }, 684 { pass: 0, 685 method: "GET", 686 origin: "https://invalid", 687 responseHeaders: { "x-my-header": "x header" }, 688 exposeHeaders: "x-my-header", 689 expectedResponseHeaders: [], 690 }, 691 { pass: 1, 692 method: "GET", 693 responseHeaders: { "x-my-header": "x header" }, 694 expectedResponseHeaders: [], 695 }, 696 { pass: 1, 697 method: "GET", 698 responseHeaders: { "x-my-header": "x header" }, 699 exposeHeaders: "x-my-header y", 700 expectedResponseHeaders: [], 701 }, 702 { pass: 1, 703 method: "GET", 704 responseHeaders: { "x-my-header": "x header" }, 705 exposeHeaders: "y x-my-header", 706 expectedResponseHeaders: [], 707 }, 708 { pass: 1, 709 method: "GET", 710 responseHeaders: { "x-my-header": "x header" }, 711 exposeHeaders: "x-my-header, y-my-header z", 712 expectedResponseHeaders: [], 713 }, 714 { pass: 1, 715 method: "GET", 716 responseHeaders: { "x-my-header": "x header" }, 717 exposeHeaders: "x-my-header, y-my-hea(er", 718 expectedResponseHeaders: [], 719 }, 720 { pass: 1, 721 method: "GET", 722 responseHeaders: { "x-my-header": "x header", 723 "y-my-header": "y header" }, 724 exposeHeaders: " , ,,y-my-header,z-my-header, ", 725 expectedResponseHeaders: ["y-my-header"], 726 }, 727 { pass: 1, 728 method: "GET", 729 responseHeaders: { "Cache-Control": "cacheControl header", 730 "Content-Language": "contentLanguage header", 731 "Expires":"expires header", 732 "Last-Modified":"lastModified header", 733 "Pragma":"pragma header", 734 "Unexpected":"unexpected header" }, 735 expectedResponseHeaders: ["Cache-Control","Content-Language","Content-Type","Expires","Last-Modified","Pragma"], 736 }, 737 // Check that sending a body in the OPTIONS response works 738 { pass: 1, 739 method: "DELETE", 740 allowMethods: "DELETE", 741 preflightBody: "I'm a preflight response body", 742 }, 743 ]; 744 745 if (!runPreflightTests) { 746 tests = []; 747 } 748 749 for (test of tests) { 750 var req = { 751 url: baseURL + "allowOrigin=" + escape(test.origin || origin), 752 method: test.method, 753 headers: test.headers, 754 uploadProgress: test.uploadProgress, 755 body: test.body, 756 responseHeaders: test.responseHeaders, 757 withCred: test.withCred ? test.withCred : 0, 758 }; 759 760 if (test.pass) { 761 req.url += "&origin=" + escape(origin) + 762 "&requestMethod=" + test.method; 763 } 764 765 if ("username" in test) { 766 req.username = test.username; 767 } 768 769 if ("password" in test) { 770 req.password = test.password; 771 } 772 773 if (test.noAllowPreflight) 774 req.url += "&noAllowPreflight"; 775 776 if (test.allowCred) 777 req.url += "&allowCred"; 778 779 if (test.pass && "headers" in test) { 780 function isUnsafeHeader(name) { 781 lName = name.toLowerCase(); 782 return lName != "accept" && 783 lName != "accept-language" && 784 (lName != "content-type" || 785 !["text/plain", 786 "multipart/form-data", 787 "application/x-www-form-urlencoded"] 788 .includes(test.headers[name].toLowerCase())); 789 } 790 req.url += "&headers=" + escape(JSON.stringify(test.headers)); 791 reqHeaders = 792 escape(Object.keys(test.headers) 793 .filter(isUnsafeHeader) 794 .map(s => s.toLowerCase()) 795 .sort() 796 .join(",")); 797 req.url += reqHeaders ? "&requestHeaders=" + reqHeaders : ""; 798 } 799 if ("allowHeaders" in test) 800 req.url += "&allowHeaders=" + escape(test.allowHeaders); 801 if ("allowMethods" in test) 802 req.url += "&allowMethods=" + escape(test.allowMethods); 803 if (test.body) 804 req.url += "&body=" + escape(test.body); 805 if (test.status) { 806 req.url += "&status=" + test.status; 807 req.url += "&statusMessage=" + escape(test.statusMessage); 808 } 809 if (test.preflightStatus) 810 req.url += "&preflightStatus=" + test.preflightStatus; 811 if (test.responseHeaders) 812 req.url += "&responseHeaders=" + escape(JSON.stringify(test.responseHeaders)); 813 if (test.exposeHeaders) 814 req.url += "&exposeHeaders=" + escape(test.exposeHeaders); 815 if (test.preflightBody) 816 req.url += "&preflightBody=" + escape(test.preflightBody); 817 818 loaderWindow.postMessage(JSON.stringify(req), origin); 819 res = JSON.parse(yield); 820 821 if (test.pass) { 822 is(res.didFail, false, 823 "shouldn't have failed in test for " + JSON.stringify(test)); 824 if (test.status) { 825 is(res.status, test.status, "wrong status in test for " + JSON.stringify(test)); 826 is(res.statusText, test.statusMessage, "wrong status text for " + JSON.stringify(test)); 827 } 828 else { 829 is(res.status, 200, "wrong status in test for " + JSON.stringify(test)); 830 is(res.statusText, "OK", "wrong status text for " + JSON.stringify(test)); 831 } 832 if (test.method !== "HEAD") { 833 is(res.responseXML, "<res>hello pass</res>", 834 "wrong responseXML in test for " + JSON.stringify(test)); 835 is(res.responseText, "<res>hello pass</res>\n", 836 "wrong responseText in test for " + JSON.stringify(test)); 837 is(res.events.join(","), 838 "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend", 839 "wrong responseText in test for " + JSON.stringify(test)); 840 } 841 else { 842 is(res.responseXML, null, 843 "wrong responseXML in test for " + JSON.stringify(test)); 844 is(res.responseText, "", 845 "wrong responseText in test for " + JSON.stringify(test)); 846 is(res.events.join(","), 847 "opening,rs1,sending,loadstart,rs2,rs4,load,loadend", 848 "wrong responseText in test for " + JSON.stringify(test)); 849 } 850 if (test.responseHeaders) { 851 for (header in test.responseHeaders) { 852 if (!test.expectedResponseHeaders.includes(header)) { 853 is(res.responseHeaders[header], null, 854 "|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " + 855 JSON.stringify(test)); 856 is(res.allResponseHeaders[header], undefined, 857 "|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " + 858 JSON.stringify(test)); 859 } 860 else { 861 is(res.responseHeaders[header], test.responseHeaders[header], 862 "|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " + 863 JSON.stringify(test)); 864 is(res.allResponseHeaders[header.toLowerCase()], test.responseHeaders[header], 865 "|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " + 866 JSON.stringify(test)); 867 } 868 } 869 } 870 } 871 else { 872 is(res.didFail, true, 873 "should have failed in test for " + JSON.stringify(test)); 874 is(res.status, 0, "wrong status in test for " + JSON.stringify(test)); 875 is(res.statusText, "", "wrong status text for " + JSON.stringify(test)); 876 is(res.responseXML, null, 877 "wrong responseXML in test for " + JSON.stringify(test)); 878 is(res.responseText, "", 879 "wrong responseText in test for " + JSON.stringify(test)); 880 if (!res.sendThrew) { 881 is(res.events.join(","), 882 "opening,rs1,sending,loadstart,rs4,error,loadend", 883 "wrong events in test for " + JSON.stringify(test)); 884 } 885 is(res.progressEvents, 0, 886 "wrong events in test for " + JSON.stringify(test)); 887 if (test.responseHeaders) { 888 for (header in test.responseHeaders) { 889 is(res.responseHeaders[header], null, 890 "wrong response header (" + header + ") in test for " + 891 JSON.stringify(test)); 892 } 893 } 894 } 895 } 896 897 // Test cookie behavior 898 tests = [{ pass: 1, 899 method: "GET", 900 withCred: 1, 901 allowCred: 1, 902 }, 903 { pass: 0, 904 method: "GET", 905 withCred: 1, 906 allowCred: 0, 907 }, 908 { pass: 0, 909 method: "GET", 910 withCred: 1, 911 allowCred: 1, 912 origin: "*", 913 }, 914 { pass: 1, 915 method: "GET", 916 withCred: 0, 917 allowCred: 1, 918 origin: "*", 919 }, 920 { pass: 1, 921 method: "GET", 922 setCookie: "a=1; Partitioned; Secure; SameSite=None", 923 withCred: 1, 924 allowCred: 1, 925 }, 926 { pass: 1, 927 method: "GET", 928 cookie: "a=1", 929 withCred: 1, 930 allowCred: 1, 931 }, 932 { pass: 1, 933 method: "GET", 934 noCookie: 1, 935 withCred: 0, 936 allowCred: 1, 937 }, 938 { pass: 0, 939 method: "GET", 940 noCookie: 1, 941 withCred: 1, 942 allowCred: 1, 943 }, 944 { pass: 1, 945 method: "GET", 946 setCookie: "a=2; Partitioned; Secure; SameSite=None", 947 withCred: 0, 948 allowCred: 1, 949 }, 950 { pass: 1, 951 method: "GET", 952 cookie: "a=1", 953 withCred: 1, 954 allowCred: 1, 955 }, 956 { pass: 1, 957 method: "GET", 958 setCookie: "a=2; Partitioned; Secure; SameSite=None", 959 withCred: 1, 960 allowCred: 1, 961 }, 962 { pass: 1, 963 method: "GET", 964 cookie: "a=2", 965 withCred: 1, 966 allowCred: 1, 967 }, 968 ]; 969 970 if (!runCookieTests) { 971 tests = []; 972 } 973 974 for (test of tests) { 975 req = { 976 url: baseURL + "allowOrigin=" + escape(test.origin || origin), 977 method: test.method, 978 headers: test.headers, 979 withCred: test.withCred, 980 }; 981 982 if (test.allowCred) 983 req.url += "&allowCred"; 984 985 if (test.setCookie) 986 req.url += "&setCookie=" + escape(test.setCookie); 987 if (test.cookie) 988 req.url += "&cookie=" + escape(test.cookie); 989 if (test.noCookie) 990 req.url += "&noCookie"; 991 992 if ("allowHeaders" in test) 993 req.url += "&allowHeaders=" + escape(test.allowHeaders); 994 if ("allowMethods" in test) 995 req.url += "&allowMethods=" + escape(test.allowMethods); 996 997 loaderWindow.postMessage(JSON.stringify(req), origin); 998 999 res = JSON.parse(yield); 1000 if (test.pass) { 1001 is(res.didFail, false, 1002 "shouldn't have failed in test for " + JSON.stringify(test)); 1003 is(res.status, 200, "wrong status in test for " + JSON.stringify(test)); 1004 is(res.statusText, "OK", "wrong status text for " + JSON.stringify(test)); 1005 is(res.responseXML, "<res>hello pass</res>", 1006 "wrong responseXML in test for " + JSON.stringify(test)); 1007 is(res.responseText, "<res>hello pass</res>\n", 1008 "wrong responseText in test for " + JSON.stringify(test)); 1009 is(res.events.join(","), 1010 "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend", 1011 "wrong responseText in test for " + JSON.stringify(test)); 1012 } 1013 else { 1014 is(res.didFail, true, 1015 "should have failed in test for " + JSON.stringify(test)); 1016 is(res.status, 0, "wrong status in test for " + JSON.stringify(test)); 1017 is(res.statusText, "", "wrong status text for " + JSON.stringify(test)); 1018 is(res.responseXML, null, 1019 "wrong responseXML in test for " + JSON.stringify(test)); 1020 is(res.responseText, "", 1021 "wrong responseText in test for " + JSON.stringify(test)); 1022 is(res.events.join(","), 1023 "opening,rs1,sending,loadstart,rs4,error,loadend", 1024 "wrong events in test for " + JSON.stringify(test)); 1025 is(res.progressEvents, 0, 1026 "wrong events in test for " + JSON.stringify(test)); 1027 } 1028 } 1029 1030 // Make sure to clear cookies to avoid affecting other tests 1031 document.cookie = "a=; partitioned; secure; samesite=none; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT" 1032 is(document.cookie, "", "No cookies should be left over"); 1033 1034 var otherURL = "https://example.net"; 1035 1036 // Test redirects 1037 tests = [{ pass: 1, 1038 method: "GET", 1039 hops: [{ server: otherURL, 1040 allowOrigin: origin 1041 }, 1042 ], 1043 }, 1044 { pass: 0, 1045 method: "GET", 1046 hops: [{ server: otherURL, 1047 allowOrigin: origin 1048 }, 1049 { server: origin, 1050 allowOrigin: origin 1051 }, 1052 ], 1053 }, 1054 { pass: 1, 1055 method: "GET", 1056 hops: [{ server: otherURL, 1057 allowOrigin: origin 1058 }, 1059 { server: origin, 1060 allowOrigin: "*" 1061 }, 1062 ], 1063 }, 1064 { pass: 0, 1065 method: "GET", 1066 hops: [{ server: otherURL, 1067 allowOrigin: origin 1068 }, 1069 { server: origin, 1070 }, 1071 ], 1072 }, 1073 { pass: 1, 1074 method: "GET", 1075 hops: [{ server: origin, 1076 }, 1077 { server: origin, 1078 }, 1079 { server: otherURL, 1080 allowOrigin: origin 1081 }, 1082 ], 1083 }, 1084 { pass: 0, 1085 method: "GET", 1086 hops: [{ server: origin, 1087 }, 1088 { server: origin, 1089 }, 1090 { server: otherURL, 1091 allowOrigin: origin 1092 }, 1093 { server: origin, 1094 }, 1095 ], 1096 }, 1097 { pass: 0, 1098 method: "GET", 1099 hops: [{ server: otherURL, 1100 allowOrigin: origin 1101 }, 1102 { server: "https://test3." + originHost + ":443", 1103 allowOrigin: origin 1104 }, 1105 { server: "https://sub2.test2." + originHost, 1106 allowOrigin: origin 1107 }, 1108 { server: "https://sub1.test1." + originHost, 1109 allowOrigin: origin 1110 }, 1111 ], 1112 }, 1113 { pass: 0, 1114 method: "GET", 1115 hops: [{ server: otherURL, 1116 allowOrigin: origin 1117 }, 1118 { server: "https://test3." + originHost + ":443", 1119 allowOrigin: origin 1120 }, 1121 { server: "https://sub2.test2." + originHost, 1122 allowOrigin: "*" 1123 }, 1124 { server: "https://sub1.test1." + originHost, 1125 allowOrigin: "*" 1126 }, 1127 ], 1128 }, 1129 { pass: 1, 1130 method: "GET", 1131 hops: [{ server: otherURL, 1132 allowOrigin: origin 1133 }, 1134 { server: "https://test3." + originHost + ":443", 1135 allowOrigin: "*" 1136 }, 1137 { server: "https://sub2.test2." + originHost, 1138 allowOrigin: "*" 1139 }, 1140 { server: "https://sub1.test1." + originHost, 1141 allowOrigin: "*" 1142 }, 1143 ], 1144 }, 1145 { pass: 0, 1146 method: "GET", 1147 hops: [{ server: otherURL, 1148 allowOrigin: origin 1149 }, 1150 { server: "https://test3." + originHost + ":443", 1151 allowOrigin: origin 1152 }, 1153 { server: "https://sub2.test2." + originHost, 1154 allowOrigin: "x" 1155 }, 1156 { server: "https://sub1.test1." + originHost, 1157 allowOrigin: origin 1158 }, 1159 ], 1160 }, 1161 { pass: 0, 1162 method: "GET", 1163 hops: [{ server: otherURL, 1164 allowOrigin: origin 1165 }, 1166 { server: "https://test3." + originHost + ":443", 1167 allowOrigin: origin 1168 }, 1169 { server: "https://sub2.test2." + originHost, 1170 allowOrigin: "*" 1171 }, 1172 { server: "https://sub1.test1." + originHost, 1173 allowOrigin: origin 1174 }, 1175 ], 1176 }, 1177 { pass: 0, 1178 method: "GET", 1179 hops: [{ server: otherURL, 1180 allowOrigin: origin 1181 }, 1182 { server: "https://test3." + originHost + ":443", 1183 allowOrigin: origin 1184 }, 1185 { server: "https://sub2.test2." + originHost, 1186 allowOrigin: "*" 1187 }, 1188 { server: "https://sub1.test1." + originHost }, 1189 ], 1190 }, 1191 { pass: 1, 1192 method: "POST", 1193 body: "hi there", 1194 headers: { "Content-Type": "text/plain" }, 1195 hops: [{ server: origin, 1196 }, 1197 { server: otherURL, 1198 allowOrigin: origin, 1199 }, 1200 ], 1201 }, 1202 { pass: 1, 1203 method: "POST", 1204 body: "hi there", 1205 headers: { "Content-Type": "text/plain", 1206 "my-header": "myValue", 1207 }, 1208 hops: [{ server: origin, 1209 }, 1210 { server: otherURL, 1211 allowOrigin: origin, 1212 allowHeaders: "my-header", 1213 }, 1214 ], 1215 }, 1216 { pass: 0, 1217 method: "POST", 1218 body: "hi there", 1219 headers: { "Content-Type": "text/plain", 1220 "my-header": "myValue", 1221 }, 1222 hops: [{ server: origin, 1223 }, 1224 { server: otherURL, 1225 allowOrigin: origin, 1226 allowHeaders: "my-header", 1227 }, 1228 { server: "https://sub1.test1." + originHost, 1229 allowOrigin: origin, 1230 allowHeaders: "my-header", 1231 }, 1232 ], 1233 }, 1234 { pass: 1, 1235 method: "POST", 1236 body: "hi there", 1237 headers: { "Content-Type": "text/plain", 1238 "my-header": "myValue", 1239 }, 1240 hops: [{ server: origin, 1241 }, 1242 { server: otherURL, 1243 allowOrigin: origin, 1244 allowHeaders: "my-header", 1245 }, 1246 { server: "https://sub1.test1." + originHost, 1247 allowOrigin: "*", 1248 allowHeaders: "my-header", 1249 }, 1250 ], 1251 }, 1252 { pass: 1, 1253 method: "POST", 1254 body: "hi there", 1255 headers: { "Content-Type": "text/plain", 1256 "my-header": "myValue", 1257 }, 1258 hops: [{ server: origin, 1259 }, 1260 { server: otherURL, 1261 allowOrigin: origin, 1262 allowHeaders: "my-header", 1263 }, 1264 { server: otherURL, 1265 allowOrigin: origin, 1266 allowHeaders: "my-header", 1267 }, 1268 ], 1269 }, 1270 { pass: 0, 1271 method: "POST", 1272 body: "hi there", 1273 headers: { "Content-Type": "text/plain", 1274 "my-header": "myValue", 1275 }, 1276 hops: [{ server: origin, 1277 }, 1278 { server: otherURL, 1279 allowOrigin: origin, 1280 allowHeaders: "my-header", 1281 }, 1282 { server: origin, 1283 allowOrigin: origin, 1284 allowHeaders: "my-header", 1285 }, 1286 ], 1287 }, 1288 { pass: 0, 1289 method: "POST", 1290 body: "hi there", 1291 headers: { "Content-Type": "text/plain", 1292 "my-header": "myValue", 1293 }, 1294 hops: [{ server: origin, 1295 }, 1296 { server: otherURL, 1297 allowOrigin: origin, 1298 noAllowPreflight: 1, 1299 }, 1300 ], 1301 }, 1302 { pass: 1, 1303 method: "DELETE", 1304 hops: [{ server: origin, 1305 }, 1306 { server: otherURL, 1307 allowOrigin: origin, 1308 allowMethods: "DELETE", 1309 }, 1310 ], 1311 }, 1312 { pass: 0, 1313 method: "DELETE", 1314 hops: [{ server: origin, 1315 }, 1316 { server: otherURL, 1317 allowOrigin: origin, 1318 allowMethods: "DELETE", 1319 }, 1320 { server: "https://sub1.test1." + originHost, 1321 allowOrigin: origin, 1322 allowMethods: "DELETE", 1323 }, 1324 ], 1325 }, 1326 { pass: 1, 1327 method: "DELETE", 1328 hops: [{ server: origin, 1329 }, 1330 { server: otherURL, 1331 allowOrigin: origin, 1332 allowMethods: "DELETE", 1333 }, 1334 { server: "https://sub1.test1." + originHost, 1335 allowOrigin: "*", 1336 allowMethods: "DELETE", 1337 }, 1338 ], 1339 }, 1340 { pass: 1, 1341 method: "DELETE", 1342 hops: [{ server: origin, 1343 }, 1344 { server: otherURL, 1345 allowOrigin: origin, 1346 allowMethods: "DELETE", 1347 }, 1348 { server: otherURL, 1349 allowOrigin: origin, 1350 allowMethods: "DELETE", 1351 }, 1352 ], 1353 }, 1354 { pass: 0, 1355 method: "DELETE", 1356 hops: [{ server: origin, 1357 }, 1358 { server: otherURL, 1359 allowOrigin: origin, 1360 allowMethods: "DELETE", 1361 }, 1362 { server: origin, 1363 allowOrigin: origin, 1364 allowMethods: "DELETE", 1365 }, 1366 ], 1367 }, 1368 { pass: 0, 1369 method: "DELETE", 1370 hops: [{ server: origin, 1371 }, 1372 { server: otherURL, 1373 allowOrigin: origin, 1374 allowMethods: "DELETE", 1375 noAllowPreflight: 1, 1376 }, 1377 ], 1378 }, 1379 { pass: 0, 1380 method: "POST", 1381 body: "hi there", 1382 headers: { "Content-Type": "text/plain", 1383 "my-header": "myValue", 1384 }, 1385 hops: [{ server: otherURL, 1386 allowOrigin: origin, 1387 }, 1388 { server: "https://sub1.test1." + originHost, 1389 allowOrigin: origin, 1390 }, 1391 ], 1392 }, 1393 { pass: 0, 1394 method: "DELETE", 1395 hops: [{ server: otherURL, 1396 allowOrigin: origin, 1397 }, 1398 { server: "https://sub1.test1." + originHost, 1399 allowOrigin: origin, 1400 }, 1401 ], 1402 }, 1403 { pass: 0, 1404 method: "POST", 1405 body: "hi there", 1406 headers: { "Content-Type": "text/plain", 1407 "my-header": "myValue", 1408 }, 1409 hops: [{ server: otherURL, 1410 }, 1411 { server: "https://sub1.test1." + originHost, 1412 allowOrigin: origin, 1413 allowHeaders: "my-header", 1414 }, 1415 ], 1416 }, 1417 { pass: 1, 1418 method: "POST", 1419 body: "hi there", 1420 headers: { "Content-Type": "text/plain" }, 1421 hops: [{ server: origin, 1422 }, 1423 { server: otherURL, 1424 allowOrigin: origin, 1425 }, 1426 ], 1427 }, 1428 { pass: 0, 1429 method: "POST", 1430 body: "hi there", 1431 headers: { "Content-Type": "text/plain", 1432 "my-header": "myValue", 1433 }, 1434 hops: [{ server: otherURL, 1435 allowOrigin: origin, 1436 allowHeaders: "my-header", 1437 }, 1438 { server: origin, 1439 allowOrigin: origin, 1440 allowHeaders: "my-header", 1441 }, 1442 ], 1443 }, 1444 1445 // test redirects with different credentials settings 1446 { 1447 // Initialize by setting a cookies for same- and cross- origins. 1448 pass: 1, 1449 method: "GET", 1450 hops: [{ server: origin, 1451 setCookie: escape("a=1; Partitioned; Secure; SameSite=None"), 1452 }, 1453 { server: otherURL, 1454 allowOrigin: origin, 1455 allowCred: 1, 1456 setCookie: escape("a=2; Partitioned; Secure; SameSite=None"), 1457 }, 1458 ], 1459 withCred: 1, 1460 }, 1461 { pass: 1, 1462 method: "GET", 1463 hops: [{ server: origin, 1464 cookie: escape("a=1"), 1465 }, 1466 { server: origin, 1467 cookie: escape("a=1"), 1468 }, 1469 { server: otherURL, 1470 allowOrigin: origin, 1471 noCookie: 1, 1472 }, 1473 ], 1474 withCred: 0, 1475 }, 1476 { pass: 1, 1477 method: "GET", 1478 hops: [{ server: origin, 1479 cookie: escape("a=1"), 1480 }, 1481 { server: origin, 1482 cookie: escape("a=1"), 1483 }, 1484 { server: otherURL, 1485 allowOrigin: origin, 1486 allowCred: 1, 1487 cookie: escape("a=2"), 1488 }, 1489 ], 1490 withCred: 1, 1491 }, 1492 // expected fail because allow-credentials CORS header is not set 1493 { pass: 0, 1494 method: "GET", 1495 hops: [{ server: origin, 1496 cookie: escape("a=1"), 1497 }, 1498 { server: origin, 1499 cookie: escape("a=1"), 1500 }, 1501 { server: otherURL, 1502 allowOrigin: origin, 1503 cookie: escape("a=2"), 1504 }, 1505 ], 1506 withCred: 1, 1507 }, 1508 { pass: 1, 1509 method: "GET", 1510 hops: [{ server: origin, 1511 cookie: escape("a=1"), 1512 }, 1513 { server: origin, 1514 cookie: escape("a=1"), 1515 }, 1516 { server: otherURL, 1517 allowOrigin: '*', 1518 noCookie: 1, 1519 }, 1520 ], 1521 withCred: 0, 1522 }, 1523 { pass: 0, 1524 method: "GET", 1525 hops: [{ server: origin, 1526 cookie: escape("a=1"), 1527 }, 1528 { server: origin, 1529 cookie: escape("a=1"), 1530 }, 1531 { server: otherURL, 1532 allowOrigin: '*', 1533 allowCred: 1, 1534 cookie: escape("a=2"), 1535 }, 1536 ], 1537 withCred: 1, 1538 }, 1539 ]; 1540 1541 if (!runRedirectTests) { 1542 tests = []; 1543 } 1544 1545 for (test of tests) { 1546 req = { 1547 url: test.hops[0].server + basePath + "hop=1&hops=" + 1548 escape(JSON.stringify(test.hops)), 1549 method: test.method, 1550 headers: test.headers, 1551 body: test.body, 1552 withCred: test.withCred, 1553 }; 1554 1555 if (test.pass) { 1556 if (test.body) 1557 req.url += "&body=" + escape(test.body); 1558 } 1559 1560 loaderWindow.postMessage(JSON.stringify(req), origin); 1561 1562 res = JSON.parse(yield); 1563 if (test.pass) { 1564 is(res.didFail, false, 1565 "shouldn't have failed in test for " + JSON.stringify(test)); 1566 is(res.status, 200, "wrong status in test for " + JSON.stringify(test)); 1567 is(res.statusText, "OK", "wrong status text for " + JSON.stringify(test)); 1568 is(res.responseXML, "<res>hello pass</res>", 1569 "wrong responseXML in test for " + JSON.stringify(test)); 1570 is(res.responseText, "<res>hello pass</res>\n", 1571 "wrong responseText in test for " + JSON.stringify(test)); 1572 is(res.events.join(","), 1573 "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend", 1574 "wrong responseText in test for " + JSON.stringify(test)); 1575 } 1576 else { 1577 is(res.didFail, true, 1578 "should have failed in test for " + JSON.stringify(test)); 1579 is(res.status, 0, "wrong status in test for " + JSON.stringify(test)); 1580 is(res.statusText, "", "wrong status text for " + JSON.stringify(test)); 1581 is(res.responseXML, null, 1582 "wrong responseXML in test for " + JSON.stringify(test)); 1583 is(res.responseText, "", 1584 "wrong responseText in test for " + JSON.stringify(test)); 1585 is(res.events.join(","), 1586 "opening,rs1,sending,loadstart,rs4,error,loadend", 1587 "wrong events in test for " + JSON.stringify(test)); 1588 is(res.progressEvents, 0, 1589 "wrong progressevents in test for " + JSON.stringify(test)); 1590 } 1591 } 1592 1593 SpecialPowers.clearUserPref("network.cookie.sameSite.laxByDefault"); 1594 SpecialPowers.clearUserPref("browser.contentblocking.category"); 1595 1596 clearCORSPreflightCacheTest(); 1597 } 1598 1599 </script> 1600 </pre> 1601 </body> 1602 </html>