referrer_testserver.sjs (18318B)
1 /* 2 * Test server for iframe, anchor, and area referrer attributes. 3 * https://bugzilla.mozilla.org/show_bug.cgi?id=1175736 4 * Also server for further referrer tests such as redirecting tests 5 * bug 1174913, bug 1175736, bug 1184781 6 */ 7 8 const SJS = "referrer_testserver.sjs?"; 9 const SJS_PATH = "/tests/dom/base/test/"; 10 const BASE_ORIGIN = "example.com"; 11 const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS; 12 const SHARED_KEY = SJS; 13 const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS; 14 const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS; 15 16 const IMG_BYTES = atob( 17 "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + 18 "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" 19 ); 20 21 function createTestUrl( 22 aPolicy, 23 aAction, 24 aName, 25 aType, 26 aSchemeFrom, 27 aSchemeTo, 28 crossOrigin, 29 referrerPolicyHeader 30 ) { 31 var schemeTo = aSchemeTo || "http"; 32 var schemeFrom = aSchemeFrom || "http"; 33 var rpHeader = referrerPolicyHeader || ""; 34 var url = schemeTo + "://"; 35 url += crossOrigin ? CROSS_ORIGIN_URL : BASE_URL; 36 url += 37 "ACTION=" + 38 aAction + 39 "&" + 40 "policy=" + 41 aPolicy + 42 "&" + 43 "NAME=" + 44 aName + 45 "&" + 46 "type=" + 47 aType + 48 "&" + 49 "RP_HEADER=" + 50 rpHeader + 51 "&" + 52 "SCHEME_FROM=" + 53 schemeFrom; 54 return url; 55 } 56 57 // test page using iframe referrer attribute 58 // if aParams are set this creates a test where the iframe url is a redirect 59 function createIframeTestPageUsingRefferer( 60 aMetaPolicy, 61 aAttributePolicy, 62 aNewAttributePolicy, 63 aName, 64 aParams, 65 aSchemeFrom, 66 aSchemeTo, 67 aChangingMethod 68 ) { 69 var metaString = ""; 70 if (aMetaPolicy) { 71 metaString = `<meta name="referrer" content="${aMetaPolicy}">`; 72 } 73 var changeString = ""; 74 if (aChangingMethod === "setAttribute") { 75 changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; 76 } else if (aChangingMethod === "property") { 77 changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`; 78 } 79 var iFrameString = `<iframe src="" id="myframe" ${ 80 aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : "" 81 }>iframe</iframe>`; 82 var iframeUrl = ""; 83 if (aParams) { 84 aParams.delete("ACTION"); 85 aParams.append("ACTION", "redirectIframe"); 86 iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); 87 } else { 88 iframeUrl = createTestUrl( 89 aAttributePolicy, 90 "test", 91 aName, 92 "iframe", 93 aSchemeFrom, 94 aSchemeTo 95 ); 96 } 97 98 return `<!DOCTYPE HTML> 99 <html> 100 <head> 101 ${metaString} 102 </head> 103 <body> 104 ${iFrameString} 105 <script> 106 window.addEventListener("load", function() { 107 ${changeString} 108 document.getElementById("myframe").onload = function(){ 109 parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 110 }; 111 document.getElementById("myframe").src = "${iframeUrl}"; 112 }.bind(window), false); 113 </script> 114 </body> 115 </html>`; 116 } 117 118 function buildAnchorString( 119 aMetaPolicy, 120 aReferrerPolicy, 121 aName, 122 aRelString, 123 aSchemeFrom, 124 aSchemeTo 125 ) { 126 if (aReferrerPolicy) { 127 return `<a href="${createTestUrl( 128 aReferrerPolicy, 129 "test", 130 aName, 131 "link", 132 aSchemeFrom, 133 aSchemeTo 134 )}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`; 135 } 136 return `<a href="${createTestUrl( 137 aMetaPolicy, 138 "test", 139 aName, 140 "link", 141 aSchemeFrom, 142 aSchemeTo 143 )}" id="link" ${aRelString}>link</a>`; 144 } 145 146 function buildAreaString( 147 aMetaPolicy, 148 aReferrerPolicy, 149 aName, 150 aRelString, 151 aSchemeFrom, 152 aSchemeTo 153 ) { 154 var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`; 155 result += `<map name="imageMap">`; 156 if (aReferrerPolicy) { 157 result += `<area shape="circle" coords="1,1,1" href="${createTestUrl( 158 aReferrerPolicy, 159 "test", 160 aName, 161 "link", 162 aSchemeFrom, 163 aSchemeTo 164 )}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`; 165 } else { 166 result += `<area shape="circle" coords="1,1,1" href="${createTestUrl( 167 aMetaPolicy, 168 "test", 169 aName, 170 "link", 171 aSchemeFrom, 172 aSchemeTo 173 )}" alt="theArea" id="link" ${aRelString}>`; 174 } 175 result += `</map>`; 176 177 return result; 178 } 179 180 // test page using anchor or area referrer attribute 181 function createAETestPageUsingRefferer( 182 aMetaPolicy, 183 aAttributePolicy, 184 aNewAttributePolicy, 185 aName, 186 aRel, 187 aStringBuilder, 188 aSchemeFrom, 189 aSchemeTo, 190 aChangingMethod 191 ) { 192 var metaString = ""; 193 if (aMetaPolicy) { 194 metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; 195 } 196 var changeString = ""; 197 if (aChangingMethod === "setAttribute") { 198 changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; 199 } else if (aChangingMethod === "property") { 200 changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`; 201 } 202 var relString = ""; 203 if (aRel) { 204 relString = `rel="noreferrer"`; 205 } 206 var elementString = aStringBuilder( 207 aMetaPolicy, 208 aAttributePolicy, 209 aName, 210 relString, 211 aSchemeFrom, 212 aSchemeTo 213 ); 214 215 return `<!DOCTYPE HTML> 216 <html> 217 ${metaString} 218 <body> 219 ${elementString} 220 <script> 221 window.addEventListener("load", function() { 222 ${changeString} 223 document.getElementById("link").click(); 224 }.bind(window), false); 225 </script> 226 </body> 227 </html>`; 228 } 229 230 // test page using anchor target=_blank rel=noopener 231 function createTargetBlankRefferer( 232 aMetaPolicy, 233 aName, 234 aSchemeFrom, 235 aSchemeTo, 236 aRpHeader 237 ) { 238 var metaString = ""; 239 if (aMetaPolicy) { 240 metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; 241 } 242 var elementString = `<a href="${createTestUrl( 243 aMetaPolicy, 244 "test", 245 aName, 246 "link", 247 aSchemeFrom, 248 aSchemeTo, 249 aRpHeader 250 )}" target=_blank rel="noopener" id="link">link</a>`; 251 252 return `<!DOCTYPE HTML> 253 <html> 254 ${metaString} 255 <body> 256 ${elementString} 257 <script> 258 window.addEventListener("load", function() { 259 let link = document.getElementById("link"); 260 SpecialPowers.wrap(window).parent.postMessage("childLoadReady", "*"); 261 link.click(); 262 }.bind(window), false); 263 </script> 264 </body> 265 </html>`; 266 } 267 268 // creates test page with img that is a redirect 269 function createRedirectImgTestCase(aParams, aAttributePolicy) { 270 var metaString = ""; 271 if (aParams.has("META_POLICY")) { 272 metaString = `<meta name="referrer" content="${aParams.get( 273 "META_POLICY" 274 )}">`; 275 } 276 aParams.delete("ACTION"); 277 aParams.append("ACTION", "redirectImg"); 278 var imgUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); 279 280 return `<!DOCTYPE HTML> 281 <html> 282 <head> 283 <meta charset="utf-8"> 284 ${metaString} 285 <title>Test referrer policies on redirect (img)</title> 286 </head> 287 <body> 288 <img id="testImg" src="${imgUrl}" ${ 289 aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : "" 290 }> 291 <script> 292 window.addEventListener("load", function() { 293 parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 294 }.bind(window), false); 295 </script> 296 </body> 297 </html>`; 298 } 299 300 // test page using link referrer attribute 301 function createLinkPageUsingRefferer( 302 aMetaPolicy, 303 aAttributePolicy, 304 aNewAttributePolicy, 305 aName, 306 aRel, 307 aStringBuilder, 308 aSchemeFrom, 309 aSchemeTo, 310 aTestType 311 ) { 312 var metaString = ""; 313 if (aMetaPolicy) { 314 metaString = `<meta name="referrer" content="${aMetaPolicy}">`; 315 } 316 317 var changeString = ""; 318 var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy; 319 var elementString = aStringBuilder( 320 policy, 321 aName, 322 aRel, 323 aSchemeFrom, 324 aSchemeTo, 325 aTestType 326 ); 327 328 if (aTestType === "setAttribute") { 329 changeString = `var link = document.getElementById("test_link"); 330 link.setAttribute("referrerpolicy", "${aNewAttributePolicy}"); 331 link.href = "${createTestUrl( 332 policy, 333 "test", 334 aName, 335 "link_element_" + aRel, 336 aSchemeFrom, 337 aSchemeTo 338 )}";`; 339 } else if (aTestType === "property") { 340 changeString = `var link = document.getElementById("test_link"); 341 link.referrerPolicy = "${aNewAttributePolicy}"; 342 link.href = "${createTestUrl( 343 policy, 344 "test", 345 aName, 346 "link_element_" + aRel, 347 aSchemeFrom, 348 aSchemeTo 349 )}";`; 350 } 351 352 return `<!DOCTYPE HTML> 353 <html> 354 <head> 355 ${metaString} 356 </head> 357 <body> 358 ${elementString} 359 <script> 360 ${changeString} 361 </script> 362 </body> 363 </html>`; 364 } 365 366 function createFetchUserControlRPTestCase( 367 aName, 368 aSchemeFrom, 369 aSchemeTo, 370 crossOrigin 371 ) { 372 var srcUrl = createTestUrl( 373 "", 374 "test", 375 aName, 376 "fetch", 377 aSchemeFrom, 378 aSchemeTo, 379 crossOrigin 380 ); 381 382 return `<!DOCTYPE HTML> 383 <html> 384 <head> 385 <meta charset="utf-8"> 386 <title>Test user control referrer policies</title> 387 </head> 388 <body> 389 <script> 390 fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) { 391 window.parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 392 }); 393 </script> 394 </body> 395 </html>`; 396 } 397 398 function buildLinkString( 399 aPolicy, 400 aName, 401 aRel, 402 aSchemeFrom, 403 aSchemeTo, 404 aTestType 405 ) { 406 var href = ""; 407 var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`; 408 var policy = ""; 409 var asString = ""; 410 var relString = ""; 411 412 if (aRel) { 413 relString = `rel="${aRel}"`; 414 } 415 416 if (aPolicy) { 417 policy = `referrerpolicy=${aPolicy}`; 418 } 419 420 if (aRel == "preload") { 421 asString = 'as="image"'; 422 } 423 424 if (!aTestType) { 425 href = `href=${createTestUrl( 426 aPolicy, 427 "test", 428 aName, 429 "link_element_" + aRel, 430 aSchemeFrom, 431 aSchemeTo 432 )}`; 433 } 434 435 return `<link ${relString} ${href} ${policy} ${asString} id="test_link" onload='${onChildComplete}' onerror='${onChildComplete}'>`; 436 } 437 438 // eslint-disable-next-line complexity 439 function handleRequest(request, response) { 440 var params = new URLSearchParams(request.queryString); 441 var action = params.get("ACTION"); 442 var schemeFrom = params.get("SCHEME_FROM") || "http"; 443 var schemeTo = params.get("SCHEME_TO") || "http"; 444 var crossOrigin = params.get("CROSS_ORIGIN") || false; 445 var referrerPolicyHeader = params.get("RP_HEADER") || ""; 446 447 response.setHeader("Access-Control-Allow-Origin", "*", false); 448 if (referrerPolicyHeader) { 449 response.setHeader("Referrer-Policy", referrerPolicyHeader, false); 450 } 451 452 if (action === "resetState") { 453 setSharedState(SHARED_KEY, "{}"); 454 response.write(""); 455 return; 456 } 457 if (action === "get-test-results") { 458 // ?action=get-result 459 response.setHeader("Cache-Control", "no-cache", false); 460 response.setHeader("Content-Type", "text/plain", false); 461 response.write(getSharedState(SHARED_KEY)); 462 return; 463 } 464 if (action === "redirect") { 465 response.write( 466 '<script>parent.postMessage("childLoadComplete", "http://mochi.test:8888");</script>' 467 ); 468 return; 469 } 470 if (action === "redirectImg") { 471 params.delete("ACTION"); 472 params.append("ACTION", "test"); 473 params.append("type", "img"); 474 // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect 475 response.setStatusLine("1.1", 302, "found"); 476 response.setHeader( 477 "Location", 478 "http://" + CROSS_ORIGIN_URL + params.toString(), 479 false 480 ); 481 return; 482 } 483 if (action === "redirectIframe") { 484 params.delete("ACTION"); 485 params.append("ACTION", "test"); 486 params.append("type", "iframe"); 487 // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect 488 response.setStatusLine("1.1", 302, "found"); 489 response.setHeader( 490 "Location", 491 "http://" + CROSS_ORIGIN_URL + params.toString(), 492 false 493 ); 494 return; 495 } 496 if (action === "test") { 497 // ?action=test&policy=origin&name=name 498 var policy = params.get("policy"); 499 var name = params.get("NAME"); 500 var type = params.get("type"); 501 var result = getSharedState(SHARED_KEY); 502 503 result = result ? JSON.parse(result) : {}; 504 505 var referrerLevel = "none"; 506 var test = {}; 507 if (request.hasHeader("Referer")) { 508 var referrer = request.getHeader("Referer"); 509 if (referrer.indexOf("referrer_testserver") > 0) { 510 referrerLevel = "full"; 511 } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) { 512 referrerLevel = "origin"; 513 } else { 514 // this is never supposed to happen 515 referrerLevel = "other-origin"; 516 } 517 test.referrer = referrer; 518 } else { 519 test.referrer = ""; 520 } 521 test.policy = referrerLevel; 522 test.expected = policy; 523 524 result[name] = test; 525 526 setSharedState(SHARED_KEY, JSON.stringify(result)); 527 528 if (type === "img" || type == "link_element_preload") { 529 // return image 530 response.setHeader("Content-Type", "image/png"); 531 response.write(IMG_BYTES); 532 return; 533 } 534 if (type === "iframe") { 535 // return iframe page 536 response.write("<html><body>I am the iframe</body></html>"); 537 return; 538 } 539 if (type === "link") { 540 // forward link click to redirect URL to finish test 541 var loc = "http://" + BASE_URL + "ACTION=redirect"; 542 response.setStatusLine("1.1", 302, "Found"); 543 response.setHeader("Location", loc, false); 544 } 545 return; 546 } 547 548 response.setHeader("Cache-Control", "no-cache", false); 549 response.setHeader("Content-Type", "text/html; charset=utf-8", false); 550 551 // parse test arguments and start test 552 var attributePolicy = params.get("ATTRIBUTE_POLICY") || ""; 553 var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || ""; 554 var metaPolicy = params.get("META_POLICY") || ""; 555 var rel = params.get("REL") || ""; 556 var name = params.get("NAME"); 557 558 // anchor & area 559 var _getPage = createAETestPageUsingRefferer.bind( 560 null, 561 metaPolicy, 562 attributePolicy, 563 newAttributePolicy, 564 name, 565 rel 566 ); 567 var _getAnchorPage = _getPage.bind( 568 null, 569 buildAnchorString, 570 schemeFrom, 571 schemeTo 572 ); 573 var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo); 574 575 // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder 576 if (action === "generate-anchor-policy-test") { 577 response.write(_getAnchorPage()); 578 return; 579 } 580 if (action === "generate-anchor-changing-policy-test-set-attribute") { 581 response.write(_getAnchorPage("setAttribute")); 582 return; 583 } 584 if (action === "generate-anchor-changing-policy-test-property") { 585 response.write(_getAnchorPage("property")); 586 return; 587 } 588 if (action === "generate-area-policy-test") { 589 response.write(_getAreaPage()); 590 return; 591 } 592 if (action === "generate-area-changing-policy-test-set-attribute") { 593 response.write(_getAreaPage("setAttribute")); 594 return; 595 } 596 if (action === "generate-area-changing-policy-test-property") { 597 response.write(_getAreaPage("property")); 598 return; 599 } 600 if (action === "generate-anchor-target-blank-policy-test") { 601 response.write( 602 createTargetBlankRefferer( 603 metaPolicy, 604 name, 605 schemeFrom, 606 schemeTo, 607 referrerPolicyHeader 608 ) 609 ); 610 return; 611 } 612 613 // iframe 614 _getPage = createIframeTestPageUsingRefferer.bind( 615 null, 616 metaPolicy, 617 attributePolicy, 618 newAttributePolicy, 619 name, 620 "", 621 schemeFrom, 622 schemeTo 623 ); 624 625 // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod 626 if (action === "generate-iframe-policy-test") { 627 response.write(_getPage()); 628 return; 629 } 630 if (action === "generate-iframe-changing-policy-test-set-attribute") { 631 response.write(_getPage("setAttribute")); 632 return; 633 } 634 if (action === "generate-iframe-changing-policy-test-property") { 635 response.write(_getPage("property")); 636 return; 637 } 638 639 // redirect tests with img and iframe 640 if (action === "generate-img-redirect-policy-test") { 641 response.write(createRedirectImgTestCase(params, attributePolicy)); 642 return; 643 } 644 if (action === "generate-iframe-redirect-policy-test") { 645 response.write( 646 createIframeTestPageUsingRefferer( 647 metaPolicy, 648 attributePolicy, 649 newAttributePolicy, 650 name, 651 params, 652 schemeFrom, 653 schemeTo 654 ) 655 ); 656 return; 657 } 658 659 var _getPage = createLinkPageUsingRefferer.bind( 660 null, 661 metaPolicy, 662 attributePolicy, 663 newAttributePolicy, 664 name, 665 rel 666 ); 667 var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo); 668 669 // link 670 if (action === "generate-link-policy-test") { 671 response.write(_getLinkPage()); 672 return; 673 } 674 if (action === "generate-link-policy-test-set-attribute") { 675 response.write(_getLinkPage("setAttribute")); 676 return; 677 } 678 if (action === "generate-link-policy-test-property") { 679 response.write(_getLinkPage("property")); 680 return; 681 } 682 683 if (action === "generate-fetch-user-control-policy-test") { 684 response.write( 685 createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin) 686 ); 687 return; 688 } 689 690 response.write("I don't know action " + action); 691 }