From 48aa16d74bbca998f64ca8ccbf0668dbd1cded53 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 2 Nov 2025 18:36:39 -0500 Subject: [PATCH] LibWebView: Add methods to remove cookies / WebStorage items This allows removing cookies and local/session storage items last accessed since a provided timestamp. --- Libraries/LibWebView/CookieJar.cpp | 17 +++++++++++++++++ Libraries/LibWebView/CookieJar.h | 2 ++ Libraries/LibWebView/StorageJar.cpp | 21 +++++++++++++++++++++ Libraries/LibWebView/StorageJar.h | 4 ++++ 4 files changed, 44 insertions(+) diff --git a/Libraries/LibWebView/CookieJar.cpp b/Libraries/LibWebView/CookieJar.cpp index 8345ecf67ab..a51365d0e99 100644 --- a/Libraries/LibWebView/CookieJar.cpp +++ b/Libraries/LibWebView/CookieJar.cpp @@ -233,6 +233,11 @@ void CookieJar::expire_cookies_with_time_offset(AK::Duration offset) m_transient_storage.purge_expired_cookies(offset); } +void CookieJar::expire_cookies_accessed_since(UnixDateTime since) +{ + m_transient_storage.expire_and_purge_cookies_accessed_since(since); +} + Requests::CacheSizes CookieJar::estimate_storage_size_accessed_since(UnixDateTime since) const { return m_transient_storage.estimate_storage_size_accessed_since(since); @@ -652,6 +657,18 @@ void CookieJar::TransientStorage::expire_and_purge_all_cookies() purge_expired_cookies(); } +void CookieJar::TransientStorage::expire_and_purge_cookies_accessed_since(UnixDateTime since) +{ + for (auto& [key, value] : m_cookies) { + if (value.last_access_time >= since) { + value.expiry_time = UnixDateTime::earliest(); + set_cookie(key, value); + } + } + + purge_expired_cookies(); +} + Requests::CacheSizes CookieJar::TransientStorage::estimate_storage_size_accessed_since(UnixDateTime since) const { Requests::CacheSizes sizes; diff --git a/Libraries/LibWebView/CookieJar.h b/Libraries/LibWebView/CookieJar.h index c9a98043f16..72281b33c5e 100644 --- a/Libraries/LibWebView/CookieJar.h +++ b/Libraries/LibWebView/CookieJar.h @@ -47,6 +47,7 @@ public: Vector get_all_cookies_cookiestore(URL::URL const& url); Optional get_named_cookie(URL::URL const& url, StringView name); void expire_cookies_with_time_offset(AK::Duration); + void expire_cookies_accessed_since(UnixDateTime since); Requests::CacheSizes estimate_storage_size_accessed_since(UnixDateTime since) const; private: @@ -68,6 +69,7 @@ private: UnixDateTime purge_expired_cookies(Optional offset = {}); void expire_and_purge_all_cookies(); + void expire_and_purge_cookies_accessed_since(UnixDateTime since); Requests::CacheSizes estimate_storage_size_accessed_since(UnixDateTime since) const; diff --git a/Libraries/LibWebView/StorageJar.cpp b/Libraries/LibWebView/StorageJar.cpp index 2dcc12faecb..a8f8bb18ecf 100644 --- a/Libraries/LibWebView/StorageJar.cpp +++ b/Libraries/LibWebView/StorageJar.cpp @@ -57,6 +57,7 @@ ErrorOr> StorageJar::create(Database::Database& databa statements.get_item = TRY(database.prepare_statement("SELECT bottle_value FROM WebStorage WHERE storage_endpoint = ? AND storage_key = ? AND bottle_key = ?;"sv)); statements.set_item = TRY(database.prepare_statement("INSERT OR REPLACE INTO WebStorage VALUES (?, ?, ?, ?, ?);"sv)); statements.delete_item = TRY(database.prepare_statement("DELETE FROM WebStorage WHERE storage_endpoint = ? AND storage_key = ? AND bottle_key = ?;"sv)); + statements.delete_items_accessed_since = TRY(database.prepare_statement("DELETE FROM WebStorage WHERE last_access_time >= ?;"sv)); statements.update_last_access_time = TRY(database.prepare_statement("UPDATE WebStorage SET last_access_time = ? WHERE storage_endpoint = ? AND storage_key = ? AND bottle_key = ?;"sv)); statements.clear = TRY(database.prepare_statement("DELETE FROM WebStorage WHERE storage_endpoint = ? AND storage_key = ?;"sv)); statements.get_keys = TRY(database.prepare_statement("SELECT bottle_key FROM WebStorage WHERE storage_endpoint = ? AND storage_key = ?;"sv)); @@ -125,6 +126,14 @@ void StorageJar::remove_item(StorageEndpointType storage_endpoint, String const& m_transient_storage.delete_item(storage_location); } +void StorageJar::remove_items_accessed_since(UnixDateTime since) +{ + if (m_persisted_storage.has_value()) + m_persisted_storage->delete_items_accessed_since(since); + else + m_transient_storage.delete_items_accessed_since(since); +} + void StorageJar::clear_storage_key(StorageEndpointType storage_endpoint, String const& storage_key) { if (m_persisted_storage.has_value()) @@ -181,6 +190,13 @@ void StorageJar::TransientStorage::delete_item(StorageLocation const& key) m_storage_items.remove(key); } +void StorageJar::TransientStorage::delete_items_accessed_since(UnixDateTime since) +{ + m_storage_items.remove_all_matching([&](auto const&, auto const& entry) { + return entry.last_access_time >= since; + }); +} + void StorageJar::TransientStorage::clear(StorageEndpointType storage_endpoint, String const& storage_key) { Vector keys_to_remove; @@ -284,6 +300,11 @@ void StorageJar::PersistedStorage::delete_item(StorageLocation const& key) key.bottle_key); } +void StorageJar::PersistedStorage::delete_items_accessed_since(UnixDateTime since) +{ + database.execute_statement(statements.delete_items_accessed_since, {}, since); +} + void StorageJar::PersistedStorage::clear(StorageEndpointType storage_endpoint, String const& storage_key) { database.execute_statement( diff --git a/Libraries/LibWebView/StorageJar.h b/Libraries/LibWebView/StorageJar.h index 0f23d49127c..60f9dac5673 100644 --- a/Libraries/LibWebView/StorageJar.h +++ b/Libraries/LibWebView/StorageJar.h @@ -41,6 +41,7 @@ public: Optional get_item(StorageEndpointType storage_endpoint, String const& storage_key, String const& bottle_key); StorageOperationError set_item(StorageEndpointType storage_endpoint, String const& storage_key, String const& bottle_key, String const& bottle_value); void remove_item(StorageEndpointType storage_endpoint, String const& storage_key, String const& key); + void remove_items_accessed_since(UnixDateTime); void clear_storage_key(StorageEndpointType storage_endpoint, String const& storage_key); Vector get_all_keys(StorageEndpointType storage_endpoint, String const& storage_key); Requests::CacheSizes estimate_storage_size_accessed_since(UnixDateTime since) const; @@ -50,6 +51,7 @@ private: Database::StatementID get_item { 0 }; Database::StatementID set_item { 0 }; Database::StatementID delete_item { 0 }; + Database::StatementID delete_items_accessed_since { 0 }; Database::StatementID update_last_access_time { 0 }; Database::StatementID clear { 0 }; Database::StatementID get_keys { 0 }; @@ -62,6 +64,7 @@ private: Optional get_item(StorageLocation const& key); StorageOperationError set_item(StorageLocation const& key, String const& value); void delete_item(StorageLocation const& key); + void delete_items_accessed_since(UnixDateTime); void clear(StorageEndpointType storage_endpoint, String const& storage_key); Vector get_keys(StorageEndpointType storage_endpoint, String const& storage_key); Requests::CacheSizes estimate_storage_size_accessed_since(UnixDateTime since) const; @@ -79,6 +82,7 @@ private: Optional get_item(StorageLocation const& key); StorageOperationError set_item(StorageLocation const& key, String const& value); void delete_item(StorageLocation const& key); + void delete_items_accessed_since(UnixDateTime); void clear(StorageEndpointType storage_endpoint, String const& storage_key); Vector get_keys(StorageEndpointType storage_endpoint, String const& storage_key); Requests::CacheSizes estimate_storage_size_accessed_since(UnixDateTime since) const;