mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Bug 266554 - Send Referer
header on refresh. r=peterv,ckerschb,dom-core,smaug
This applies for refreshes resulting from either a `<meta>` refresh or the Refresh header. Referrer Policy is honored. Because exposing the referrer in a new place could have privacy implications, this behavior is gated behind a disabled pref until anti-tracking has been considered in bug 1928294. Some WPTs that D227450 touches are cleaned up a bit. Differential Revision: https://phabricator.services.mozilla.com/D227450
This commit is contained in:
parent
39159ab795
commit
9d26826a63
@ -5067,13 +5067,15 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||
loadState->SetLoadType(LOAD_REFRESH);
|
||||
}
|
||||
|
||||
/* We mimic HTTP, which passes the original referrer.
|
||||
* TODO(bug 266554): Send the referrer to the server (if allowed by referrer
|
||||
* policy and tracking protection).
|
||||
* See step 3 of
|
||||
const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
|
||||
/* The document's referrer policy is needed instead of mReferrerInfo's
|
||||
* referrer policy.
|
||||
*/
|
||||
const nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
||||
new ReferrerInfo(*doc, sendReferrer);
|
||||
/* We mimic HTTP, which passes the original referrer. See step 3 of
|
||||
* <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
|
||||
*/
|
||||
const nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(*doc, false);
|
||||
loadState->SetReferrerInfo(referrerInfo);
|
||||
|
||||
loadState->SetLoadFlags(
|
||||
|
@ -2,6 +2,7 @@
|
||||
tags = "condprof"
|
||||
prefs = [
|
||||
"formhelper.autozoom.force-disable.test-only=true",
|
||||
"network.http.referer.sendFromRefresh=false",
|
||||
"plugins.rewrite_youtube_embeds=true",
|
||||
]
|
||||
support-files = [
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name='referrer' content='origin'>
|
||||
<title>Test for referrer of meta refresh request</title>
|
||||
<title>Test for referrer of meta refresh request when network.http.referer.sendFromRefresh is disabled.</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
|
@ -12525,6 +12525,13 @@
|
||||
value: 500
|
||||
mirror: always
|
||||
|
||||
# Whether to send the Referer header in response to a meta refresh, or
|
||||
# in response to a Refresh header.
|
||||
- name: network.http.referer.sendFromRefresh
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# false=real referer, true=spoof referer (use target URI as referer).
|
||||
- name: network.http.referer.spoofSource
|
||||
type: bool
|
||||
|
@ -0,0 +1 @@
|
||||
prefs: [network.http.referer.sendFromRefresh:true]
|
@ -0,0 +1 @@
|
||||
prefs: [network.http.referer.sendFromRefresh:true]
|
@ -0,0 +1 @@
|
||||
prefs: [network.http.referer.sendFromRefresh:true]
|
@ -0,0 +1,20 @@
|
||||
[refresh-cross-origin.sub.html]
|
||||
[cross-origin meta refresh with referrer policy "no-referrer-when-downgrade" refreshes with full url as referrer]
|
||||
# This is wontfix behavior.
|
||||
bug: 'https://bugzilla.mozilla.org/show_bug.cgi?id=1800070#c2'
|
||||
expected: FAIL
|
||||
|
||||
[cross-origin header refresh with referrer policy "no-referrer-when-downgrade" refreshes with full url as referrer]
|
||||
# This is wontfix behavior.
|
||||
bug: 'https://bugzilla.mozilla.org/show_bug.cgi?id=1800070#c2'
|
||||
expected: FAIL
|
||||
|
||||
[cross-origin meta refresh with referrer policy "unsafe-url" refreshes with full url as referrer]
|
||||
# This is wontfix behavior.
|
||||
bug: 'https://bugzilla.mozilla.org/show_bug.cgi?id=1800070#c2'
|
||||
expected: FAIL
|
||||
|
||||
[cross-origin header refresh with referrer policy "unsafe-url" refreshes with full url as referrer]
|
||||
# This is wontfix behavior.
|
||||
bug: 'https://bugzilla.mozilla.org/show_bug.cgi?id=1800070#c2'
|
||||
expected: FAIL
|
@ -0,0 +1,42 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Referrer from Refresh after Same-Document Navigation</title>
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=266554">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives:navigate">
|
||||
<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
promise_test(async t => {
|
||||
const refreshTo = new URL("resources/refreshed.txt", location).href;
|
||||
const refreshFrom = new URL("resources/refresh-with-section.sub.html", location).href + "?" + new URLSearchParams({url: refreshTo});
|
||||
|
||||
const frame = document.createElement("iframe");
|
||||
const { promise: frameLoaded, resolve: resolveFrameLoaded } = Promise.withResolvers();
|
||||
|
||||
let loadCount = 0;
|
||||
frame.addEventListener("load", t.step_func(() => {
|
||||
loadCount++;
|
||||
try {
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, refreshFrom + "#section", "same-document navigation occurred");
|
||||
assert_equals(frame.contentWindow.referrer.textContent, location.href, "referrer header is parent frame");
|
||||
assert_equals(frame.contentDocument.referrer, location.href, "document referrer is parent frame");
|
||||
}
|
||||
} finally {
|
||||
if (loadCount === 2) {
|
||||
resolveFrameLoaded();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
frame.src = refreshFrom;
|
||||
document.body.appendChild(frame);
|
||||
await frameLoaded;
|
||||
|
||||
assert_equals(frame.contentWindow.location.href, refreshTo, "refresh page has expected URL")
|
||||
assert_equals(frame.contentDocument.referrer, frame.src, "referrer does not include fragment");
|
||||
});
|
||||
</script>
|
||||
</body>
|
@ -1,9 +1,19 @@
|
||||
async_test(t => {
|
||||
var loadCount = 0;
|
||||
var expectedReferrer = location.href;
|
||||
const frame = document.createElement("iframe");
|
||||
frame.src = "resources/refresh.py"
|
||||
var originalPath = "resources/refresh.py";
|
||||
frame.src = originalPath;
|
||||
frame.onload = t.step_func(() => {
|
||||
// Could be better by verifying that resources/refresh.py loads too
|
||||
if(frame.contentWindow.location.href === (new URL("resources/refreshed.txt?\u0080\u00FF", self.location)).href) { // Make sure bytes got mapped to code points of the same value
|
||||
loadCount++;
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, new URL(originalPath, self.location).href, "original page loads");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is parent frame");
|
||||
expectedReferrer = frame.src;
|
||||
} else if (loadCount === 2) {
|
||||
assert_equals(frame.contentWindow.location.href,
|
||||
new URL("resources/refreshed.txt?\u0080\u00FF", self.location).href, "bytes got mapped to code points of the same value");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is previous page");
|
||||
t.done();
|
||||
}
|
||||
});
|
||||
@ -11,11 +21,20 @@ async_test(t => {
|
||||
}, "When navigating the Refresh header needs to be followed");
|
||||
|
||||
async_test(t => {
|
||||
var loadCount = 0;
|
||||
var expectedReferrer = location.href;
|
||||
const frame = document.createElement("iframe");
|
||||
frame.src = "resources/multiple.asis"
|
||||
var originalPath = "resources/multiple.asis";
|
||||
frame.src = originalPath
|
||||
frame.onload = t.step_func(() => {
|
||||
// Could be better by verifying that resources/refresh.py loads too
|
||||
if(frame.contentWindow.location.href === (new URL("resources/refreshed.txt", self.location)).href) {
|
||||
loadCount++;
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, new URL(originalPath, self.location).href, "original page loads");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is parent frame");
|
||||
expectedReferrer = frame.src;
|
||||
} else if (loadCount === 2) {
|
||||
assert_equals(frame.contentWindow.location.href, new URL("resources/refreshed.txt", self.location).href, "refresh page loads");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is previous page");
|
||||
t.done();
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,35 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<p id="referrer">{{header_or_default(referer, )}}</p>
|
||||
<section id="section">My section</section>
|
||||
<span id="info">Refreshing to</span>
|
||||
<span id=url>{{GET[url]}}</span>
|
||||
<script>
|
||||
function refresh() {
|
||||
if (url.textContent !== "") {
|
||||
const refresh = document.createElement("meta");
|
||||
refresh.httpEquiv = "refresh";
|
||||
refresh.content = `0; url=${url.textContent}`;
|
||||
document.documentElement.appendChild(refresh);
|
||||
} else {
|
||||
info.textContent = "Not refreshing.";
|
||||
}
|
||||
}
|
||||
|
||||
function sendData() {
|
||||
const documentReferrer = document.referrer;
|
||||
const data = {referrer: referrer.textContent, documentReferrer, url: location.href};
|
||||
window.parent.postMessage(data, "*");
|
||||
}
|
||||
|
||||
const sectionHash = "#section";
|
||||
if (url.textContent !== sectionHash) {
|
||||
window.addEventListener("hashchange", refresh);
|
||||
location.hash = sectionHash;
|
||||
} else if (location.hash !== sectionHash) {
|
||||
window.addEventListener("hashchange", sendData);
|
||||
refresh();
|
||||
} else {
|
||||
sendData();
|
||||
}
|
||||
</script>
|
@ -0,0 +1,54 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Same-Document Referrer from Refresh</title>
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=266554">
|
||||
<link rel="help" href="https://github.com/whatwg/html/issues/6451">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-fragid-step">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives:navigate">
|
||||
<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
promise_test(async t => {
|
||||
const fragment = "#section";
|
||||
const refreshFrom = new URL("resources/refresh-with-section.sub.html", location).href + "?" + new URLSearchParams({url: fragment});
|
||||
|
||||
const frame = document.createElement("iframe");
|
||||
const { promise: frameLoaded, resolve: resolveFrameLoaded } = Promise.withResolvers();
|
||||
const { promise: messageHandled, resolve: resolveMessageHandled } = Promise.withResolvers();
|
||||
|
||||
let loadCount = 0;
|
||||
frame.addEventListener("load", t.step_func(() => {
|
||||
loadCount++;
|
||||
try {
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, refreshFrom, "original page loads");
|
||||
assert_equals(frame.contentWindow.referrer.textContent, location.href, "referrer header is parent frame");
|
||||
assert_equals(frame.contentDocument.referrer, location.href, "document referrer is parent frame");
|
||||
}
|
||||
} finally {
|
||||
if (loadCount === 1) {
|
||||
resolveFrameLoaded();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
addEventListener("message", t.step_func(msg => {
|
||||
const {referrer, documentReferrer, url} = msg.data;
|
||||
try {
|
||||
assert_equals(url, refreshFrom + fragment, "refresh page has expected URL");
|
||||
assert_equals(referrer, location.href, "referrer header is unchanged");
|
||||
assert_equals(documentReferrer, location.href, "document referrer is unchanged");
|
||||
} finally {
|
||||
resolveMessageHandled();
|
||||
}
|
||||
}));
|
||||
|
||||
frame.src = refreshFrom;
|
||||
document.body.appendChild(frame);
|
||||
await frameLoaded;
|
||||
await messageHandled;
|
||||
});
|
||||
</script>
|
||||
</body>
|
@ -118,11 +118,13 @@ tests_arr.forEach(function(test_obj) {
|
||||
iframe.src = "support/" + filename + "?input=" + encodeURIComponent(test_obj.input);
|
||||
document.body.appendChild(iframe);
|
||||
var loadCount = 0;
|
||||
var expectedReferrer = location.href;
|
||||
iframe.onload = t.step_func(function() {
|
||||
loadCount++;
|
||||
var got = iframe.contentDocument.body.textContent.trim();
|
||||
var content = iframe.contentDocument.body.textContent.trim();
|
||||
if (test_obj.expected.length === 0) {
|
||||
assert_equals(got, filename);
|
||||
assert_equals(content, filename, "page has expected content");
|
||||
assert_equals(iframe.contentDocument.referrer, expectedReferrer, "referrer is parent frame");
|
||||
if (loadCount === 1) {
|
||||
t.step_timeout(function() {
|
||||
t.done();
|
||||
@ -130,15 +132,16 @@ tests_arr.forEach(function(test_obj) {
|
||||
} else {
|
||||
assert_unreached('Got > 1 load events');
|
||||
}
|
||||
} else {
|
||||
if (loadCount === 2) {
|
||||
if(test_obj.expected[1] === "__filename__") {
|
||||
assert_equals(got, filename);
|
||||
} else {
|
||||
assert_equals(got, test_obj.expected[1]);
|
||||
}
|
||||
t.done();
|
||||
} else if (loadCount === 2) {
|
||||
if(test_obj.expected[1] === "__filename__") {
|
||||
assert_equals(content, filename, "page has expected content");
|
||||
} else {
|
||||
assert_equals(content, test_obj.expected[1], "page has expected content");
|
||||
}
|
||||
assert_equals(iframe.contentDocument.referrer, expectedReferrer, "referrer is previous page");
|
||||
t.done();
|
||||
} else if (loadCount === 1) {
|
||||
expectedReferrer = iframe.src;
|
||||
}
|
||||
});
|
||||
}, type + ": " + format_value(test_obj.input));
|
||||
|
@ -0,0 +1,51 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Cross-Origin Referrer Policy applied to Refresh</title>
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=266554">
|
||||
<link rel="help" href="https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#populating-a-session-history-entry:concept-request">
|
||||
<link rel="help" href="https://github.com/privacycg/proposals/issues/13">
|
||||
<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="./resources/refresh-by-host.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
const ports = {
|
||||
http: "{{ports[http][0]}}",
|
||||
https: "{{ports[https][0]}}",
|
||||
};
|
||||
|
||||
let scheme;
|
||||
const originScheme = location.protocol.slice(0, -1);
|
||||
if (originScheme === "http") {
|
||||
scheme = originScheme;
|
||||
} else {
|
||||
scheme = "https";
|
||||
}
|
||||
const port = ports[scheme];
|
||||
|
||||
const origin = `${scheme}://{{hosts[alt][]}}:${port}`;
|
||||
const path = "resources/referrer-info.sub.html";
|
||||
const base = new URL(location.pathname, origin);
|
||||
const url = new URL(path, base).href;
|
||||
const expectationsByPolicy = {
|
||||
"no-referrer": kExpectEmptyString,
|
||||
// WebKit and Gecko send the origin for no-referrer-when-downgrade Referrer Policy refreshes in an
|
||||
// iframe, but per the spec, the full URL should be sent in this case. Further discussion:
|
||||
// <https://github.com/privacycg/proposals/issues/13>
|
||||
"no-referrer-when-downgrade": kExpectFullURL,
|
||||
"origin": kExpectOrigin,
|
||||
"origin-when-cross-origin": kExpectOrigin,
|
||||
"same-origin": kExpectEmptyString,
|
||||
"strict-origin": kExpectOrigin,
|
||||
"strict-origin-when-cross-origin": kExpectOrigin,
|
||||
// WebKit and Gecko send the origin for unsafe-url Referrer Policy refreshes in an iframe, but per
|
||||
// the spec, the full URL should be sent in this case. Further discussion:
|
||||
// <https://github.com/privacycg/proposals/issues/13>
|
||||
"unsafe-url": kExpectFullURL,
|
||||
"": kExpectOrigin,
|
||||
};
|
||||
|
||||
refreshWithPoliciesTest(url, expectationsByPolicy);
|
||||
</script>
|
@ -0,0 +1,28 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Same-Origin Referrer Policy applied to Refresh</title>
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=266554">
|
||||
<link rel="help" href="https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#populating-a-session-history-entry:concept-request">
|
||||
<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="./resources/refresh-by-host.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
const path = "resources/referrer-info.sub.html";
|
||||
const url = new URL(path, location).href;
|
||||
const expectationsByPolicy = {
|
||||
"no-referrer": kExpectEmptyString,
|
||||
"no-referrer-when-downgrade": kExpectFullURL,
|
||||
"origin": kExpectOrigin,
|
||||
"origin-when-cross-origin": kExpectFullURL,
|
||||
"same-origin": kExpectFullURL,
|
||||
"strict-origin": kExpectOrigin,
|
||||
"strict-origin-when-cross-origin": kExpectFullURL,
|
||||
"unsafe-url": kExpectFullURL,
|
||||
"": kExpectFullURL,
|
||||
};
|
||||
|
||||
refreshWithPoliciesTest(url, expectationsByPolicy);
|
||||
</script>
|
@ -0,0 +1,70 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Same-URL Referrer Policy applied to Refresh</title>
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=266554">
|
||||
<link rel="help" href="https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#populating-a-session-history-entry:concept-request">
|
||||
<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="./resources/refresh-by-host.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
const expectationsByPolicy = {
|
||||
"no-referrer": kExpectEmptyString,
|
||||
"no-referrer-when-downgrade": kExpectFullURL,
|
||||
"origin": kExpectOrigin,
|
||||
"origin-when-cross-origin": kExpectFullURL,
|
||||
"same-origin": kExpectFullURL,
|
||||
"strict-origin": kExpectOrigin,
|
||||
"strict-origin-when-cross-origin": kExpectFullURL,
|
||||
"unsafe-url": kExpectFullURL,
|
||||
"": kExpectFullURL,
|
||||
};
|
||||
|
||||
refreshWithPoliciesSameURLTest(expectationsByPolicy);
|
||||
|
||||
function refreshWithPoliciesSameURLTest(aExpectationsByPolicy) {
|
||||
Object.entries(aExpectationsByPolicy).forEach(([policy, expected]) =>
|
||||
Object.entries(kRefreshOptionsByDescription).forEach(([description, refreshFrom]) => {
|
||||
let expectedURL = new URL(refreshFrom, location).href;
|
||||
const originalURL = expectedURL + "?" + new URLSearchParams({url: expectedURL, policy});
|
||||
let expectedReferrer = location.href;
|
||||
|
||||
promise_test(async t => {
|
||||
let loadCount = 0;
|
||||
const { promise: frameLoaded, resolve: resolveFrameLoaded } = Promise.withResolvers();
|
||||
|
||||
const frame = document.createElement("iframe");
|
||||
try {
|
||||
frame.addEventListener("load", t.step_func(() => {
|
||||
loadCount++;
|
||||
try {
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, originalURL, "original page loads");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is parent frame");
|
||||
|
||||
expectedReferrer = referrerPolicyExpectationValue(expected, frame);
|
||||
} else if (loadCount === 2) {
|
||||
assert_equals(frame.contentWindow.location.href, expectedURL, "refresh page has expected URL");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "document referrer is same page");
|
||||
}
|
||||
} finally {
|
||||
if (loadCount === 2) {
|
||||
resolveFrameLoaded();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
frame.src = originalURL;
|
||||
document.body.appendChild(frame);
|
||||
|
||||
await frameLoaded;
|
||||
} finally {
|
||||
frame.remove();
|
||||
t.done();
|
||||
}
|
||||
}, `same-URL ${description} with referrer policy "${policy}" refreshes with ${expected} as referrer`);
|
||||
}));
|
||||
}
|
||||
</script>
|
@ -0,0 +1,8 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<p id="referrer">{{header_or_default(referer, )}}</p>
|
||||
<script>
|
||||
const documentReferrer = document.referrer;
|
||||
const data = {referrer: referrer.textContent, documentReferrer, url: location.href};
|
||||
window.parent.postMessage(data, "*");
|
||||
</script>
|
@ -0,0 +1,83 @@
|
||||
const kOriginTypeDescriptions = {
|
||||
true: "same-origin",
|
||||
false: "cross-origin",
|
||||
}
|
||||
|
||||
const kRefreshOptionsByDescription = {
|
||||
"meta refresh": "resources/refresh-policy.sub.html",
|
||||
"header refresh": "resources/refresh-policy.py",
|
||||
};
|
||||
|
||||
const kExpectEmptyString = "the empty string";
|
||||
const kExpectOrigin = "origin";
|
||||
const kExpectFullURL = "full url";
|
||||
|
||||
function referrerPolicyExpectationValue(aExpected, aFrame) {
|
||||
let expectedReferrer;
|
||||
switch (aExpected) {
|
||||
case kExpectEmptyString:
|
||||
expectedReferrer = "";
|
||||
break;
|
||||
case kExpectOrigin:
|
||||
expectedReferrer = new URL(aFrame.src).origin + "/";
|
||||
break;
|
||||
case kExpectFullURL:
|
||||
expectedReferrer = aFrame.src;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unexpected referrer type ${aExpected}`);
|
||||
}
|
||||
return expectedReferrer;
|
||||
}
|
||||
|
||||
function refreshWithPoliciesTest(aExpectedURL, aExpectationsByPolicy) {
|
||||
const isSameOrigin = location.origin === new URL(aExpectedURL).origin;
|
||||
Object.entries(aExpectationsByPolicy).forEach(([policy, expected]) =>
|
||||
Object.entries(kRefreshOptionsByDescription).forEach(([description, refreshFrom]) =>
|
||||
promise_test(async t => {
|
||||
const originalPath = refreshFrom + "?" + new URLSearchParams({url: aExpectedURL, policy});
|
||||
let expectedReferrer = location.href;
|
||||
let loadCount = 0;
|
||||
const { promise: frameLoaded, resolve: resolveFrameLoaded } = Promise.withResolvers();
|
||||
const { promise: messageHandled, resolve: resolveMessageHandled } = Promise.withResolvers();
|
||||
|
||||
const frame = document.createElement("iframe");
|
||||
try {
|
||||
frame.addEventListener("load", t.step_func(() => {
|
||||
loadCount++;
|
||||
try {
|
||||
if (loadCount === 1) {
|
||||
assert_equals(frame.contentWindow.location.href, new URL(originalPath, location).href, "original page loads");
|
||||
assert_equals(frame.contentDocument.referrer, expectedReferrer, "referrer is parent frame");
|
||||
|
||||
expectedReferrer = referrerPolicyExpectationValue(expected, frame);
|
||||
}
|
||||
} finally {
|
||||
if (loadCount === 1) {
|
||||
resolveFrameLoaded();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
addEventListener("message", t.step_func(msg => {
|
||||
const {referrer, documentReferrer, url} = msg.data;
|
||||
try {
|
||||
assert_equals(url, aExpectedURL, "refresh page has expected URL");
|
||||
assert_equals(referrer, expectedReferrer, "referrer header is previous page");
|
||||
assert_equals(documentReferrer, expectedReferrer, "document referrer is previous page");
|
||||
} finally {
|
||||
resolveMessageHandled();
|
||||
}
|
||||
}));
|
||||
|
||||
frame.src = originalPath;
|
||||
document.body.appendChild(frame);
|
||||
|
||||
await frameLoaded;
|
||||
await messageHandled;
|
||||
} finally {
|
||||
frame.remove();
|
||||
t.done();
|
||||
}
|
||||
}, `${kOriginTypeDescriptions[isSameOrigin]} ${description} with referrer policy "${policy}" refreshes with ${expected} as referrer`)))
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
def main(request, _response):
|
||||
response_headers = [("Content-Type", "text/html")]
|
||||
|
||||
body = "<!doctype html>"
|
||||
|
||||
url = request.GET.first(b"url", b"").decode()
|
||||
if url:
|
||||
response_headers.append(("Refresh", "0; url=" + url))
|
||||
body += "Refreshing to %s" % url
|
||||
else:
|
||||
body += "Not refreshing"
|
||||
|
||||
policy = request.GET.first(b"policy", b"").decode()
|
||||
response_headers.append(("Referrer-Policy", policy))
|
||||
|
||||
return 200, response_headers, body
|
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<meta name="referrer" content="{{GET[policy]}}"/>
|
||||
<span id="info">Refreshing to</span>
|
||||
<span id=url>{{GET[url]}}</span>
|
||||
<script>
|
||||
if (url.textContent !== "") {
|
||||
const refresh = document.createElement("meta");
|
||||
refresh.httpEquiv = "refresh";
|
||||
refresh.content = `0; url=${url.textContent}`;
|
||||
document.documentElement.appendChild(refresh);
|
||||
} else {
|
||||
info.textContent = "Not refreshing.";
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user