Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- Manifest: netwerk/test/unit/xpcshell.toml
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
"use strict";
// CacheFileIOManager::OnIdleDaily is the fallback that removes cache folders the
// purge background task failed to delete. A single read-only entry makes both
// DeleteFileW and RemoveDirectoryW fail with ACCESS_DENIED, so without forcing
const { TestUtils } = ChromeUtils.importESModule(
);
const RESIDUAL_LEAF = "cache2.2024-01-01-00-00-00.purge.bg_rm";
function clearReadOnlyRecursive(aFile) {
try {
if (aFile.isDirectory()) {
for (let child of aFile.directoryEntries) {
clearReadOnlyRecursive(child);
}
}
aFile.QueryInterface(Ci.nsILocalFileWin).readOnly = false;
} catch (e) {}
}
// subdirectories and three zero-length context eviction files.
function createReadOnlyResidualFolder() {
let dir = do_get_profile();
dir.append(RESIDUAL_LEAF);
dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o744);
let children = [];
for (let sub of ["doomed", "entries"]) {
let d = dir.clone();
d.append(sub);
d.create(Ci.nsIFile.DIRECTORY_TYPE, 0o744);
children.push(d);
}
for (let leaf of [
"ce_Kg==",
"ce_T151c2VyQ29udGV4dElkPTUs",
"ce_T151c2VyQ29udGV4dElkPTUsYSw=",
]) {
let f = dir.clone();
f.append(leaf);
f.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
children.push(f);
}
for (let child of children) {
child.QueryInterface(Ci.nsILocalFileWin).readOnly = true;
}
return dir;
}
add_task(
{ skip_if: () => mozinfo.os != "win" },
async function test_readonly_residual_folder_removed_on_idle_daily() {
do_get_profile();
// OnIdleDaily only sweeps when the cache is cleared at shutdown via the
// background task.
Services.prefs.setBoolPref("privacy.sanitize.sanitizeOnShutdown", true);
Services.prefs.setBoolPref("privacy.clearOnShutdown_v2.cache", true);
Services.prefs.setBoolPref(
"network.cache.shutdown_purge_in_background_task",
true
);
// Write an entry so the disk cache, and therefore mCacheDirectory, exists.
await new Promise(resolve => {
asyncOpenCacheEntry(
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
new OpenCallback(NEW, "a1m", "a1d", resolve)
);
});
let dir = createReadOnlyResidualFolder();
Assert.ok(dir.exists(), "residual folder was created");
Services.obs.notifyObservers(null, "idle-daily");
try {
await TestUtils.waitForCondition(
() => !dir.exists(),
"read-only residual cache folder should be removed by the daily sweep"
);
} finally {
clearReadOnlyRecursive(dir);
if (dir.exists()) {
dir.remove(true);
}
}
}
);