188 lines
5.5 KiB
JavaScript
188 lines
5.5 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const { CookieXPCShellUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/CookieXPCShellUtils.sys.mjs"
|
|
);
|
|
|
|
let gHints = 0;
|
|
|
|
CookieXPCShellUtils.init(this);
|
|
|
|
function countMatchingCacheEntries(cacheEntries, domain, path) {
|
|
return cacheEntries
|
|
.map(entry => entry.uri.asciiSpec)
|
|
.filter(spec => spec.includes(domain))
|
|
.filter(spec => spec.includes(path)).length;
|
|
}
|
|
|
|
async function checkCache(originAttributes) {
|
|
const loadContextInfo = Services.loadContextInfo.custom(
|
|
false,
|
|
originAttributes
|
|
);
|
|
|
|
const data = await new Promise(resolve => {
|
|
let cacheEntries = [];
|
|
let cacheVisitor = {
|
|
onCacheStorageInfo() {},
|
|
onCacheEntryInfo(uri, idEnhance) {
|
|
cacheEntries.push({ uri, idEnhance });
|
|
},
|
|
onCacheEntryVisitCompleted() {
|
|
resolve(cacheEntries);
|
|
},
|
|
QueryInterface: ChromeUtils.generateQI(["nsICacheStorageVisitor"]),
|
|
};
|
|
// Visiting the disk cache also visits memory storage so we do not
|
|
// need to use Services.cache2.memoryCacheStorage() here.
|
|
let storage = Services.cache2.diskCacheStorage(loadContextInfo);
|
|
storage.asyncVisitStorage(cacheVisitor, true);
|
|
});
|
|
|
|
let foundEntryCount = countMatchingCacheEntries(
|
|
data,
|
|
"example.org",
|
|
"style.css"
|
|
);
|
|
Assert.greater(
|
|
foundEntryCount,
|
|
0,
|
|
`Cache entries expected for style.css and OA=${originAttributes}`
|
|
);
|
|
}
|
|
|
|
add_task(async () => {
|
|
do_get_profile();
|
|
|
|
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
|
|
|
|
const server = CookieXPCShellUtils.createServer({
|
|
hosts: ["example.org", "foo.com"],
|
|
});
|
|
|
|
server.registerPathHandler("/empty", (metadata, response) => {
|
|
var body = "<h1>Hello!</h1>";
|
|
response.bodyOutputStream.write(body, body.length);
|
|
});
|
|
|
|
server.registerPathHandler("/style.css", (metadata, response) => {
|
|
gHints++;
|
|
response.setHeader("Cache-Control", "max-age=10000", false);
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
|
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
|
var body = "* { color: red }";
|
|
response.bodyOutputStream.write(body, body.length);
|
|
});
|
|
|
|
server.registerPathHandler("/preload", (metadata, response) => {
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
|
response.setHeader("Content-Type", "text/html", false);
|
|
var body = `<html><head></head><body><script>
|
|
const link = document.createElement("link")
|
|
link.setAttribute("rel", "preload");
|
|
link.setAttribute("as", "style");
|
|
link.setAttribute("href", "http://example.org/style.css");
|
|
document.head.appendChild(link);
|
|
link.onload = () => {
|
|
fetch("/done").then(() => {});
|
|
};
|
|
</script></body></html>`;
|
|
response.bodyOutputStream.write(body, body.length);
|
|
});
|
|
|
|
const tests = [
|
|
{
|
|
// 2 hints because we have 2 different top-level origins, loading the
|
|
// same resource. This will end up creating 2 separate cache entries.
|
|
hints: 2,
|
|
prefValue: true,
|
|
originAttributes: { partitionKey: "(http,example.org)" },
|
|
},
|
|
{
|
|
// 1 hint because, with network-state isolation, the cache entry will be
|
|
// reused for the second loading, even if the top-level origins are
|
|
// different.
|
|
hints: 1,
|
|
originAttributes: {},
|
|
prefValue: false,
|
|
},
|
|
];
|
|
|
|
for (let test of tests) {
|
|
await new Promise(resolve =>
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve)
|
|
);
|
|
|
|
info("Reset the shared sheets");
|
|
let contentPage = await CookieXPCShellUtils.loadContentPage(
|
|
"http://example.org/empty"
|
|
);
|
|
|
|
await contentPage.spawn([], () => {
|
|
ChromeUtils.clearResourceCache({
|
|
types: ["stylesheet", "script"],
|
|
});
|
|
});
|
|
|
|
await contentPage.close();
|
|
|
|
info("Reset the counter");
|
|
gHints = 0;
|
|
|
|
info("Enabling network state partitioning");
|
|
Services.prefs.setBoolPref(
|
|
"privacy.partition.network_state",
|
|
test.prefValue
|
|
);
|
|
|
|
let complete = new Promise(resolve => {
|
|
server.registerPathHandler("/done", (metadata, response) => {
|
|
response.setHeader("Cache-Control", "max-age=10000", false);
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
|
response.setHeader("Content-Type", "text/html", false);
|
|
var body = "OK";
|
|
response.bodyOutputStream.write(body, body.length);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
info("Let's load a page with origin A");
|
|
contentPage = await CookieXPCShellUtils.loadContentPage(
|
|
"http://example.org/preload"
|
|
);
|
|
|
|
await complete;
|
|
await checkCache(test.originAttributes);
|
|
await contentPage.close();
|
|
|
|
complete = new Promise(resolve => {
|
|
server.registerPathHandler("/done", (metadata, response) => {
|
|
response.setHeader("Cache-Control", "max-age=10000", false);
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
|
response.setHeader("Content-Type", "text/html", false);
|
|
var body = "OK";
|
|
response.bodyOutputStream.write(body, body.length);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
info("Let's load a page with origin B");
|
|
contentPage = await CookieXPCShellUtils.loadContentPage(
|
|
"http://foo.com/preload"
|
|
);
|
|
|
|
await complete;
|
|
await checkCache(test.originAttributes);
|
|
await contentPage.close();
|
|
|
|
Assert.equal(
|
|
gHints,
|
|
test.hints,
|
|
"We have the current number of requests with pref " + test.prefValue
|
|
);
|
|
}
|
|
});
|