CookieJar.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (c) 2021-2024, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Function.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/Optional.h>
  10. #include <AK/String.h>
  11. #include <AK/StringView.h>
  12. #include <AK/Traits.h>
  13. #include <LibCore/DateTime.h>
  14. #include <LibCore/Timer.h>
  15. #include <LibURL/Forward.h>
  16. #include <LibWeb/Cookie/Cookie.h>
  17. #include <LibWeb/Forward.h>
  18. #include <LibWebView/Database.h>
  19. #include <LibWebView/Forward.h>
  20. namespace WebView {
  21. struct CookieStorageKey {
  22. bool operator==(CookieStorageKey const&) const = default;
  23. String name;
  24. String domain;
  25. String path;
  26. };
  27. class CookieJar {
  28. struct Statements {
  29. Database::StatementID insert_cookie { 0 };
  30. Database::StatementID expire_cookie { 0 };
  31. Database::StatementID select_all_cookies { 0 };
  32. };
  33. class TransientStorage {
  34. public:
  35. using Cookies = HashMap<CookieStorageKey, Web::Cookie::Cookie>;
  36. void set_cookies(Cookies);
  37. void set_cookie(CookieStorageKey, Web::Cookie::Cookie);
  38. Optional<Web::Cookie::Cookie> get_cookie(CookieStorageKey const&);
  39. size_t size() const { return m_cookies.size(); }
  40. UnixDateTime purge_expired_cookies(Optional<AK::Duration> offset = {});
  41. auto take_dirty_cookies() { return move(m_dirty_cookies); }
  42. template<typename Callback>
  43. void for_each_cookie(Callback callback)
  44. {
  45. using ReturnType = InvokeResult<Callback, Web::Cookie::Cookie&>;
  46. for (auto& it : m_cookies) {
  47. if constexpr (IsSame<ReturnType, IterationDecision>) {
  48. if (callback(it.value) == IterationDecision::Break)
  49. return;
  50. } else {
  51. static_assert(IsSame<ReturnType, void>);
  52. callback(it.value);
  53. }
  54. }
  55. }
  56. private:
  57. Cookies m_cookies;
  58. Cookies m_dirty_cookies;
  59. };
  60. struct PersistedStorage {
  61. void insert_cookie(Web::Cookie::Cookie const& cookie);
  62. TransientStorage::Cookies select_all_cookies();
  63. Database& database;
  64. Statements statements;
  65. RefPtr<Core::Timer> synchronization_timer {};
  66. };
  67. public:
  68. static ErrorOr<NonnullOwnPtr<CookieJar>> create(Database&);
  69. static NonnullOwnPtr<CookieJar> create();
  70. ~CookieJar();
  71. String get_cookie(const URL::URL& url, Web::Cookie::Source source);
  72. void set_cookie(const URL::URL& url, Web::Cookie::ParsedCookie const& parsed_cookie, Web::Cookie::Source source);
  73. void update_cookie(Web::Cookie::Cookie);
  74. void dump_cookies();
  75. Vector<Web::Cookie::Cookie> get_all_cookies();
  76. Vector<Web::Cookie::Cookie> get_all_cookies(URL::URL const& url);
  77. Optional<Web::Cookie::Cookie> get_named_cookie(URL::URL const& url, StringView name);
  78. void expire_cookies_with_time_offset(AK::Duration);
  79. private:
  80. explicit CookieJar(Optional<PersistedStorage>);
  81. AK_MAKE_NONCOPYABLE(CookieJar);
  82. AK_MAKE_NONMOVABLE(CookieJar);
  83. static Optional<String> canonicalize_domain(const URL::URL& url);
  84. static bool domain_matches(StringView string, StringView domain_string);
  85. static bool path_matches(StringView request_path, StringView cookie_path);
  86. enum class MatchingCookiesSpecMode {
  87. RFC6265,
  88. WebDriver,
  89. };
  90. void store_cookie(Web::Cookie::ParsedCookie const& parsed_cookie, const URL::URL& url, String canonicalized_domain, Web::Cookie::Source source);
  91. Vector<Web::Cookie::Cookie> get_matching_cookies(const URL::URL& url, StringView canonicalized_domain, Web::Cookie::Source source, MatchingCookiesSpecMode mode = MatchingCookiesSpecMode::RFC6265);
  92. Optional<PersistedStorage> m_persisted_storage;
  93. TransientStorage m_transient_storage;
  94. };
  95. }
  96. template<>
  97. struct AK::Traits<WebView::CookieStorageKey> : public AK::DefaultTraits<WebView::CookieStorageKey> {
  98. static unsigned hash(WebView::CookieStorageKey const& key)
  99. {
  100. unsigned hash = 0;
  101. hash = pair_int_hash(hash, key.name.hash());
  102. hash = pair_int_hash(hash, key.domain.hash());
  103. hash = pair_int_hash(hash, key.path.hash());
  104. return hash;
  105. }
  106. };