|  | // META: script=/common/utils.js | 
|  | // META: script=/common/get-host-info.sub.js | 
|  |  | 
|  | const origins = get_host_info(); | 
|  |  | 
|  | promise_test(async function () { | 
|  | const stash = token(), | 
|  | redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; | 
|  |  | 
|  | // Cross-origin -> same-origin will result in setting the tainted origin flag for the second | 
|  | // request. | 
|  | let url = origins.HTTP_ORIGIN + redirectPath + "?stash=" + stash; | 
|  | url = origins.HTTP_REMOTE_ORIGIN + redirectPath + "?stash=" + stash + "&location=" + encodeURIComponent(url) + "&dummyJS"; | 
|  |  | 
|  | await fetch(url, { mode: "no-cors", method: "POST" }); | 
|  |  | 
|  | const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); | 
|  |  | 
|  | assert_equals(json[0], origins.HTTP_ORIGIN); | 
|  | assert_equals(json[1], "null"); | 
|  | }, "Origin header and 308 redirect"); | 
|  |  | 
|  | promise_test(async function () { | 
|  | const stash = token(), | 
|  | redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; | 
|  |  | 
|  | let url = origins.HTTP_ORIGIN + redirectPath + "?stash=" + stash; | 
|  | url = origins.HTTP_REMOTE_ORIGIN + redirectPath + "?stash=" + stash + "&location=" + encodeURIComponent(url); | 
|  |  | 
|  | await new Promise(resolve => { | 
|  | const frame = document.createElement("iframe"); | 
|  | frame.src = url; | 
|  | frame.onload = () => { | 
|  | resolve(); | 
|  | frame.remove(); | 
|  | } | 
|  | document.body.appendChild(frame); | 
|  | }); | 
|  |  | 
|  | const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); | 
|  |  | 
|  | assert_equals(json[0], "no Origin header"); | 
|  | assert_equals(json[1], "no Origin header"); | 
|  | }, "Origin header and GET navigation"); | 
|  |  | 
|  | promise_test(async function () { | 
|  | const stash = token(), | 
|  | redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; | 
|  |  | 
|  | let url = origins.HTTP_ORIGIN + redirectPath + "?stash=" + stash; | 
|  | url = origins.HTTP_REMOTE_ORIGIN + redirectPath + "?stash=" + stash + "&location=" + encodeURIComponent(url); | 
|  |  | 
|  | await new Promise(resolve => { | 
|  | const frame = document.createElement("iframe"); | 
|  | self.addEventListener("message", e => { | 
|  | if (e.data === "loaded") { | 
|  | resolve(); | 
|  | frame.remove(); | 
|  | } | 
|  | }, { once: true }); | 
|  | frame.onload = () => { | 
|  | const doc = frame.contentDocument, | 
|  | form = doc.body.appendChild(doc.createElement("form")), | 
|  | submit = form.appendChild(doc.createElement("input")); | 
|  | form.action = url; | 
|  | form.method = "POST"; | 
|  | submit.type = "submit"; | 
|  | submit.click(); | 
|  | } | 
|  | document.body.appendChild(frame); | 
|  | }); | 
|  |  | 
|  | const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); | 
|  |  | 
|  | assert_equals(json[0], origins.HTTP_ORIGIN); | 
|  | assert_equals(json[1], "null"); | 
|  | }, "Origin header and POST navigation"); | 
|  |  | 
|  | function navigationReferrerPolicy(referrerPolicy, destination, expectedOrigin) { | 
|  | return async function () { | 
|  | const stash = token(); | 
|  | const referrerPolicyPath = "/fetch/origin/resources/referrer-policy.py"; | 
|  | const redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; | 
|  |  | 
|  | let postUrl = | 
|  | (destination === "same-origin" ? origins.HTTP_ORIGIN | 
|  | : origins.HTTP_REMOTE_ORIGIN) + | 
|  | redirectPath + "?stash=" + stash; | 
|  |  | 
|  | await new Promise(resolve => { | 
|  | const frame = document.createElement("iframe"); | 
|  | document.body.appendChild(frame); | 
|  | frame.src = origins.HTTP_ORIGIN + referrerPolicyPath + | 
|  | "?referrerPolicy=" + referrerPolicy; | 
|  | self.addEventListener("message", function listener(e) { | 
|  | if (e.data === "loaded") { | 
|  | resolve(); | 
|  | frame.remove(); | 
|  | self.removeEventListener("message", listener); | 
|  | } else if (e.data === "action") { | 
|  | const doc = frame.contentDocument, | 
|  | form = doc.body.appendChild(doc.createElement("form")), | 
|  | submit = form.appendChild(doc.createElement("input")); | 
|  | form.action = postUrl; | 
|  | form.method = "POST"; | 
|  | submit.type = "submit"; | 
|  | submit.click(); | 
|  | } | 
|  | }); | 
|  | }); | 
|  |  | 
|  | const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); | 
|  |  | 
|  | assert_equals(json[0], expectedOrigin); | 
|  | }; | 
|  | } | 
|  |  | 
|  | function fetchReferrerPolicy(referrerPolicy, destination, fetchMode, expectedOrigin, httpMethod) { | 
|  | return async function () { | 
|  | const stash = token(); | 
|  | const redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; | 
|  |  | 
|  | let fetchUrl = | 
|  | (destination === "same-origin" ? origins.HTTP_ORIGIN | 
|  | : origins.HTTP_REMOTE_ORIGIN) + | 
|  | redirectPath + "?stash=" + stash + "&dummyJS"; | 
|  |  | 
|  | await fetch(fetchUrl, { mode: fetchMode, method: httpMethod , "referrerPolicy": referrerPolicy}); | 
|  |  | 
|  | const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); | 
|  |  | 
|  | assert_equals(json[0], expectedOrigin); | 
|  | }; | 
|  | } | 
|  |  | 
|  | function referrerPolicyTestString(referrerPolicy, method, destination) { | 
|  | return "Origin header and " + method + " " + destination + " with Referrer-Policy " + | 
|  | referrerPolicy; | 
|  | } | 
|  |  | 
|  | [ | 
|  | { | 
|  | "policy": "no-referrer", | 
|  | "expectedOriginForSameOrigin": "null", | 
|  | "expectedOriginForCrossOrigin": "null" | 
|  | }, | 
|  | { | 
|  | "policy": "same-origin", | 
|  | "expectedOriginForSameOrigin": origins.HTTP_ORIGIN, | 
|  | "expectedOriginForCrossOrigin": "null" | 
|  | }, | 
|  | { | 
|  | "policy": "origin-when-cross-origin", | 
|  | "expectedOriginForSameOrigin": origins.HTTP_ORIGIN, | 
|  | "expectedOriginForCrossOrigin": origins.HTTP_ORIGIN | 
|  | }, | 
|  | { | 
|  | "policy": "no-referrer-when-downgrade", | 
|  | "expectedOriginForSameOrigin": origins.HTTP_ORIGIN, | 
|  | "expectedOriginForCrossOrigin": origins.HTTP_ORIGIN | 
|  | }, | 
|  | { | 
|  | "policy": "unsafe-url", | 
|  | "expectedOriginForSameOrigin": origins.HTTP_ORIGIN, | 
|  | "expectedOriginForCrossOrigin": origins.HTTP_ORIGIN | 
|  | }, | 
|  | ].forEach(testObj => { | 
|  | [ | 
|  | { | 
|  | "name": "same-origin", | 
|  | "expectedOrigin": testObj.expectedOriginForSameOrigin | 
|  | }, | 
|  | { | 
|  | "name": "cross-origin", | 
|  | "expectedOrigin": testObj.expectedOriginForCrossOrigin | 
|  | } | 
|  | ].forEach(destination => { | 
|  | // Test form POST navigation | 
|  | promise_test(navigationReferrerPolicy(testObj.policy, | 
|  | destination.name, | 
|  | destination.expectedOrigin), | 
|  | referrerPolicyTestString(testObj.policy, "POST", | 
|  | destination.name + " navigation")); | 
|  | // Test fetch | 
|  | promise_test(fetchReferrerPolicy(testObj.policy, | 
|  | destination.name, | 
|  | "no-cors", | 
|  | destination.expectedOrigin, | 
|  | "POST"), | 
|  | referrerPolicyTestString(testObj.policy, "POST", | 
|  | destination.name + " fetch no-cors mode")); | 
|  |  | 
|  | // Test cors mode POST | 
|  | promise_test(fetchReferrerPolicy(testObj.policy, | 
|  | destination.name, | 
|  | "cors", | 
|  | origins.HTTP_ORIGIN, | 
|  | "POST"), | 
|  | referrerPolicyTestString(testObj.policy, "POST", | 
|  | destination.name + " fetch cors mode")); | 
|  |  | 
|  | // Test cors mode GET | 
|  | promise_test(fetchReferrerPolicy(testObj.policy, | 
|  | destination.name, | 
|  | "cors", | 
|  | (destination.name == "same-origin") ? "no Origin header" : origins.HTTP_ORIGIN, | 
|  | "GET"), | 
|  | referrerPolicyTestString(testObj.policy, "GET", | 
|  | destination.name + " fetch cors mode")); | 
|  | }); | 
|  | }); |