Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /cookies/prefix/__host.explicit-path.https.window.html - WPT Dashboard Interop Dashboard
// META: title=The "__Host-" prefix requires an explicit Path attribute of "/"
// META: timeout=long
'use strict';
// A "__Host-" prefixed cookie has to have been set with a Path attribute whose
// value is "/". That is not the same as ending up with a path of "/": a cookie
// set without a Path attribute from a URL whose path has a single segment gets a
// default path of "/" as well, and has to be rejected all the same.
//
// Reaching that case needs a document whose URL has a single path segment, so
// that its default cookie path is "/". "/" itself is the only such URL that
// wptserve does not redirect, and a document there is same-origin, so cookies can
// be set and read through it. HTTP is not covered for want of a handler at that
// depth.
//
const NAME_PREFIX = 'explicit-path-';
// A document whose default cookie path is "/".
function loadRootDocument() {
return new Promise(resolve => {
const iframe = document.createElement('iframe');
iframe.style = 'display: none';
iframe.addEventListener('load', () => resolve(iframe), {once: true});
iframe.src = '/';
document.body.appendChild(iframe);
});
}
function cookieValue(cookieString, name) {
for (const pair of cookieString.split('; ')) {
const index = pair.indexOf('=');
if (index !== -1 && pair.substring(0, index) === name) {
return pair.substring(index + 1);
}
}
return null;
}
// A "__Host-" prefixed cookie can only be expired by a Set-Cookie that satisfies
// the prefix itself, so the cleanup below carries Secure and Path=/ too.
function rootDocumentTest({name, suffix, attributes, stored}) {
const cookieName = `__Host-${NAME_PREFIX}${suffix}`;
promise_test(async t => {
t.add_cleanup(() => {
document.cookie = `${cookieName}=; Secure; Path=/; Max-Age=0`;
});
const iframe = await loadRootDocument();
t.add_cleanup(() => iframe.remove());
const doc = iframe.contentWindow.document;
assert_equals(iframe.contentWindow.location.pathname, '/',
'The document has a single path segment');
doc.cookie = `${cookieName}=1; ${attributes}`;
assert_equals(cookieValue(doc.cookie, cookieName), stored ? '1' : null);
}, name);
}
// Establishes the premise: a cookie set from this document without a Path
// attribute has a default path of "/", so it reaches a path outside this test's
// own directory.
promise_test(async t => {
const cookieName = `${NAME_PREFIX}defaultpath`;
t.add_cleanup(() => {
document.cookie = `${cookieName}=; Path=/; Max-Age=0`;
});
const root = await loadRootDocument();
t.add_cleanup(() => root.remove());
root.contentWindow.document.cookie = `${cookieName}=1`;
const elsewhere = await new Promise(resolve => {
const iframe = document.createElement('iframe');
iframe.style = 'display: none';
iframe.addEventListener('load', () => resolve(iframe), {once: true});
iframe.src = '/common/blank.html';
document.body.appendChild(iframe);
});
t.add_cleanup(() => elsewhere.remove());
assert_equals(
cookieValue(elsewhere.contentWindow.document.cookie, cookieName), '1',
'The cookie reaches /common/blank.html, so its path is "/"');
}, 'CONTROL a cookie set without a Path attribute here has a path of "/"');
// Control: the prefix is honoured when the Path attribute is there.
rootDocumentTest({
name: 'CONTROL "__Host-" with an explicit Path of "/" is set',
suffix: 'withpath',
attributes: 'Secure; Path=/',
stored: true,
});
// The cases under test. Each of these ends up with a path of "/" through the
// default path, without a Path attribute that says so.
rootDocumentTest({
name: '"__Host-" without a Path attribute is not set',
suffix: 'nopath',
attributes: 'Secure',
stored: false,
});
rootDocumentTest({
name: '"__Host-" with an empty Path attribute is not set',
suffix: 'emptypath',
attributes: 'Secure; Path=',
stored: false,
});
rootDocumentTest({
name: '"__Host-" with a valueless Path attribute is not set',
suffix: 'barepath',
attributes: 'Secure; Path',
stored: false,
});