Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<body>
<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>
<script>
/**
* Constructs a url for an intermediate "bounce" hop which represents a tracker.
* @param {string} cacheHelper - Unique uuid for this test
* @param {*} options - URL generation options.
* @param {boolean} [options.second_origin = true] - whether domain should be a different origin
* @param {boolean} [options.subdomain = false] - whether the domain should start with
* a different subdomain
* @param {boolean} [options.cache = false] - whether the resource should be cacheable
* @param {(null|'cache'|'all')} [options.clear] - whether to send the
* Clear-Site-Data header.
* @param {(null|'cache'|'all')} [options.clear_first] - whether to send the
* Clear-Site-Data header on first response
* @param {*} [options.iframe] - iframe same parameters as options (recursive)
*/
function getUrl(cacheHelper, {
subdomain = false,
secondOrigin = false,
cache = false,
clear = null,
clearFirst = null,
iframe = null,
}) {
let url = "https://";
if (subdomain && secondOrigin) {
url += "{{hosts[alt][www2]}}";
} else if (subdomain) { // && !second_origin
url += "{{hosts[][www2]}}";
} else if (secondOrigin) { // && !subdomain
url += "{{hosts[alt][]}}";
} else { // !second_origin && !subdomain
url += "{{hosts[][]}}";
}
url += ":{{ports[https][1]}}";
url += "/clear-site-data/support/clear-site-data-cache.py";
url = new URL(url);
let params = new URLSearchParams();
params.append("cache_helper", cacheHelper);
params.append("response", "single_html")
if (clear !== null) {
params.append("clear", clear);
}
if (clearFirst != null) {
params.append("clear_first", clearFirst);
}
if (cache) {
params.append("cache", "");
}
if (iframe != null) {
let iframeUrl = getUrl(cacheHelper, iframe);
params.append("iframe", iframeUrl);
}
url.search = params;
return url.toString();
}
/**
* Opens test pages sequentially, compares first and last uuid. Makes sure test cleans up properly
* @param test - test clean up
* @param {string} firstUuid - uuid returned by first url
* @param {array[string]} testUrls - array of all urls that should be visited
* @param {integer} curIdx - index in testUrls that is visited in the current function call
* @param {function assert_not_equal|assert_equal} assert - function that gets passed first and last
* uuid and determines the success of the test case
* @param {function} resolve - function to call when test case is complete
* @param {*} options - URL generation options.
*/
function openTestPageHelper(test, firstUuid, testUrls, curIdx, assert, resolve) {
window.addEventListener("message", test.step_func(e => {
let curUuid = e.data;
if (firstUuid === null) {
firstUuid = curUuid;
}
if (curIdx + 1 < testUrls.length) {
openTestPageHelper(test, firstUuid, testUrls, curIdx + 1, assert, resolve);
} else {
// Last Step
assert(firstUuid, curUuid);
resolve();
}
}), {once: true});
window.open(testUrls[curIdx]);
}
// Here's the set-up for this test: Step 1 and Step 2 are repeated for each param in params
// Step 1 (main window) Open popup window with url generated with `getUrl`
// Step 2 (first window) Message main window with potentially cached uuid and close popup
// Last Step (main window): Assert first and last uuid not equal due to `clear-site-data: "cache"` header
//
// Basic diagram visualizing how the test works:
//
// main window opens sequentially:
// (1) (2) (last) = (1)
// | Step 1 | Step 3 | Step 4
// | | |
// +--------v---------+ +------v----------+ +------v-----------+
// | first / second | | Clear Data? | | |
// | origin | | | | |
// | | | | | |
// | +-iframe-------+ | | +-(iframe?)---+ | ... | +-iframe-------+ |
// | | first/second | | | | Clear Data? | | | | | |
// | | origin | | | | | | | | | |
// | +-----------+--+ | | +-------------+ | | +-+------------+ |
// +-------------+----+ +-----------------+ +---+--------------+
// | |
// | Step 2 +----------------+ Step 5
// | |
// v v
// Last Step: is uuid from (1) different from (last)?
function testCacheClear(test, params, assert) {
if (params.length < 2) {
// fail test case
return new Promise((resolve, reject) => reject());
}
const cacheHelper = self.crypto.randomUUID();
const testUrls = params.map((param) => getUrl(cacheHelper, param));
return new Promise(resolve => {
openTestPageHelper(test, null, testUrls, 0, assert, resolve)
});
}
const CLEAR_ORIGIN_CACHE = {
clear: "cache",
}
promise_test(test => {
const TEST_SITE = {
iframe: {
cache: true,
}
}
return testCacheClear(test, [TEST_SITE, CLEAR_ORIGIN_CACHE, TEST_SITE], assert_not_equals);
}, "same site data also gets cleared in iframe");
promise_test(test => {
const TEST_SITE = {
iframe: {
cache: true,
secondOrigin: true,
}
}
return testCacheClear(test, [TEST_SITE, CLEAR_ORIGIN_CACHE, TEST_SITE], assert_equals);
}, "cross origin iframe data doesn't get cleared");
promise_test(test => {
const TEST_SITE = {
iframe: {
cache: true,
secondOrigin: true,
}
}
return testCacheClear(test, [TEST_SITE, CLEAR_ORIGIN_CACHE, TEST_SITE], assert_equals);
}, "clearing cache doesn't affect cross origin iframe");
promise_test(test => {
const TEST_SITE = {
cache: true,
subdomain: true,
}
return testCacheClear(test, [TEST_SITE, CLEAR_ORIGIN_CACHE, TEST_SITE], assert_equals);
}, "clearing cache doesn't affect subdomain");
promise_test(test => {
const TEST_SITE = {
iframe: {
secondOrigin: true,
cache: true,
}
}
const TEST_SITE_CLEAR_IFRAME = {
iframe: {
secondOrigin: true,
clear: "all",
}
}
return testCacheClear(test, [TEST_SITE, TEST_SITE_CLEAR_IFRAME, TEST_SITE], assert_not_equals);
}, "clear in cross origin iframe clears data from that iframe");
promise_test(test => {
const TEST_SITE = {
cache: true
};
const TEST_SITE_CLEAR_IFRAME = {
secondOrigin: true,
iframe: {
clear: "cache",
}
}
return testCacheClear(test, [TEST_SITE, TEST_SITE_CLEAR_IFRAME, TEST_SITE], assert_equals);
}, "clear in cross origin iframe doesn't clear unpartitioned data from that cross origin");
promise_test(test => {
const TEST_SITE = {
secondOrigin: true,
iframe: {
cache: true,
}
}
const TEST_SITE_CLEAR_IFRAME = {
clear: "cache"
};
return testCacheClear(test, [TEST_SITE, TEST_SITE_CLEAR_IFRAME, TEST_SITE], assert_equals);
}, "clear in unpartitioned context doesn't clear partitioned data");
</script>
</body>
</html>