LibHTTP+LibWebView+RequestServer: Allow users to set disk cache limits

This adds a settings box to about:settings to allow users to limit the
disk cache size. This will override the default 5 GiB limit. We do not
automatically delete cache data if the new limit is suddenly less than
the used disk space; this will happen on the next request. This allows
multiple changes to the settings in a row without thrashing the cache.

In the future, we can add more toggles, such as disabling the disk
cache altogether.
This commit is contained in:
Timothy Flynn
2026-02-05 12:25:14 -05:00
committed by Tim Flynn
parent c5d666ea7b
commit 7d60d0bfb7
Notes: github-actions[bot] 2026-02-13 15:22:05 +00:00
21 changed files with 299 additions and 46 deletions

View File

@@ -145,6 +145,7 @@
font-size: 14px;
}
input[type="number"],
input[type="text"],
input[type="url"],
select {
@@ -154,11 +155,13 @@
border: 1px solid var(--border-color);
}
input[type="number"].success,
input[type="text"].success,
input[type="url"].success {
border: 1px solid green;
}
input[type="number"].error,
input[type="text"].error,
input[type="url"].error {
border: 1px solid red;
@@ -390,7 +393,7 @@
<div class="card-body">
<div class="card-group inline-container">
<span>Browsing Data</span>
<button id="clear-browsing-data" class="secondary-button">Clear...</button>
<button id="browsing-data-settings" class="secondary-button">Settings...</button>
</div>
<hr />
@@ -518,17 +521,34 @@
</div>
</dialog>
<dialog id="clear-browsing-data-dialog">
<dialog id="browsing-data-settings-dialog">
<div class="dialog-header">
<h3 id="clear-browsing-data-title" class="dialog-title">Clear Browsing Data</h3>
<button id="clear-browsing-data-close" class="close-button dialog-button">&times;</button>
<h3 class="dialog-title">Browsing Data Settings</h3>
<button id="browsing-data-settings-close" class="close-button dialog-button">&times;</button>
</div>
<div class="dialog-body">
<p id="clear-browsing-data-total-size" class="description"></p>
<p id="browsing-data-total-size" class="description"></p>
<hr />
<div class="input-field-container">
<p>From:</p>
<label for="browsing-data-settings-max-disk-cache-size">
Maximum&nbsp;disk&nbsp;cache&nbsp;size:
</label>
<input id="browsing-data-settings-max-disk-cache-size" type="number" min="1" />
<select id="browsing-data-settings-max-disk-cache-unit">
<option value="MiB">MiB</option>
<option value="GiB">GiB</option>
</select>
</div>
<p class="description" style="margin-top: 10px">
Limit the amount of space used for the HTTP disk cache. This may be further limited by the browser,
depending on the amount of disk space available.
</p>
<hr />
<div class="input-field-container">
<p>Remove&nbsp;browsing&nbsp;data&nbsp;from:</p>
<select id="clear-browsing-data-time-range">
<option value="lastHour">Last hour</option>
<option value="last4Hours">Last 4 hours</option>
@@ -536,7 +556,6 @@
<option value="all" selected>All time</option>
</select>
</div>
<div class="input-field-container">
<input id="clear-browsing-data-cached-files" type="checkbox" value="" checked />
<label for="clear-browsing-data-cached-files">
@@ -551,9 +570,9 @@
<p class="description">Remove items that may sign you out of most sites</p>
</label>
</div>
</div>
<div class="dialog-footer">
<button id="clear-browsing-data-remove-data" class="secondary-button">Remove Data</button>
<div class="button-container">
<button id="clear-browsing-data-remove-data" class="secondary-button">Remove Data</button>
</div>
</div>
</dialog>

View File

@@ -1,4 +1,5 @@
import { getByteFormatter } from "../../utils.js";
const byteFormatter = getByteFormatter(unit => {
return {
unitDisplay: unit === "byte" ? "long" : "short",
@@ -6,20 +7,52 @@ const byteFormatter = getByteFormatter(unit => {
};
});
const clearBrowsingData = document.querySelector("#clear-browsing-data");
const browsingDataSettings = document.querySelector("#browsing-data-settings");
const browsingDataSettingsClose = document.querySelector("#browsing-data-settings-close");
const browsingDataSettingsDialog = document.querySelector("#browsing-data-settings-dialog");
const browsingDataSettingsMaxDiskCacheSize = document.querySelector("#browsing-data-settings-max-disk-cache-size");
const browsingDataSettingsMaxDiskCacheUnit = document.querySelector("#browsing-data-settings-max-disk-cache-unit");
const browsingDataTotalSize = document.querySelector("#browsing-data-total-size");
const clearBrowsingDataCachedFiles = document.querySelector("#clear-browsing-data-cached-files");
const clearBrowsingDataCachedFilesSize = document.querySelector("#clear-browsing-data-cached-files-size");
const clearBrowsingDataClose = document.querySelector("#clear-browsing-data-close");
const clearBrowsingDataDialog = document.querySelector("#clear-browsing-data-dialog");
const clearBrowsingDataRemoveData = document.querySelector("#clear-browsing-data-remove-data");
const clearBrowsingDataSiteData = document.querySelector("#clear-browsing-data-site-data");
const clearBrowsingDataSiteDataSize = document.querySelector("#clear-browsing-data-site-data-size");
const clearBrowsingDataTimeRange = document.querySelector("#clear-browsing-data-time-range");
const clearBrowsingDataTotalSize = document.querySelector("#clear-browsing-data-total-size");
const globalPrivacyControlToggle = document.querySelector("#global-privacy-control-toggle");
const MiB = 1024 * 1024;
const GiB = MiB * 1024;
let BROWSING_DATA = {};
function loadSettings(settings) {
BROWSING_DATA = settings.browsingData || {};
globalPrivacyControlToggle.checked = settings.globalPrivacyControl;
if (browsingDataSettingsDialog.open) {
showBrowsingDataSettings();
}
}
function updateBrowsingDataSizes(sizes) {
const totalSize = sizes.totalCacheSize + sizes.totalSiteDataSize;
browsingDataTotalSize.innerText = `Your browsing data is currently using ${byteFormatter.formatBytes(totalSize)} of disk space`;
clearBrowsingDataCachedFilesSize.innerText = ` (remove ${byteFormatter.formatBytes(sizes.cacheSizeSinceRequestedTime)})`;
clearBrowsingDataSiteDataSize.innerText = ` (remove ${byteFormatter.formatBytes(sizes.siteDataSizeSinceRequestedTime)})`;
}
function formatDiskCacheSize(bytes) {
if (bytes >= GiB && bytes % GiB == 0) {
return { value: bytes / GiB, unit: "GiB" };
}
return { value: bytes / MiB, unit: "MiB" };
}
function computeTimeRange() {
@@ -48,28 +81,64 @@ function estimateBrowsingDataSizes() {
});
}
function updateBrowsingDataSizes(sizes) {
const totalSize = sizes.totalCacheSize + sizes.totalSiteDataSize;
function saveBrowsingDataSettings() {
browsingDataSettingsMaxDiskCacheSize.classList.remove("success");
browsingDataSettingsMaxDiskCacheSize.classList.remove("error");
clearBrowsingDataTotalSize.innerText = `Your browsing data is currently using ${byteFormatter.formatBytes(totalSize)} of disk space`;
if (
browsingDataSettingsMaxDiskCacheSize.value.length === 0 ||
!browsingDataSettingsMaxDiskCacheSize.checkValidity()
) {
browsingDataSettingsMaxDiskCacheSize.classList.add("error");
return;
}
clearBrowsingDataCachedFilesSize.innerText = ` (remove ${byteFormatter.formatBytes(sizes.cacheSizeSinceRequestedTime)})`;
clearBrowsingDataSiteDataSize.innerText = ` (remove ${byteFormatter.formatBytes(sizes.siteDataSizeSinceRequestedTime)})`;
BROWSING_DATA.diskCache = {};
BROWSING_DATA.diskCache.maxSize =
browsingDataSettingsMaxDiskCacheUnit.value === "MiB"
? browsingDataSettingsMaxDiskCacheSize.value * MiB
: browsingDataSettingsMaxDiskCacheSize.value * GiB;
ladybird.sendMessage("setBrowsingDataSettings", BROWSING_DATA);
browsingDataSettingsMaxDiskCacheSize.classList.add("success");
setTimeout(() => {
browsingDataSettingsMaxDiskCacheSize.classList.remove("success");
}, 1000);
}
clearBrowsingData.addEventListener("click", () => {
function showBrowsingDataSettings() {
const maxDiskCacheSize = BROWSING_DATA.diskCache?.maxSize || 5 * GiB;
const { value, unit } = formatDiskCacheSize(maxDiskCacheSize);
browsingDataSettingsMaxDiskCacheSize.value = value;
browsingDataSettingsMaxDiskCacheUnit.value = unit;
if (!browsingDataSettingsDialog.open) {
browsingDataSettingsDialog.showModal();
}
}
browsingDataSettings.addEventListener("click", () => {
estimateBrowsingDataSizes();
clearBrowsingDataDialog.showModal();
showBrowsingDataSettings();
});
browsingDataSettingsClose.addEventListener("click", () => {
browsingDataSettingsDialog.close();
});
browsingDataSettingsMaxDiskCacheSize.addEventListener("change", () => {
saveBrowsingDataSettings();
});
browsingDataSettingsMaxDiskCacheUnit.addEventListener("change", () => {
saveBrowsingDataSettings();
});
clearBrowsingDataTimeRange.addEventListener("change", () => {
estimateBrowsingDataSizes();
});
clearBrowsingDataClose.addEventListener("click", () => {
clearBrowsingDataDialog.close();
});
function setRemoveDataEnabledState() {
clearBrowsingDataRemoveData.disabled = !clearBrowsingDataCachedFiles.checked && !clearBrowsingDataSiteData.checked;
}
@@ -86,7 +155,7 @@ clearBrowsingDataRemoveData.addEventListener("click", () => {
siteData: clearBrowsingDataSiteData.checked,
});
clearBrowsingDataDialog.close();
browsingDataSettingsDialog.close();
});
globalPrivacyControlToggle.addEventListener("change", () => {

View File

@@ -130,6 +130,7 @@ button.secondary-button:active {
background-color: var(--secondary-button-active);
}
input[type="number"],
input[type="search"],
input[type="text"],
input[type="url"],
@@ -142,6 +143,7 @@ select {
padding: 10px 12px;
}
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="url"]:focus,