Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
const { SiteDataTestUtils } = ChromeUtils.importESModule(
);
const COOKIE = {
host: "example.com",
name: "test_cookie",
path: "/",
};
const COOKIE_NET = {
host: "example.net",
name: "test_cookie",
path: "/",
};
const COOKIE_ORG = {
host: "example.org",
name: "test_cookie",
path: "/",
};
let since, oldCookie;
function addCookie(cookie) {
Services.cookies.add(
cookie.host,
cookie.path,
cookie.name,
"test",
false,
false,
false,
Date.now() / 1000 + 10000,
{},
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
ok(
Services.cookies.cookieExists(cookie.host, cookie.path, cookie.name, {}),
`Cookie ${cookie.name} was created.`
);
}
async function setUpCookies() {
Services.cookies.removeAll();
// Add a cookie which will end up with an older creationTime.
oldCookie = Object.assign({}, COOKIE, { name: Date.now() });
addCookie(oldCookie);
await new Promise(resolve => setTimeout(resolve, 10));
since = Date.now();
await new Promise(resolve => setTimeout(resolve, 10));
// Add a cookie which will end up with a more recent creationTime.
addCookie(COOKIE);
// Add cookies for different domains.
addCookie(COOKIE_NET);
addCookie(COOKIE_ORG);
}
async function setUpCache() {
Services.cache2.clear();
// Add cache entries for different domains.
for (const domain of ["example.net", "example.org", "example.com"]) {
await SiteDataTestUtils.addCacheEntry(`http://${domain}/`, "disk");
await SiteDataTestUtils.addCacheEntry(`http://${domain}/`, "memory");
}
}
function hasCacheEntry(domain) {
const disk = SiteDataTestUtils.hasCacheEntry(`http://${domain}/`, "disk");
const memory = SiteDataTestUtils.hasCacheEntry(`http://${domain}/`, "memory");
equal(
disk,
memory,
`For ${domain} either either both or neither caches need to exists.`
);
return disk;
}
add_task(async function testCache() {
function background() {
browser.test.onMessage.addListener(async msg => {
if (msg == "removeCache") {
await browser.browsingData.removeCache({});
} else {
await browser.browsingData.remove({}, { cache: true });
}
browser.test.sendMessage("cacheRemoved");
});
}
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["browsingData"],
},
});
async function testRemovalMethod(method) {
await setUpCache();
extension.sendMessage(method);
await extension.awaitMessage("cacheRemoved");
ok(!hasCacheEntry("example.net"), "example.net cache was removed");
ok(!hasCacheEntry("example.org"), "example.org cache was removed");
ok(!hasCacheEntry("example.com"), "example.com cache was removed");
}
await extension.startup();
await testRemovalMethod("removeCache");
await testRemovalMethod("remove");
await extension.unload();
});
add_task(async function testCookies() {
// Above in setUpCookies we create an 'old' cookies, wait 10ms, then log a timestamp.
// Here we ask the browser to delete all cookies after the timestamp, with the intention
// that the 'old' cookie is not removed. The issue arises when the timer precision is
// low enough such that the timestamp that gets logged is the same as the 'old' cookie.
// We hardcode a precision value to ensure that there is time between the 'old' cookie
// and the timestamp generation.
Services.prefs.setBoolPref("privacy.reduceTimerPrecision", true);
Services.prefs.setIntPref(
"privacy.resistFingerprinting.reduceTimerPrecision.microseconds",
2000
);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("privacy.reduceTimerPrecision");
Services.prefs.clearUserPref(
"privacy.resistFingerprinting.reduceTimerPrecision.microseconds"
);
});
function background() {
browser.test.onMessage.addListener(async (msg, options) => {
if (msg == "removeCookies") {
await browser.browsingData.removeCookies(options);
} else {
await browser.browsingData.remove(options, { cookies: true });
}
browser.test.sendMessage("cookiesRemoved");
});
}
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["browsingData"],
},
});
async function testRemovalMethod(method) {
// Clear cookies with a recent since value.
await setUpCookies();
extension.sendMessage(method, { since });
await extension.awaitMessage("cookiesRemoved");
ok(
Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
"Old cookie was not removed."
);
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
"Recent cookie was removed."
);
// Clear cookies with an old since value.
await setUpCookies();
addCookie(COOKIE);
extension.sendMessage(method, { since: since - 100000 });
await extension.awaitMessage("cookiesRemoved");
ok(
!Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
"Old cookie was removed."
);
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
"Recent cookie was removed."
);
// Clear cookies with no since value and valid originTypes.
await setUpCookies();
extension.sendMessage(method, {
originTypes: { unprotectedWeb: true, protectedWeb: false },
});
await extension.awaitMessage("cookiesRemoved");
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
`Cookie ${COOKIE.name} was removed.`
);
ok(
!Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
`Cookie ${oldCookie.name} was removed.`
);
}
await extension.startup();
await testRemovalMethod("removeCookies");
await testRemovalMethod("remove");
await extension.unload();
});
add_task(async function testCacheAndCookies() {
function background() {
browser.test.onMessage.addListener(async options => {
await browser.browsingData.remove(options, {
cache: true,
cookies: true,
});
browser.test.sendMessage("cacheAndCookiesRemoved");
});
}
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["browsingData"],
},
});
await extension.startup();
// Clear cache and cookies with a recent since value.
await setUpCookies();
await setUpCache();
extension.sendMessage({ since });
await extension.awaitMessage("cacheAndCookiesRemoved");
ok(
Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
"Old cookie was not removed."
);
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
"Recent cookie was removed."
);
// Cache does not support |since| and deletes everything!
ok(!hasCacheEntry("example.net"), "example.net cache was removed");
ok(!hasCacheEntry("example.org"), "example.org cache was removed");
ok(!hasCacheEntry("example.com"), "example.com cache was removed");
// Clear cache and cookies with an old since value.
await setUpCookies();
await setUpCache();
extension.sendMessage({ since: since - 100000 });
await extension.awaitMessage("cacheAndCookiesRemoved");
// Cache does not support |since| and deletes everything!
ok(!hasCacheEntry("example.net"), "example.net cache was removed");
ok(!hasCacheEntry("example.org"), "example.org cache was removed");
ok(!hasCacheEntry("example.com"), "example.com cache was removed");
ok(
!Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
"Old cookie was removed."
);
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
"Recent cookie was removed."
);
// Clear cache and cookies with hostnames value.
await setUpCookies();
await setUpCache();
extension.sendMessage({
hostnames: ["example.net", "example.org", "unknown.com"],
});
await extension.awaitMessage("cacheAndCookiesRemoved");
ok(
Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
`Cookie ${COOKIE.name} was not removed.`
);
ok(
!Services.cookies.cookieExists(
COOKIE_NET.host,
COOKIE_NET.path,
COOKIE_NET.name,
{}
),
`Cookie ${COOKIE_NET.name} was removed.`
);
ok(
!Services.cookies.cookieExists(
COOKIE_ORG.host,
COOKIE_ORG.path,
COOKIE_ORG.name,
{}
),
`Cookie ${COOKIE_ORG.name} was removed.`
);
ok(!hasCacheEntry("example.net"), "example.net cache was removed");
ok(!hasCacheEntry("example.org"), "example.org cache was removed");
ok(hasCacheEntry("example.com"), "example.com cache was not removed");
// Clear cache and cookies with (empty) hostnames value.
await setUpCookies();
await setUpCache();
extension.sendMessage({ hostnames: [] });
await extension.awaitMessage("cacheAndCookiesRemoved");
ok(
Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
`Cookie ${COOKIE.name} was not removed.`
);
ok(
Services.cookies.cookieExists(
COOKIE_NET.host,
COOKIE_NET.path,
COOKIE_NET.name,
{}
),
`Cookie ${COOKIE_NET.name} was not removed.`
);
ok(
Services.cookies.cookieExists(
COOKIE_ORG.host,
COOKIE_ORG.path,
COOKIE_ORG.name,
{}
),
`Cookie ${COOKIE_ORG.name} was not removed.`
);
ok(hasCacheEntry("example.net"), "example.net cache was not removed");
ok(hasCacheEntry("example.org"), "example.org cache was not removed");
ok(hasCacheEntry("example.com"), "example.com cache was not removed");
// Clear cache and cookies with both hostnames and since values.
await setUpCache();
await setUpCookies();
extension.sendMessage({ hostnames: ["example.com"], since });
await extension.awaitMessage("cacheAndCookiesRemoved");
ok(
Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
"Old cookie was not removed."
);
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
"Recent cookie was removed."
);
ok(
Services.cookies.cookieExists(
COOKIE_NET.host,
COOKIE_NET.path,
COOKIE_NET.name,
{}
),
"Cookie with different hostname was not removed"
);
ok(
Services.cookies.cookieExists(
COOKIE_ORG.host,
COOKIE_ORG.path,
COOKIE_ORG.name,
{}
),
"Cookie with different hostname was not removed"
);
ok(hasCacheEntry("example.net"), "example.net cache was not removed");
ok(hasCacheEntry("example.org"), "example.org cache was not removed");
ok(!hasCacheEntry("example.com"), "example.com cache was removed");
// Clear cache and cookies with no since or hostnames value.
await setUpCache();
await setUpCookies();
extension.sendMessage({});
await extension.awaitMessage("cacheAndCookiesRemoved");
ok(
!Services.cookies.cookieExists(COOKIE.host, COOKIE.path, COOKIE.name, {}),
`Cookie ${COOKIE.name} was removed.`
);
ok(
!Services.cookies.cookieExists(
oldCookie.host,
oldCookie.path,
oldCookie.name,
{}
),
`Cookie ${oldCookie.name} was removed.`
);
ok(
!Services.cookies.cookieExists(
COOKIE_NET.host,
COOKIE_NET.path,
COOKIE_NET.name,
{}
),
`Cookie ${COOKIE_NET.name} was removed.`
);
ok(
!Services.cookies.cookieExists(
COOKIE_ORG.host,
COOKIE_ORG.path,
COOKIE_ORG.name,
{}
),
`Cookie ${COOKIE_ORG.name} was removed.`
);
ok(!hasCacheEntry("example.net"), "example.net cache was removed");
ok(!hasCacheEntry("example.org"), "example.org cache was removed");
ok(!hasCacheEntry("example.com"), "example.com cache was removed");
await extension.unload();
});