Tests: Import a WPT test for cookie domain processing
This commit is contained in:
parent
790b9bd36a
commit
2c33de1583
13 changed files with 831 additions and 1 deletions
|
|
@ -1,6 +1,7 @@
|
|||
[LoadFromHttpServer]
|
||||
; Cookies require HTTP(s) scheme.
|
||||
; Tests cookies.
|
||||
Text/input/cookie-working.html
|
||||
Text/input/wpt-import/cookies/attributes/domain.sub.html
|
||||
|
||||
; Performs cross-origin Worker fetch
|
||||
Text/input/wpt-import/html/infrastructure/safe-passing-of-structured-data/structuredclone_0.html
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 55 tests
|
||||
|
||||
53 Pass
|
||||
2 Fail
|
||||
Pass Test cookie domain attribute parsing
|
||||
Pass Return cookie for a domain match
|
||||
Pass No cookie returned for domain mismatch (subdomains differ post-redirect)
|
||||
Pass Return cookie for a domain match with leading '.'
|
||||
Pass Return cookie for domain match (domain attribute is suffix of the host name and first level subdomain)
|
||||
Pass Return cookie for domain match (domain attribute is suffix of the host name and first level subdomain, with leading '.')
|
||||
Pass No cookie returned for domain mismatch (subdomains differ, with leading '.')
|
||||
Pass No cookie returned for domain mismatch when cookie was created (which would match after the redirect, with one subdomain level)
|
||||
Pass Return cookie for domain match (domain attribute is suffix of the host name, with leading '.')
|
||||
Pass Return cookie for domain match (domain attribute is suffix of the host name)
|
||||
Pass No cookie returned for domain attribute with double leading '.'
|
||||
Pass No cookie returned for domain attribute with subdomain followed by ..
|
||||
Pass Return cookie for a domain match with leading whitespace and '.'
|
||||
Pass No cookie returned for domain attribute with whitespace that surrounds a leading '.'
|
||||
Pass No cookie returned for domain attribute with trailing '.'
|
||||
Pass No cookie returned for domain attribute with trailing '..'
|
||||
Pass No cookie returned for domain attribute with trailing whitespace and '.'
|
||||
Fail No cookie returned for domain attribute with TLD as value
|
||||
Pass No cookie returned for domain attribute with TLD as value, with leading '.'
|
||||
Pass No cookie returned for domain attribute with TLD as value, with leading and trailing '.'
|
||||
Pass Return multiple cookies that match on domain (without and with leading '.')
|
||||
Pass Return multiple cookies that match on domain (with and without leading '.')
|
||||
Pass No cookie returned for domain attribute value between quotes
|
||||
Pass Return multiple cookies that match on subdomain and domain (without and with leading '.')
|
||||
Pass Return multiple cookies that match on domain and subdomain (with and without leading '.')
|
||||
Pass No cookie returned when domain attribute does not domain-match (and first does)
|
||||
Pass Return cookie for domain attribute match (first does not, but second does)
|
||||
Pass Return cookie for domain match (with bizarre capitalization for domain attribute value)
|
||||
Pass No cookie returned for domain attribute value with port
|
||||
Pass No cookie returned for domain mismatch when cookie was created (which would match after the redirect, with two subdomain levels)
|
||||
Pass No cookie returned for cookie set on different domain (with no domain attribute)
|
||||
Pass Return cookie set with bare domain= attribute
|
||||
Pass Return cookie that domain-matches with bizarre-cased URL
|
||||
Pass No cookie returned for domain attribute mismatch (first attribute matches, but second does not)
|
||||
Pass Return cookie for domain match (first attribute doesn't, but second does)
|
||||
Pass Return cookie for domain match (first attribute matches, second doesn't, third does)
|
||||
Pass No cookie returned for domain attribute mismatch (first attribute doesn't, second does, third doesn't)
|
||||
Pass Return cookie for domain match (with two identical domain attributes)
|
||||
Pass Return cookie for domain match (with first domain attribute a match for host name and second as suffix of host name)
|
||||
Pass Return cookie for domain match (with first domain attribute as suffix of host name and second a match for host name)
|
||||
Pass No cookie set on domain mismatch before a (domain matching) redirect
|
||||
Pass No cookie set on domain mismatch before a (domain matching) redirect (for second level subdomain)
|
||||
Pass Return cookie for domain match (with first domain attribute as suffix of host name and second a bare attribute)
|
||||
Pass Cookie returned for bare domain attribute following mismatched domain attribute (after redirect to same-origin page).
|
||||
Pass No cookie returned for domain mismatch (first attribute is a different subdomain and second is bare)
|
||||
Pass Cookies with same name, path, and domain (differing only in leading '.') overwrite each other ('.' second)
|
||||
Pass Cookies with same name, path, and domain (differing only in leading '.') overwrite each other ('.' first)
|
||||
Fail No cookie returned for domain with single dot ('.') value.
|
||||
Pass Return cookie with valid domain after domain with single dot ('.') value.
|
||||
Pass Empty domain treated as host cookie 1
|
||||
Pass Empty domain treated as host cookie 2
|
||||
Pass Empty domain treated as host cookie 3
|
||||
Pass No host cookies returned for host cookies after non-host redirect 1
|
||||
Pass No host cookies returned for host cookies after non-host redirect 2
|
||||
Pass No host cookies returned for host cookies after non-host redirect 3
|
||||
0
Tests/LibWeb/Text/input/wpt-import/cookies/__init__.py
Normal file
0
Tests/LibWeb/Text/input/wpt-import/cookies/__init__.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Test cookie domain attribute parsing</title>
|
||||
<meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.3">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
const port = "{{ports[http][0]}}";
|
||||
const wwwHost = "{{domains[www]}}";
|
||||
|
||||
test(t => {
|
||||
const win = window.open(`http://${wwwHost}:${port}/cookies/attributes/resources/domain-child.sub.html`);
|
||||
fetch_tests_from_window(win);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,401 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Test cookie domain attribute parsing</title>
|
||||
<meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.3">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testdriver.js"></script>
|
||||
<script src="../../../resources/testdriver-vendor.js"></script>
|
||||
<script src="../../../cookies/resources/cookie-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
const path = "path=/cookies/attributes"
|
||||
const port = "{{ports[http][0]}}";
|
||||
const host = "{{host}}"; // example.org
|
||||
const wwwHost = "{{domains[www]}}"; // home.example.org
|
||||
const www1Host = "{{domains[www1]}}"; // sibling.example.org
|
||||
const www2wwwHost = "{{domains[www2.www]}}"; // subdomain.home.example.org
|
||||
|
||||
// naive helper method to return the TLD for a given domain
|
||||
const getTLD = domain => {
|
||||
let match = /\.[a-z]+$/.exec(domain);
|
||||
if (match) {
|
||||
return match[0];
|
||||
} else {
|
||||
throw 'Domain is malformed!';
|
||||
}
|
||||
}
|
||||
|
||||
// helper to take a domain like "www.example.org"
|
||||
// and return a string like "www.eXaMpLe.org"
|
||||
const makeBizarre = domain => {
|
||||
let bizarre = "";
|
||||
let domainArray = domain.split(".");
|
||||
let secondLevel = domainArray[domainArray.length - 2];
|
||||
for (let i in secondLevel) {
|
||||
if (i % 2 == 1) {
|
||||
bizarre += secondLevel[i].toUpperCase();
|
||||
} else {
|
||||
bizarre += secondLevel[i];
|
||||
}
|
||||
}
|
||||
domainArray[domainArray.length - 2] = bizarre;
|
||||
return domainArray.join(".");
|
||||
}
|
||||
|
||||
// helper to change the current TLD to a TLD that doesn't exist, and is
|
||||
// unlikely to exist in the future. (the main point is that the TLD
|
||||
// *changes*, so there is no domain match, but we cant' predict how WPT
|
||||
// servers may be set up in the wild so picking any valid TLD has the risk
|
||||
// of future (unintentional) domain matching.
|
||||
const changeTLD = domain => {
|
||||
let domainArray = domain.split(".");
|
||||
domainArray[domainArray.length - 1] += "zzz";
|
||||
return domainArray.join(".");
|
||||
}
|
||||
|
||||
const domainTests = [
|
||||
{
|
||||
cookie: `test=1; domain=${wwwHost}`,
|
||||
expected: "test=1",
|
||||
name: "Return cookie for a domain match",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=2; domain=${wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain mismatch (subdomains differ post-redirect)",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=3; domain=.${wwwHost}`,
|
||||
expected: "test=3",
|
||||
name: "Return cookie for a domain match with leading '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=4; domain=${wwwHost}`,
|
||||
expected: "test=4",
|
||||
name: "Return cookie for domain match (domain attribute is suffix of the host name and first level subdomain)",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=5; domain=.${wwwHost}`,
|
||||
expected: "test=5",
|
||||
name: "Return cookie for domain match (domain attribute is suffix of the host name and first level subdomain, with leading '.')",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=6; domain=.${wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain mismatch (subdomains differ, with leading '.')",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=7; domain=${www1Host}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain mismatch when cookie was created (which would match after the redirect, with one subdomain level)",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=8; domain=.${host}`,
|
||||
expected: "test=8",
|
||||
name: "Return cookie for domain match (domain attribute is suffix of the host name, with leading '.')",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=9; domain=${host}`,
|
||||
expected: "test=9",
|
||||
name: "Return cookie for domain match (domain attribute is suffix of the host name)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=10; domain=..${wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with double leading '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=11; domain=www..${host}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with subdomain followed by ..",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=12; domain= .${wwwHost}`,
|
||||
expected: "test=12",
|
||||
name: "Return cookie for a domain match with leading whitespace and '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=13; domain= . ${wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with whitespace that surrounds a leading '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=14; domain=${wwwHost}.`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with trailing '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=15; domain=${wwwHost}..`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with trailing '..'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=16; domain=${wwwHost} .`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with trailing whitespace and '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=17; domain=${getTLD(host)}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with TLD as value",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=18; domain=.${getTLD(host)}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with TLD as value, with leading '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=18b; domain=.${getTLD(host)}.`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute with TLD as value, with leading and trailing '.'",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`testA=19; domain=${wwwHost}`, `testB=19; domain=.${wwwHost}`],
|
||||
expected: "testA=19; testB=19",
|
||||
name: "Return multiple cookies that match on domain (without and with leading '.')",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`testB=20; domain=.${wwwHost}`, `testA=20; domain=${wwwHost}`],
|
||||
expected: "testB=20; testA=20",
|
||||
name: "Return multiple cookies that match on domain (with and without leading '.')",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=21; domain="${wwwHost}"`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute value between quotes",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`testA=22; domain=${wwwHost}`, `testB=22; domain=.${host}`],
|
||||
expected: "testA=22; testB=22",
|
||||
name: "Return multiple cookies that match on subdomain and domain (without and with leading '.')",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`testB=23; domain=.${host}`, `testA=23; domain=${wwwHost}`],
|
||||
expected: "testB=23; testA=23",
|
||||
name: "Return multiple cookies that match on domain and subdomain (with and without leading '.')",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=24; domain=.${host}; domain=${wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned when domain attribute does not domain-match (and first does)",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=25; domain=${wwwHost}; domain=.${host}`,
|
||||
expected: "test=25",
|
||||
name: "Return cookie for domain attribute match (first does not, but second does)",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=26; domain=${makeBizarre(wwwHost)}`,
|
||||
expected: "test=26",
|
||||
name: "Return cookie for domain match (with bizarre capitalization for domain attribute value)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=27; domain="${wwwHost}:${port}"`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute value with port",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=28; domain=${www2wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain mismatch when cookie was created (which would match after the redirect, with two subdomain levels)",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=29`,
|
||||
expected: "",
|
||||
name: "No cookie returned for cookie set on different domain (with no domain attribute)",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: "test=30; domain=",
|
||||
expected: "test=30",
|
||||
name: "Return cookie set with bare domain= attribute",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=31; domain=${wwwHost}`,
|
||||
expected: "test=31",
|
||||
name: "Return cookie that domain-matches with bizarre-cased URL",
|
||||
location: `http://${makeBizarre(wwwHost)}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=32; domain=${wwwHost}; domain=${changeTLD(wwwHost)}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute mismatch (first attribute matches, but second does not)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=33; domain=${changeTLD(wwwHost)}; domain=${wwwHost}`,
|
||||
expected: "test=33",
|
||||
name: "Return cookie for domain match (first attribute doesn't, but second does)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=34; domain=${wwwHost}; domain=${changeTLD(wwwHost)}; domain=${wwwHost}`,
|
||||
expected: "test=34",
|
||||
name: "Return cookie for domain match (first attribute matches, second doesn't, third does)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=35; domain=${changeTLD(wwwHost)}; domain=${wwwHost}; domain=${changeTLD(wwwHost)}`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain attribute mismatch (first attribute doesn't, second does, third doesn't)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=36; domain=${wwwHost}; domain=${wwwHost}`,
|
||||
expected: "test=36",
|
||||
name: "Return cookie for domain match (with two identical domain attributes)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=37; domain=${wwwHost}; domain=${host}`,
|
||||
expected: "test=37",
|
||||
name: "Return cookie for domain match (with first domain attribute a match for host name and second as suffix of host name)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=38; domain=${host}; domain=${wwwHost}`,
|
||||
expected: "test=38",
|
||||
name: "Return cookie for domain match (with first domain attribute as suffix of host name and second a match for host name)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=39; domain=.${www1Host}`,
|
||||
expected: "",
|
||||
name: "No cookie set on domain mismatch before a (domain matching) redirect",
|
||||
location: `http://${www1Host}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=40; domain=.${www2wwwHost}`,
|
||||
expected: "",
|
||||
name: "No cookie set on domain mismatch before a (domain matching) redirect (for second level subdomain)",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=41; domain=${host}; domain=`,
|
||||
expected: "test=41",
|
||||
name: "Return cookie for domain match (with first domain attribute as suffix of host name and second a bare attribute)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=42; domain=${www1Host}; domain=`,
|
||||
expected: "test=42",
|
||||
name: "Cookie returned for bare domain attribute following mismatched domain attribute (after redirect to same-origin page).",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=43; domain=${www1Host}; domain=`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain mismatch (first attribute is a different subdomain and second is bare)",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`test=not44; domain=${wwwHost}`, `test=44; domain=.${wwwHost}`],
|
||||
expected: "test=44",
|
||||
name: "Cookies with same name, path, and domain (differing only in leading '.') overwrite each other ('.' second)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: [`test=not45; domain=.${wwwHost}`, `test=45; domain=${wwwHost}`],
|
||||
expected: "test=45",
|
||||
name: "Cookies with same name, path, and domain (differing only in leading '.') overwrite each other ('.' first)",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=46; domain=.`,
|
||||
expected: "",
|
||||
name: "No cookie returned for domain with single dot ('.') value.",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: `test=46b; domain=.; domain=${host}`,
|
||||
expected: "test=46b",
|
||||
name: "Return cookie with valid domain after domain with single dot ('.') value.",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=47", `test=47b; domain=${host}`,`test=47b; domain=${www1Host}; domain=`],
|
||||
expected: "test=47b; test=47b",
|
||||
name: "Empty domain treated as host cookie 1",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=48", `test=48b; domain=${host}`,`test=48b; domain=${host}; domain=`],
|
||||
expected: "test=48b; test=48b",
|
||||
name: "Empty domain treated as host cookie 2",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=49", `test=49b; domain=${host}`,`test=49b; domain=`],
|
||||
expected: "test=49b; test=49b",
|
||||
name: "Empty domain treated as host cookie 3",
|
||||
location: `http://${wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=50", `test=50b; domain=${host}`,`test=50b; domain=${www1Host}; domain=`],
|
||||
expected: "test=50b",
|
||||
name: "No host cookies returned for host cookies after non-host redirect 1",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=51", `test=51b; domain=${host}`,`test=51b; domain=${host}; domain=`],
|
||||
expected: "test=51b",
|
||||
name: "No host cookies returned for host cookies after non-host redirect 2",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
{
|
||||
cookie: ["test=52", `test=52b; domain=${host}`,`test=52b; domain=`],
|
||||
expected: "test=52b",
|
||||
name: "No host cookies returned for host cookies after non-host redirect 3",
|
||||
location: `http://${www2wwwHost}:${port}/cookies/attributes/resources/path.html`,
|
||||
},
|
||||
];
|
||||
|
||||
for (const test of domainTests) {
|
||||
if (Array.isArray(test.cookie)) {
|
||||
for (let i in test.cookie) {
|
||||
test.cookie[i] += `; ${path}`;
|
||||
}
|
||||
} else {
|
||||
test.cookie += `; ${path}`;
|
||||
}
|
||||
|
||||
httpRedirectCookieTest(test.cookie, test.expected, test.name,
|
||||
test.location);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Note: this function has a dependency on testdriver.js. Any test files calling
|
||||
// it should include testdriver.js and testdriver-vendor.js
|
||||
window.addEventListener("message", (e) => {
|
||||
setTestContextUsingRootWindow();
|
||||
if (e.data == "getAndExpireCookiesForRedirectTest") {
|
||||
const cookies = document.cookie;
|
||||
test_driver.delete_all_cookies().then(() => {
|
||||
e.source.postMessage({"cookies": cookies}, '*');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>helper iframe for matching cookie path redirect tests</title>
|
||||
<meta name=help href="http://tools.ietf.org/html/rfc6265#section-5.1.4">
|
||||
</head>
|
||||
<body>
|
||||
<script src="../../../resources/testdriver.js"></script>
|
||||
<script src="../../../resources/testdriver-vendor.js"></script>
|
||||
<script src="../../../cookies/resources/cookie-test.js"></script>
|
||||
<script src="../../../cookies/attributes/resources/path-redirect-shared.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
Access-Control-Allow-Origin: *
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
// getAndExpireCookiesForDefaultPathTest is a helper method to get and delete
|
||||
// cookies using echo-cookie.html.
|
||||
async function getAndExpireCookiesForDefaultPathTest() {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.style = 'display: none';
|
||||
iframe.addEventListener('load', (e) => {
|
||||
const win = e.target.contentWindow;
|
||||
const iframeCookies = win.getCookies();
|
||||
win.expireCookies().then(() => {
|
||||
document.documentElement.removeChild(iframe);
|
||||
resolve(iframeCookies);
|
||||
});
|
||||
}, {once: true});
|
||||
iframe.src = '/cookies/resources/echo-cookie.html';
|
||||
document.documentElement.appendChild(iframe);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// getAndExpireCookiesForRedirectTest is a helper method to get and delete
|
||||
// cookies that were set from a Location header redirect.
|
||||
async function getAndExpireCookiesForRedirectTest(location) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.style = 'display: none';
|
||||
const listener = (e) => {
|
||||
if (typeof e.data == 'object' && 'cookies' in e.data) {
|
||||
window.removeEventListener('message', listener);
|
||||
document.documentElement.removeChild(iframe);
|
||||
resolve(e.data.cookies);
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', listener);
|
||||
iframe.addEventListener('load', (e) => {
|
||||
e.target.contentWindow.postMessage('getAndExpireCookiesForRedirectTest', '*');
|
||||
}, {once: true});
|
||||
iframe.src = location;
|
||||
document.documentElement.appendChild(iframe);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// httpCookieTest sets a `cookie` (via HTTP), then asserts it was or was not set
|
||||
// via `expectedValue` (via the DOM). Then cleans it up (via test driver). Most
|
||||
// tests do not set a Path attribute, so `defaultPath` defaults to true. If the
|
||||
// cookie values are expected to cause the HTTP request or response to fail, the
|
||||
// test can be made to pass when this happens via `allowFetchFailure`, which
|
||||
// defaults to false.
|
||||
//
|
||||
// `cookie` may be a single cookie string, or an array of cookie strings, where
|
||||
// the order of the array items represents the order of the Set-Cookie headers
|
||||
// sent by the server.
|
||||
//
|
||||
// Note: this function has a dependency on testdriver.js. Any test files calling
|
||||
// it should include testdriver.js and testdriver-vendor.js
|
||||
function httpCookieTest(cookie, expectedValue, name, defaultPath = true,
|
||||
allowFetchFailure = false) {
|
||||
return promise_test((t) => {
|
||||
var skipAssertions = false;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// The result is ignored as we're expiring cookies for cleaning here.
|
||||
await getAndExpireCookiesForDefaultPathTest();
|
||||
await test_driver.delete_all_cookies();
|
||||
t.add_cleanup(test_driver.delete_all_cookies);
|
||||
|
||||
let encodedCookie = encodeURIComponent(JSON.stringify(cookie));
|
||||
try {
|
||||
await fetch(`/cookies/resources/cookie.py?set=${encodedCookie}`);
|
||||
} catch {
|
||||
if (allowFetchFailure) {
|
||||
skipAssertions = true;
|
||||
} else {
|
||||
reject('Failed to fetch /cookies/resources/cookie.py');
|
||||
}
|
||||
}
|
||||
let cookies = document.cookie;
|
||||
if (defaultPath) {
|
||||
// for the tests where a Path is set from the request-uri
|
||||
// path, we need to go look for cookies in an iframe at that
|
||||
// default path.
|
||||
cookies = await getAndExpireCookiesForDefaultPathTest();
|
||||
}
|
||||
resolve(cookies);
|
||||
}).then((cookies) => {
|
||||
if (skipAssertions) {
|
||||
return;
|
||||
}
|
||||
if (Boolean(expectedValue)) {
|
||||
assert_equals(cookies, expectedValue, 'The cookie was set as expected.');
|
||||
} else {
|
||||
assert_equals(cookies, expectedValue, 'The cookie was rejected.');
|
||||
}
|
||||
});
|
||||
}, name);
|
||||
}
|
||||
|
||||
// This is a variation on httpCookieTest, where a redirect happens via
|
||||
// the Location header and we check to see if cookies are sent via
|
||||
// getRedirectedCookies
|
||||
//
|
||||
// Note: the locations targeted by this function have a dependency on
|
||||
// path-redirect-shared.js and should be sure to include it.
|
||||
function httpRedirectCookieTest(cookie, expectedValue, name, location) {
|
||||
return promise_test(async (t) => {
|
||||
// The result is ignored as we're expiring cookies for cleaning here.
|
||||
await getAndExpireCookiesForRedirectTest(location);
|
||||
|
||||
const encodedCookie = encodeURIComponent(JSON.stringify(cookie));
|
||||
const encodedLocation = encodeURIComponent(location);
|
||||
const setParams = `?set=${encodedCookie}&location=${encodedLocation}`;
|
||||
await fetch(`/cookies/resources/cookie.py${setParams}`);
|
||||
// for the tests where a redirect happens, we need to head
|
||||
// to that URI to get the cookies (and then delete them there)
|
||||
const cookies = await getAndExpireCookiesForRedirectTest(location);
|
||||
if (Boolean(expectedValue)) {
|
||||
assert_equals(cookies, expectedValue, 'The cookie was set as expected.');
|
||||
} else {
|
||||
assert_equals(cookies, expectedValue, 'The cookie was rejected.');
|
||||
}
|
||||
}, name);
|
||||
}
|
||||
|
||||
// Sets a `cookie` via the DOM, checks it against `expectedValue` via the DOM,
|
||||
// then cleans it up via the DOM. This is needed in cases where going through
|
||||
// HTTP headers may modify the cookie line (e.g. by stripping control
|
||||
// characters).
|
||||
//
|
||||
// Note: this function has a dependency on testdriver.js. Any test files calling
|
||||
// it should include testdriver.js and testdriver-vendor.js
|
||||
function domCookieTest(cookie, expectedValue, name) {
|
||||
return promise_test(async (t) => {
|
||||
await test_driver.delete_all_cookies();
|
||||
t.add_cleanup(test_driver.delete_all_cookies);
|
||||
|
||||
if (typeof cookie === "string") {
|
||||
document.cookie = cookie;
|
||||
} else if (Array.isArray(cookie)) {
|
||||
for (const singlecookie of cookie) {
|
||||
document.cookie = singlecookie;
|
||||
}
|
||||
} else {
|
||||
throw new Error('Unexpected type passed into domCookieTest as cookie: ' + typeof cookie);
|
||||
}
|
||||
let cookies = document.cookie;
|
||||
assert_equals(cookies, expectedValue, Boolean(expectedValue) ?
|
||||
'The cookie was set as expected.' :
|
||||
'The cookie was rejected.');
|
||||
}, name);
|
||||
}
|
||||
|
||||
// Returns an array of control characters along with their ASCII codes. Control
|
||||
// characters are defined by RFC 5234 to be %x00-1F / %x7F.
|
||||
function getCtlCharacters() {
|
||||
const ctlCodes = [...Array(0x20).keys()]
|
||||
.concat([0x7F]);
|
||||
return ctlCodes.map(i => ({ code: i, chr: String.fromCharCode(i) }))
|
||||
}
|
||||
|
||||
// Returns a cookie string with name set to "t" * nameLength and value
|
||||
// set to "1" * valueLength. Passing in 0 for either allows for creating
|
||||
// a name- or value-less cookie.
|
||||
//
|
||||
// Note: Cookie length checking should ignore the "=".
|
||||
function cookieStringWithNameAndValueLengths(nameLength, valueLength) {
|
||||
return `${"t".repeat(nameLength)}=${"1".repeat(valueLength)}`;
|
||||
}
|
||||
|
||||
// Finds the root window.top.opener and directs test_driver commands to it.
|
||||
//
|
||||
// If you see a message like: "Error: Tried to run in a non-testharness window
|
||||
// without a call to set_test_context." then you probably need to call this.
|
||||
function setTestContextUsingRootWindow() {
|
||||
let test_window = window.top;
|
||||
while (test_window.opener && !test_window.opener.closed) {
|
||||
test_window = test_window.opener.top;
|
||||
}
|
||||
test_driver.set_test_context(test_window);
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import json
|
||||
|
||||
from cookies.resources.helpers import setNoCacheAndCORSHeaders
|
||||
from wptserve.utils import isomorphic_decode
|
||||
from wptserve.utils import isomorphic_encode
|
||||
|
||||
def set_cookie(headers, cookie_string):
|
||||
"""Helper method to add a Set-Cookie header"""
|
||||
headers.append((b'Set-Cookie', isomorphic_encode(cookie_string)))
|
||||
|
||||
def main(request, response):
|
||||
"""Set a cookie via GET params.
|
||||
|
||||
Usage: `/cookie.py?set={cookie}`
|
||||
|
||||
The passed-in cookie string should be stringified via JSON.stringify() (in
|
||||
the case of multiple cookie headers sent in an array) and encoded via
|
||||
encodeURIComponent, otherwise `parse_qsl` will split on any semicolons
|
||||
(used by the Request.GET property getter). Note that values returned by
|
||||
Request.GET will decode any percent-encoded sequences sent in a GET param
|
||||
(which may or may not be surprising depending on what you're doing).
|
||||
|
||||
Note: here we don't use Response.delete_cookie() or similar other methods
|
||||
in this resources directory because there are edge cases that are impossible
|
||||
to express via those APIs, namely a bare (`Path`) or empty Path (`Path=`)
|
||||
attribute. Instead, we pipe through the entire cookie and append `max-age=0`
|
||||
to it.
|
||||
"""
|
||||
headers = setNoCacheAndCORSHeaders(request, response)
|
||||
|
||||
if b'set' in request.GET:
|
||||
cookie = isomorphic_decode(request.GET[b'set'])
|
||||
cookie = json.loads(cookie)
|
||||
cookies = cookie if isinstance(cookie, list) else [cookie]
|
||||
for c in cookies:
|
||||
set_cookie(headers, c)
|
||||
|
||||
if b'location' in request.GET:
|
||||
headers.append((b'Location', request.GET[b'location']))
|
||||
return 302, headers, b'{"redirect": true}'
|
||||
|
||||
return headers, b'{"success": true}'
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>helper iframe for matching cookie path tests</title>
|
||||
<meta name=help href="http://tools.ietf.org/html/rfc6265#section-5.1.4">
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/cookies/resources/cookie-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.setCookie = function (name, path) {
|
||||
document.cookie = name + '=1; Path=' + path + ';';
|
||||
};
|
||||
window.fetchCookieThen = function (name, path) {
|
||||
return fetch("/cookies/resources/set-cookie.py?name=" + encodeURIComponent(name) + "&path=" + encodeURIComponent(path), {'credentials': 'include'});
|
||||
};
|
||||
window.isCookieSet = function (name, path) {
|
||||
return document.cookie.match(name + '=1');
|
||||
};
|
||||
// Note: this function has a dependency on testdriver.js. Any test files calling
|
||||
// it should include testdriver.js and testdriver-vendor.js
|
||||
window.expireCookies = async () => {
|
||||
setTestContextUsingRootWindow();
|
||||
await test_driver.delete_all_cookies();
|
||||
};
|
||||
window.getCookies = () => document.cookie;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
from urllib.parse import parse_qs
|
||||
|
||||
from wptserve.utils import isomorphic_encode
|
||||
|
||||
def setNoCacheAndCORSHeaders(request, response):
|
||||
"""Set Cache-Control, CORS and Content-Type headers appropriate for the cookie tests."""
|
||||
headers = [(b"Content-Type", b"application/json"),
|
||||
(b"Access-Control-Allow-Credentials", b"true")]
|
||||
|
||||
origin = b"*"
|
||||
if b"origin" in request.headers:
|
||||
origin = request.headers[b"origin"]
|
||||
|
||||
headers.append((b"Access-Control-Allow-Origin", origin))
|
||||
#headers.append(("Access-Control-Allow-Credentials", "true"))
|
||||
headers.append((b"Cache-Control", b"no-cache"))
|
||||
headers.append((b"Expires", b"Fri, 01 Jan 1990 00:00:00 GMT"))
|
||||
|
||||
return headers
|
||||
|
||||
def makeCookieHeader(name, value, otherAttrs):
|
||||
"""Make a Set-Cookie header for a cookie with the name, value and attributes provided."""
|
||||
def makeAV(a, v):
|
||||
if None == v or b"" == v:
|
||||
return a
|
||||
if isinstance(v, int):
|
||||
return b"%s=%i" % (a, v)
|
||||
else:
|
||||
return b"%s=%s" % (a, v)
|
||||
|
||||
# ensure cookie name is always first
|
||||
attrs = [b"%s=%s" % (name, value)]
|
||||
attrs.extend(makeAV(a, v) for (a, v) in otherAttrs.items())
|
||||
return (b"Set-Cookie", b"; ".join((attrs)))
|
||||
|
||||
def makeDropCookie(name, secure):
|
||||
attrs = {b"max-age": 0, b"path": b"/"}
|
||||
if secure:
|
||||
attrs[b"secure"] = b""
|
||||
return makeCookieHeader(name, b"", attrs)
|
||||
|
||||
def readParameter(request, paramName, requireValue):
|
||||
"""Read a parameter from the request. Raise if requireValue is set and the
|
||||
parameter has an empty value or is not present."""
|
||||
params = parse_qs(request.url_parts.query)
|
||||
param = params[paramName][0].strip()
|
||||
if len(param) == 0:
|
||||
raise Exception(u"Empty or missing name parameter.")
|
||||
return isomorphic_encode(param)
|
||||
|
||||
def readCookies(request):
|
||||
"""Read the cookies from the client present in the request."""
|
||||
cookies = {}
|
||||
for key in request.cookies:
|
||||
for cookie in request.cookies.get_list(key):
|
||||
# do we care we'll clobber cookies here? If so, do we
|
||||
# need to modify the test to take cookie names and value lists?
|
||||
cookies[key] = cookie.value
|
||||
return cookies
|
||||
Loading…
Reference in a new issue