diff --git a/Base/res/ladybird/about-pages/settings.html b/Base/res/ladybird/about-pages/settings.html index d1b1fd39ad..81d05839f4 100644 --- a/Base/res/ladybird/about-pages/settings.html +++ b/Base/res/ladybird/about-pages/settings.html @@ -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 @@
Browsing Data - +

@@ -518,17 +521,34 @@
- +
-

Clear Browsing Data

- +

Browsing Data Settings

+
-

+


-

From:

+ + + +
+

+ 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. +

+ +
+ +
+

Remove browsing data from:

-
-
-
diff --git a/Base/res/ladybird/about-pages/settings/privacy.js b/Base/res/ladybird/about-pages/settings/privacy.js index 23cd06d5e1..725b25e38c 100644 --- a/Base/res/ladybird/about-pages/settings/privacy.js +++ b/Base/res/ladybird/about-pages/settings/privacy.js @@ -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", () => { diff --git a/Base/res/ladybird/ladybird.css b/Base/res/ladybird/ladybird.css index d05042a07e..321a532151 100644 --- a/Base/res/ladybird/ladybird.css +++ b/Base/res/ladybird/ladybird.css @@ -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, diff --git a/Libraries/LibHTTP/CMakeLists.txt b/Libraries/LibHTTP/CMakeLists.txt index 14414dcaa5..334550a2d9 100644 --- a/Libraries/LibHTTP/CMakeLists.txt +++ b/Libraries/LibHTTP/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES Cache/CacheEntry.cpp Cache/CacheIndex.cpp Cache/DiskCache.cpp + Cache/DiskCacheSettings.cpp Cache/MemoryCache.cpp Cache/Utilities.cpp Cookie/Cookie.cpp diff --git a/Libraries/LibHTTP/Cache/CacheIndex.cpp b/Libraries/LibHTTP/Cache/CacheIndex.cpp index 7c42449191..6fcf54e89b 100644 --- a/Libraries/LibHTTP/Cache/CacheIndex.cpp +++ b/Libraries/LibHTTP/Cache/CacheIndex.cpp @@ -311,4 +311,13 @@ Requests::CacheSizes CacheIndex::estimate_cache_size_accessed_since(UnixDateTime return sizes; } +void CacheIndex::set_maximum_disk_cache_size(u64 maximum_disk_cache_size) +{ + if (maximum_disk_cache_size == m_limits.maximum_disk_cache_size) + return; + + m_limits.maximum_disk_cache_size = compute_maximum_disk_cache_size(m_limits.free_disk_space, maximum_disk_cache_size); + m_limits.maximum_disk_cache_entry_size = compute_maximum_disk_cache_entry_size(m_limits.maximum_disk_cache_size); +} + } diff --git a/Libraries/LibHTTP/Cache/CacheIndex.h b/Libraries/LibHTTP/Cache/CacheIndex.h index 8abac24ac4..a3e91ec8f8 100644 --- a/Libraries/LibHTTP/Cache/CacheIndex.h +++ b/Libraries/LibHTTP/Cache/CacheIndex.h @@ -48,6 +48,8 @@ public: Requests::CacheSizes estimate_cache_size_accessed_since(UnixDateTime since); + void set_maximum_disk_cache_size(u64 maximum_disk_cache_size); + private: struct Statements { Database::StatementID insert_entry { 0 }; diff --git a/Libraries/LibHTTP/Cache/DiskCache.cpp b/Libraries/LibHTTP/Cache/DiskCache.cpp index 819711f700..e6e06473f5 100644 --- a/Libraries/LibHTTP/Cache/DiskCache.cpp +++ b/Libraries/LibHTTP/Cache/DiskCache.cpp @@ -237,6 +237,11 @@ void DiskCache::remove_entries_exceeding_cache_limit() }); } +void DiskCache::set_maximum_disk_cache_size(u64 maximum_disk_cache_size) +{ + m_index.set_maximum_disk_cache_size(maximum_disk_cache_size); +} + Requests::CacheSizes DiskCache::estimate_cache_size_accessed_since(UnixDateTime since) { return m_index.estimate_cache_size_accessed_since(since); diff --git a/Libraries/LibHTTP/Cache/DiskCache.h b/Libraries/LibHTTP/Cache/DiskCache.h index 5261da2f4a..26acb8ee93 100644 --- a/Libraries/LibHTTP/Cache/DiskCache.h +++ b/Libraries/LibHTTP/Cache/DiskCache.h @@ -53,6 +53,7 @@ public: Variant, CacheHasOpenEntry> open_entry(CacheRequest&, URL::URL const&, StringView method, HeaderList const& request_headers, CacheMode, OpenMode); void remove_entries_exceeding_cache_limit(); + void set_maximum_disk_cache_size(u64 maximum_disk_cache_size); Requests::CacheSizes estimate_cache_size_accessed_since(UnixDateTime since); void remove_entries_accessed_since(UnixDateTime since); diff --git a/Libraries/LibHTTP/Cache/DiskCacheSettings.cpp b/Libraries/LibHTTP/Cache/DiskCacheSettings.cpp new file mode 100644 index 0000000000..3bab6487b0 --- /dev/null +++ b/Libraries/LibHTTP/Cache/DiskCacheSettings.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2026, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace IPC { + +template<> +ErrorOr encode(Encoder& encoder, HTTP::DiskCacheSettings const& sizes) +{ + TRY(encoder.encode(sizes.maximum_size)); + + return {}; +} + +template<> +ErrorOr decode(Decoder& decoder) +{ + auto maximum_size = TRY(decoder.decode()); + + return HTTP::DiskCacheSettings { maximum_size }; +} + +} diff --git a/Libraries/LibHTTP/Cache/DiskCacheSettings.h b/Libraries/LibHTTP/Cache/DiskCacheSettings.h new file mode 100644 index 0000000000..96f652ad63 --- /dev/null +++ b/Libraries/LibHTTP/Cache/DiskCacheSettings.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace HTTP { + +struct DiskCacheSettings { + u64 maximum_size { DEFAULT_MAXIMUM_DISK_CACHE_SIZE }; +}; + +} + +namespace IPC { + +template<> +ErrorOr encode(Encoder&, HTTP::DiskCacheSettings const&); + +template<> +ErrorOr decode(Decoder&); + +} diff --git a/Libraries/LibHTTP/Cache/Utilities.cpp b/Libraries/LibHTTP/Cache/Utilities.cpp index ba33f083bc..498b830b06 100644 --- a/Libraries/LibHTTP/Cache/Utilities.cpp +++ b/Libraries/LibHTTP/Cache/Utilities.cpp @@ -24,19 +24,21 @@ static Optional parse_http_date(Optional date) return {}; } -u64 compute_maximum_disk_cache_size(u64 free_bytes) +u64 compute_maximum_disk_cache_size(u64 free_bytes, u64 limit_maximum_disk_cache_size) { - static constexpr u64 MAXIMUM_DISK_CACHE_SIZE = 5 * GiB; + auto cache_size = [&]() { + if (free_bytes <= 100 * MiB) + return free_bytes * 8 / 10; // Up to 80 MiB + if (free_bytes <= 800 * MiB) + return free_bytes * 6 / 10; // Up to 480 MiB + if (free_bytes <= 2 * GiB) + return free_bytes * 4 / 10; // Up to 820 MiB + if (free_bytes <= 10 * GiB) + return free_bytes * 2 / 10; // Up to 2 GiB + return limit_maximum_disk_cache_size; + }(); - if (free_bytes <= 100 * MiB) - return free_bytes * 8 / 10; // Up to 80 MiB - if (free_bytes <= 800 * MiB) - return free_bytes * 6 / 10; // Up to 480 MiB - if (free_bytes <= 2 * GiB) - return free_bytes * 4 / 10; // Up to 820 MiB - if (free_bytes <= 10 * GiB) - return free_bytes * 2 / 10; // Up to 2 GiB - return MAXIMUM_DISK_CACHE_SIZE; + return min(cache_size, limit_maximum_disk_cache_size); } u64 compute_maximum_disk_cache_entry_size(u64 maximum_disk_cache_size) diff --git a/Libraries/LibHTTP/Cache/Utilities.h b/Libraries/LibHTTP/Cache/Utilities.h index 13130fc0ee..28cfa95969 100644 --- a/Libraries/LibHTTP/Cache/Utilities.h +++ b/Libraries/LibHTTP/Cache/Utilities.h @@ -21,7 +21,9 @@ constexpr inline auto TEST_CACHE_STATUS_HEADER = "X-Ladybird-Disk-Cache-Status"s constexpr inline auto TEST_CACHE_REVALIDATION_STATUS_HEADER = "X-Ladybird-Revalidation-Status"sv; constexpr inline auto TEST_CACHE_REQUEST_TIME_OFFSET = "X-Ladybird-Request-Time-Offset"sv; -u64 compute_maximum_disk_cache_size(u64 free_bytes); +constexpr inline u64 DEFAULT_MAXIMUM_DISK_CACHE_SIZE = 5 * GiB; + +u64 compute_maximum_disk_cache_size(u64 free_bytes, u64 limit_maximum_disk_cache_size = DEFAULT_MAXIMUM_DISK_CACHE_SIZE); u64 compute_maximum_disk_cache_entry_size(u64 maximum_disk_cache_size); String serialize_url_for_cache_storage(URL::URL const&); diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index 4494ba3f46..c9679dc2dd 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -35,6 +35,12 @@ namespace WebView { Application* Application::s_the = nullptr; struct ApplicationSettingsObserver : public SettingsObserver { + virtual void browsing_data_settings_changed() override + { + auto const& browsing_data_settings = Application::settings().browsing_data_settings(); + Application::request_server_client().async_set_disk_cache_settings(browsing_data_settings.disk_cache_settings); + } + virtual void dns_settings_changed() override { Application::settings().dns_settings().visit( diff --git a/Libraries/LibWebView/HelperProcess.cpp b/Libraries/LibWebView/HelperProcess.cpp index 1f2a3ebe08..2c937fde80 100644 --- a/Libraries/LibWebView/HelperProcess.cpp +++ b/Libraries/LibWebView/HelperProcess.cpp @@ -247,13 +247,16 @@ ErrorOr> launch_request_server_process() auto client = TRY(launch_server_process("RequestServer"sv, move(arguments))); - WebView::Application::settings().dns_settings().visit( - [](WebView::SystemDNS) {}, - [&](WebView::DNSOverTLS const& dns_over_tls) { + auto const& browsing_data_settings = Application::settings().browsing_data_settings(); + client->async_set_disk_cache_settings(browsing_data_settings.disk_cache_settings); + + Application::settings().dns_settings().visit( + [](SystemDNS) {}, + [&](DNSOverTLS const& dns_over_tls) { dbgln("Setting DNS server to {}:{} with TLS ({} local dnssec)", dns_over_tls.server_address, dns_over_tls.port, dns_over_tls.validate_dnssec_locally ? "with" : "without"); client->async_set_dns_server(dns_over_tls.server_address, dns_over_tls.port, true, dns_over_tls.validate_dnssec_locally); }, - [&](WebView::DNSOverUDP const& dns_over_udp) { + [&](DNSOverUDP const& dns_over_udp) { dbgln("Setting DNS server to {}:{} ({} local dnssec)", dns_over_udp.server_address, dns_over_udp.port, dns_over_udp.validate_dnssec_locally ? "with" : "without"); client->async_set_dns_server(dns_over_udp.server_address, dns_over_udp.port, false, dns_over_udp.validate_dnssec_locally); }); diff --git a/Libraries/LibWebView/Settings.cpp b/Libraries/LibWebView/Settings.cpp index ad88871ed5..c72ef401cf 100644 --- a/Libraries/LibWebView/Settings.cpp +++ b/Libraries/LibWebView/Settings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Tim Flynn + * Copyright (c) 2025-2026, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -42,6 +42,10 @@ static constexpr auto site_setting_site_filters_key = "siteFilters"sv; static constexpr auto autoplay_key = "autoplay"sv; +static constexpr auto browsing_data_key = "browsingData"sv; +static constexpr auto disk_cache_key = "diskCache"sv; +static constexpr auto disk_cache_maximum_size_key = "maxSize"sv; + static constexpr auto global_privacy_control_key = "globalPrivacyControl"sv; static constexpr auto dns_settings_key = "dnsSettings"sv; @@ -141,6 +145,9 @@ Settings Settings::create(Badge) load_site_setting(settings.m_autoplay, autoplay_key); + if (auto browsing_data_settings = settings_json.value().get(browsing_data_key); browsing_data_settings.has_value()) + settings.m_browsing_data_settings = parse_browsing_data_settings(*browsing_data_settings); + if (auto global_privacy_control = settings_json.value().get_bool(global_privacy_control_key); global_privacy_control.has_value()) settings.m_global_privacy_control = *global_privacy_control ? GlobalPrivacyControl::Yes : GlobalPrivacyControl::No; @@ -215,6 +222,13 @@ JsonValue Settings::serialize_json() const save_site_setting(m_autoplay, autoplay_key); + JsonObject disk_cache_settings; + disk_cache_settings.set(disk_cache_maximum_size_key, m_browsing_data_settings.disk_cache_settings.maximum_size); + + JsonObject browsing_data; + browsing_data.set(disk_cache_key, move(disk_cache_settings)); + settings.set(browsing_data_key, move(browsing_data)); + settings.set(global_privacy_control_key, m_global_privacy_control == GlobalPrivacyControl::Yes); // dnsSettings :: { mode: "system" } | { mode: "custom", server: string, port: u16, type: "udp" | "tls", forciblyEnabled: bool, dnssec: bool } @@ -253,6 +267,7 @@ void Settings::restore_defaults() m_custom_search_engines.clear(); m_autocomplete_engine.clear(); m_autoplay = SiteSetting {}; + m_browsing_data_settings = {}; m_global_privacy_control = GlobalPrivacyControl::No; m_dns_settings = SystemDNS {}; @@ -265,6 +280,7 @@ void Settings::restore_defaults() observer.search_engine_changed(); observer.autocomplete_engine_changed(); observer.autoplay_settings_changed(); + observer.browsing_data_settings_changed(); observer.global_privacy_control_changed(); observer.dns_settings_changed(); } @@ -438,6 +454,30 @@ void Settings::remove_all_autoplay_site_filters() observer.autoplay_settings_changed(); } +BrowsingDataSettings Settings::parse_browsing_data_settings(JsonValue const& settings) +{ + if (!settings.is_object()) + return {}; + + BrowsingDataSettings browsing_data_settings; + + if (auto disk_cache_settings = settings.as_object().get_object(disk_cache_key); disk_cache_settings.has_value()) { + if (auto maximum_size = disk_cache_settings->get_integer(disk_cache_maximum_size_key); maximum_size.has_value()) + browsing_data_settings.disk_cache_settings.maximum_size = *maximum_size; + } + + return browsing_data_settings; +} + +void Settings::set_browsing_data_settings(BrowsingDataSettings browsing_data_settings) +{ + m_browsing_data_settings = browsing_data_settings; + persist_settings(); + + for (auto& observer : m_observers) + observer.browsing_data_settings_changed(); +} + void Settings::set_global_privacy_control(GlobalPrivacyControl global_privacy_control) { m_global_privacy_control = global_privacy_control; diff --git a/Libraries/LibWebView/Settings.h b/Libraries/LibWebView/Settings.h index 460f603811..4ed7388078 100644 --- a/Libraries/LibWebView/Settings.h +++ b/Libraries/LibWebView/Settings.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Tim Flynn + * Copyright (c) 2025-2026, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,10 @@ struct WEBVIEW_API SiteSetting { OrderedHashTable site_filters; }; +struct BrowsingDataSettings { + HTTP::DiskCacheSettings disk_cache_settings; +}; + enum class GlobalPrivacyControl { No, Yes, @@ -41,6 +46,7 @@ public: virtual void search_engine_changed() { } virtual void autocomplete_engine_changed() { } virtual void autoplay_settings_changed() { } + virtual void browsing_data_settings_changed() { } virtual void global_privacy_control_changed() { } virtual void dns_settings_changed() { } }; @@ -79,6 +85,10 @@ public: void remove_autoplay_site_filter(String const&); void remove_all_autoplay_site_filters(); + static BrowsingDataSettings parse_browsing_data_settings(JsonValue const&); + BrowsingDataSettings const& browsing_data_settings() const { return m_browsing_data_settings; } + void set_browsing_data_settings(BrowsingDataSettings); + GlobalPrivacyControl global_privacy_control() const { return m_global_privacy_control; } void set_global_privacy_control(GlobalPrivacyControl); @@ -105,6 +115,7 @@ private: Vector m_custom_search_engines; Optional m_autocomplete_engine; SiteSetting m_autoplay; + BrowsingDataSettings m_browsing_data_settings; GlobalPrivacyControl m_global_privacy_control { GlobalPrivacyControl::No }; DNSSettings m_dns_settings { SystemDNS() }; bool m_dns_override_by_command_line { false }; diff --git a/Libraries/LibWebView/WebUI/SettingsUI.cpp b/Libraries/LibWebView/WebUI/SettingsUI.cpp index 8ae43354fe..ed2d1c5b39 100644 --- a/Libraries/LibWebView/WebUI/SettingsUI.cpp +++ b/Libraries/LibWebView/WebUI/SettingsUI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Tim Flynn + * Copyright (c) 2025-2026, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -66,6 +66,9 @@ void SettingsUI::register_interfaces() register_interface("estimateBrowsingDataSizes"sv, [this](auto const& data) { estimate_browsing_data_sizes(data); }); + register_interface("setBrowsingDataSettings"sv, [this](auto const& data) { + set_browsing_data_settings(data); + }); register_interface("clearBrowsingData"sv, [this](auto const& data) { clear_browsing_data(data); }); @@ -311,6 +314,12 @@ void SettingsUI::estimate_browsing_data_sizes(JsonValue const& options) }); } +void SettingsUI::set_browsing_data_settings(JsonValue const& settings) +{ + Application::settings().set_browsing_data_settings(Settings::parse_browsing_data_settings(settings)); + load_current_settings(); +} + void SettingsUI::clear_browsing_data(JsonValue const& options) { if (!options.is_object()) diff --git a/Libraries/LibWebView/WebUI/SettingsUI.h b/Libraries/LibWebView/WebUI/SettingsUI.h index 784bf39165..5208263ebd 100644 --- a/Libraries/LibWebView/WebUI/SettingsUI.h +++ b/Libraries/LibWebView/WebUI/SettingsUI.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Tim Flynn + * Copyright (c) 2025-2026, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -37,6 +37,7 @@ private: void remove_all_site_setting_filters(JsonValue const&); void estimate_browsing_data_sizes(JsonValue const&); + void set_browsing_data_settings(JsonValue const&); void clear_browsing_data(JsonValue const&); void set_global_privacy_control(JsonValue const&); diff --git a/Services/RequestServer/ConnectionFromClient.cpp b/Services/RequestServer/ConnectionFromClient.cpp index 2b4e6e9397..5c44f093d9 100644 --- a/Services/RequestServer/ConnectionFromClient.cpp +++ b/Services/RequestServer/ConnectionFromClient.cpp @@ -165,6 +165,12 @@ ErrorOr ConnectionFromClient::create_client_socket() return IPC::File::adopt_fd(socket_fds[1]); } +void ConnectionFromClient::set_disk_cache_settings(HTTP::DiskCacheSettings disk_cache_settings) +{ + if (g_disk_cache.has_value()) + g_disk_cache->set_maximum_disk_cache_size(disk_cache_settings.maximum_size); +} + Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_supported_protocol(ByteString protocol) { return protocol == "http"sv || protocol == "https"sv; diff --git a/Services/RequestServer/ConnectionFromClient.h b/Services/RequestServer/ConnectionFromClient.h index 2d643ec06b..add7b4cfe0 100644 --- a/Services/RequestServer/ConnectionFromClient.h +++ b/Services/RequestServer/ConnectionFromClient.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,8 @@ private: virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override; virtual Messages::RequestServer::ConnectNewClientsResponse connect_new_clients(size_t count) override; + virtual void set_disk_cache_settings(HTTP::DiskCacheSettings) override; + virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString) override; virtual void set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally) override; virtual void set_use_system_dns() override; diff --git a/Services/RequestServer/RequestServer.ipc b/Services/RequestServer/RequestServer.ipc index 873435ef3a..f119091c03 100644 --- a/Services/RequestServer/RequestServer.ipc +++ b/Services/RequestServer/RequestServer.ipc @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -11,6 +12,8 @@ endpoint RequestServer connect_new_client() => (IPC::File client_socket) connect_new_clients(size_t count) => (Vector sockets) + set_disk_cache_settings(HTTP::DiskCacheSettings disk_cache_settings) =| + // use_tls: enable DNS over TLS set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally) =| set_use_system_dns() =|