diff --git a/Tests/LibWeb/Text/expected/cookie.txt b/Tests/LibWeb/Text/expected/cookie.txt index 1855397519f..bfd83b6c895 100644 --- a/Tests/LibWeb/Text/expected/cookie.txt +++ b/Tests/LibWeb/Text/expected/cookie.txt @@ -16,10 +16,10 @@ SameSite=Lax: "cookie=value" SameSite=Strict: "cookie=value" SameSite=None: "" Max-Age (before expiration): "cookie-max-age1=value; cookie-max-age2=value" -Expires (before expiration): "cookie-expires=value; cookie-max-age1=value; cookie-max-age2=value" Max-Age (after expiration): "cookie-max-age2=value" -Expires (after expiration): "" Max-Age in past: "" +Expires (before expiration): "cookie-expires=value" +Expires (after expiration): "" Expires in past: "" Invalid expiry (date does not exist): "cookie=value" Invalid expiry (missing time): "cookie=value" diff --git a/Tests/LibWeb/Text/input/cookie.html b/Tests/LibWeb/Text/input/cookie.html index 3835a8642ab..cd439f213d8 100644 --- a/Tests/LibWeb/Text/input/cookie.html +++ b/Tests/LibWeb/Text/input/cookie.html @@ -122,13 +122,12 @@ deleteCookie("cookie"); }; - const maxAgeTest1 = () => { + const maxAgeTest = () => { document.cookie = "cookie-max-age1=value; max-age=1"; document.cookie = `cookie-max-age2=value; max-age=${"1".repeat(1024)}`; printCookies("Max-Age (before expiration)"); - }; - const maxAgeTest2 = () => { + internals.expireCookiesWithTimeOffset(2); printCookies("Max-Age (after expiration)"); deleteCookie("cookie-max-age2"); }; @@ -139,15 +138,14 @@ printCookies("Max-Age in past"); }; - const expiresTest1 = () => { + const expiresTest = () => { let expiry = new Date(Date.now() + 1000); expiry = expiry.toUTCString(); document.cookie = `cookie-expires=value; expires=${expiry}`; printCookies("Expires (before expiration)"); - }; - const expiresTest2 = () => { + internals.expireCookiesWithTimeOffset(2); printCookies("Expires (after expiration)"); }; @@ -179,7 +177,7 @@ deleteCookie("cookie"); }; - asyncTest(done => { + test(() => { basicTest(); multipleCookiesTest(); @@ -200,18 +198,11 @@ publicSuffixTest(); sameSiteTest(); - maxAgeTest1(); - expiresTest1(); + maxAgeTest(); + maxAgeInPastTest(); - setTimeout(() => { - maxAgeTest2(); - expiresTest2(); - - maxAgeInPastTest(); - expiresInPastTest(); - invalidExpiryTest(); - - done(); - }, 1200); + expiresTest(); + expiresInPastTest(); + invalidExpiryTest(); }); diff --git a/Userland/Libraries/LibWeb/Internals/Internals.cpp b/Userland/Libraries/LibWeb/Internals/Internals.cpp index a97cd04b7f2..1b0a41956e0 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.cpp +++ b/Userland/Libraries/LibWeb/Internals/Internals.cpp @@ -184,4 +184,9 @@ void Internals::simulate_drop(double x, double y) page.handle_drag_and_drop_event(DragEvent::Type::Drop, position, position, UIEvents::MouseButton::Primary, 0, 0, {}); } +void Internals::expire_cookies_with_time_offset(WebIDL::LongLong seconds) +{ + internals_page().client().page_did_expire_cookies_with_time_offset(AK::Duration::from_seconds(seconds)); +} + } diff --git a/Userland/Libraries/LibWeb/Internals/Internals.h b/Userland/Libraries/LibWeb/Internals/Internals.h index 2623a5b3759..69336c8d0fd 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.h +++ b/Userland/Libraries/LibWeb/Internals/Internals.h @@ -44,6 +44,8 @@ public: void simulate_drag_move(double x, double y); void simulate_drop(double x, double y); + void expire_cookies_with_time_offset(WebIDL::LongLong seconds); + private: explicit Internals(JS::Realm&); virtual void initialize(JS::Realm&) override; diff --git a/Userland/Libraries/LibWeb/Internals/Internals.idl b/Userland/Libraries/LibWeb/Internals/Internals.idl index 665b55de9a8..d6b2c14327e 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.idl +++ b/Userland/Libraries/LibWeb/Internals/Internals.idl @@ -33,4 +33,6 @@ interface Internals { undefined simulateDragStart(double x, double y, DOMString mimeType, DOMString contents); undefined simulateDragMove(double x, double y); undefined simulateDrop(double x, double y); + + undefined expireCookiesWithTimeOffset(long long seconds); }; diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 6877a072572..3242bbca6cc 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -343,6 +343,7 @@ public: virtual String page_did_request_cookie(URL::URL const&, Cookie::Source) { return {}; } virtual void page_did_set_cookie(URL::URL const&, Cookie::ParsedCookie const&, Cookie::Source) { } virtual void page_did_update_cookie(Web::Cookie::Cookie) { } + virtual void page_did_expire_cookies_with_time_offset(AK::Duration) { } virtual void page_did_update_resource_count(i32) { } struct NewWebViewResult { JS::GCPtr page; diff --git a/Userland/Libraries/LibWebView/CookieJar.cpp b/Userland/Libraries/LibWebView/CookieJar.cpp index 5acac7caa39..404110e536d 100644 --- a/Userland/Libraries/LibWebView/CookieJar.cpp +++ b/Userland/Libraries/LibWebView/CookieJar.cpp @@ -213,6 +213,11 @@ Optional CookieJar::get_named_cookie(URL::URL const& url, S return {}; } +void CookieJar::expire_cookies_with_time_offset(AK::Duration offset) +{ + m_transient_storage.purge_expired_cookies(offset); +} + // https://www.ietf.org/archive/id/draft-ietf-httpbis-rfc6265bis-15.html#section-5.1.2 Optional CookieJar::canonicalize_domain(const URL::URL& url) { @@ -643,12 +648,19 @@ Optional CookieJar::TransientStorage::get_cookie(CookieStor return m_cookies.get(key); } -UnixDateTime CookieJar::TransientStorage::purge_expired_cookies() +UnixDateTime CookieJar::TransientStorage::purge_expired_cookies(Optional offset) { auto now = UnixDateTime::now(); - auto is_expired = [&](auto const&, auto const& cookie) { return cookie.expiry_time < now; }; + if (offset.has_value()) { + now += *offset; + for (auto& cookie : m_dirty_cookies) + cookie.value.expiry_time -= *offset; + } + + auto is_expired = [&](auto const&, auto const& cookie) { return cookie.expiry_time < now; }; m_cookies.remove_all_matching(is_expired); + return now; } diff --git a/Userland/Libraries/LibWebView/CookieJar.h b/Userland/Libraries/LibWebView/CookieJar.h index a8591753819..b7db194d386 100644 --- a/Userland/Libraries/LibWebView/CookieJar.h +++ b/Userland/Libraries/LibWebView/CookieJar.h @@ -47,7 +47,7 @@ class CookieJar { size_t size() const { return m_cookies.size(); } - UnixDateTime purge_expired_cookies(); + UnixDateTime purge_expired_cookies(Optional offset = {}); auto take_dirty_cookies() { return move(m_dirty_cookies); } @@ -94,6 +94,7 @@ public: Vector get_all_cookies(); Vector get_all_cookies(URL::URL const& url); Optional get_named_cookie(URL::URL const& url, StringView name); + void expire_cookies_with_time_offset(AK::Duration); private: explicit CookieJar(Optional); diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp index ce6629dc8a0..5e13efc4f73 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.cpp +++ b/Userland/Libraries/LibWebView/WebContentClient.cpp @@ -445,6 +445,11 @@ void WebContentClient::did_update_cookie(Web::Cookie::Cookie const& cookie) Application::cookie_jar().update_cookie(cookie); } +void WebContentClient::did_expire_cookies_with_time_offset(AK::Duration offset) +{ + Application::cookie_jar().expire_cookies_with_time_offset(offset); +} + Messages::WebContentClient::DidRequestNewWebViewResponse WebContentClient::did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab const& activate_tab, Web::HTML::WebViewHints const& hints, Optional const& page_index) { if (auto view = view_for_page_id(page_id); view.has_value()) { diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h index 57b2297ba4d..4b9d84e2f89 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.h +++ b/Userland/Libraries/LibWebView/WebContentClient.h @@ -93,6 +93,7 @@ private: virtual Messages::WebContentClient::DidRequestCookieResponse did_request_cookie(URL::URL const&, Web::Cookie::Source) override; virtual void did_set_cookie(URL::URL const&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override; virtual void did_update_cookie(Web::Cookie::Cookie const&) override; + virtual void did_expire_cookies_with_time_offset(AK::Duration) override; virtual Messages::WebContentClient::DidRequestNewWebViewResponse did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab const&, Web::HTML::WebViewHints const&, Optional const& page_index) override; virtual void did_request_activate_tab(u64 page_id) override; virtual void did_close_browsing_context(u64 page_id) override; diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index ff9b135df92..ca2b9fb502d 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -502,6 +502,11 @@ void PageClient::page_did_update_cookie(Web::Cookie::Cookie cookie) client().async_did_update_cookie(move(cookie)); } +void PageClient::page_did_expire_cookies_with_time_offset(AK::Duration offset) +{ + client().async_did_expire_cookies_with_time_offset(offset); +} + void PageClient::page_did_update_resource_count(i32 count_waiting) { client().async_did_update_resource_count(m_id, count_waiting); diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index 5f727b42916..2875428d799 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -146,6 +146,7 @@ private: virtual String page_did_request_cookie(URL::URL const&, Web::Cookie::Source) override; virtual void page_did_set_cookie(URL::URL const&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override; virtual void page_did_update_cookie(Web::Cookie::Cookie) override; + virtual void page_did_expire_cookies_with_time_offset(AK::Duration) override; virtual void page_did_update_resource_count(i32) override; virtual NewWebViewResult page_did_request_new_web_view(Web::HTML::ActivateTab, Web::HTML::WebViewHints, Web::HTML::TokenizedFeature::NoOpener) override; virtual void page_did_request_activate_tab() override; diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index a9cb4cef920..94b346ccac1 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -71,6 +71,7 @@ endpoint WebContentClient did_request_cookie(URL::URL url, Web::Cookie::Source source) => (String cookie) did_set_cookie(URL::URL url, Web::Cookie::ParsedCookie cookie, Web::Cookie::Source source) => () did_update_cookie(Web::Cookie::Cookie cookie) =| + did_expire_cookies_with_time_offset(AK::Duration offset) =| did_update_resource_count(u64 page_id, i32 count_waiting) =| did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Optional page_index) => (String handle) did_request_activate_tab(u64 page_id) =|