From f1d66939907929a67ef6448cfafe7844dda1e177 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 26 Feb 2024 10:28:28 -0500 Subject: [PATCH] LibWebView: Reduce overhead of updating a cookie's last access time Getting a document's cookie value currently involves: 1. Doing a large SELECT statement and filtering the results to match the document and some query parameters based on the cookie RFC. 2. For every cookie selected this way, doing an UPDATE to set its last access time. 3. For every UPDATE, do a DELETE to remove all expired cookies. There's no need to perform cookie expiration for every UPDATE. Instead, we can do the expiration once after all the UPDATEs are complete. This reduces time spent waiting for cookies on https://twinings.co.uk from ~1.9s to ~1.3s on my machine. --- Userland/Libraries/LibWebView/CookieJar.cpp | 25 ++++++++++++++++++++- Userland/Libraries/LibWebView/CookieJar.h | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWebView/CookieJar.cpp b/Userland/Libraries/LibWebView/CookieJar.cpp index 3f92532e33..72def99327 100644 --- a/Userland/Libraries/LibWebView/CookieJar.cpp +++ b/Userland/Libraries/LibWebView/CookieJar.cpp @@ -55,6 +55,10 @@ ErrorOr CookieJar::create(Database& database) persistent=? WHERE ((name = ?) AND (domain = ?) AND (path = ?));)#"sv)); + statements.update_cookie_last_access_time = TRY(database.prepare_statement(R"#( + UPDATE Cookies SET last_access_time=? + WHERE ((name = ?) AND (domain = ?) AND (path = ?));)#"sv)); + statements.insert_cookie = TRY(database.prepare_statement("INSERT INTO Cookies VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"sv)); statements.expire_cookie = TRY(database.prepare_statement("DELETE FROM Cookies WHERE (expiry_time < ?);"sv)); statements.select_cookie = TRY(database.prepare_statement("SELECT * FROM Cookies WHERE ((name = ?) AND (domain = ?) AND (path = ?));"sv)); @@ -447,9 +451,10 @@ Vector CookieJar::get_matching_cookies(const URL& url, Stri for (auto& cookie : cookie_list) { cookie.last_access_time = now; - update_cookie_in_database(cookie); + update_cookie_last_access_time_in_database(cookie); } + purge_expired_cookies(); return cookie_list; } @@ -567,6 +572,24 @@ void CookieJar::update_cookie_in_database(Web::Cookie::Cookie const& cookie) }); } +void CookieJar::update_cookie_last_access_time_in_database(Web::Cookie::Cookie const& cookie) +{ + m_storage.visit( + [&](PersistedStorage& storage) { + storage.database.execute_statement( + storage.statements.update_cookie_last_access_time, + {}, {}, {}, + cookie.last_access_time, + cookie.name, + cookie.domain, + cookie.path); + }, + [&](TransientStorage& storage) { + CookieStorageKey key { cookie.name, cookie.domain, cookie.path }; + storage.set(key, cookie); + }); +} + struct WrappedCookie : public RefCounted { explicit WrappedCookie(Web::Cookie::Cookie cookie_) : RefCounted() diff --git a/Userland/Libraries/LibWebView/CookieJar.h b/Userland/Libraries/LibWebView/CookieJar.h index 71510faaab..9d65f7d9f1 100644 --- a/Userland/Libraries/LibWebView/CookieJar.h +++ b/Userland/Libraries/LibWebView/CookieJar.h @@ -33,6 +33,7 @@ class CookieJar { SQL::StatementID create_table { 0 }; SQL::StatementID insert_cookie { 0 }; SQL::StatementID update_cookie { 0 }; + SQL::StatementID update_cookie_last_access_time { 0 }; SQL::StatementID expire_cookie { 0 }; SQL::StatementID select_cookie { 0 }; SQL::StatementID select_all_cookies { 0 }; @@ -76,6 +77,7 @@ private: void insert_cookie_into_database(Web::Cookie::Cookie const& cookie); void update_cookie_in_database(Web::Cookie::Cookie const& cookie); + void update_cookie_last_access_time_in_database(Web::Cookie::Cookie const& cookie); using OnCookieFound = Function; using OnCookieNotFound = Function;