#ifndef NET_COOKIES_COOKIE_MONSTER_CHANGE_DISPATCHER_H_
#define NET_COOKIES_COOKIE_MONSTER_CHANGE_DISPATCHER_H_
#include <map>
#include <memory>
#include <string>
#include "base/callback_list.h"
#include "base/containers/linked_list.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/cookies/cookie_partition_key_collection.h"
#include "url/gurl.h"
namespace net {
class CookieAccessDelegate;
class CookieMonster;
class CookieMonsterChangeDispatcher : public CookieChangeDispatcher {
public:
using CookieChangeCallbackList =
base::RepeatingCallbackList<void(const CookieChangeInfo&)>;
explicit CookieMonsterChangeDispatcher(const CookieMonster* cookie_monster);
CookieMonsterChangeDispatcher(const CookieMonsterChangeDispatcher&) = delete;
CookieMonsterChangeDispatcher& operator=(
const CookieMonsterChangeDispatcher&) = delete;
~CookieMonsterChangeDispatcher() override;
static std::string NameKey(std::string name);
static std::string DomainKey(const std::string& domain);
static std::string DomainKey(const GURL& url);
[[nodiscard]] std::unique_ptr<CookieChangeSubscription> AddCallbackForCookie(
const GURL& url,
const std::string& name,
const std::optional<CookiePartitionKey>& cookie_partition_key,
CookieChangeCallback callback) override;
[[nodiscard]] std::unique_ptr<CookieChangeSubscription> AddCallbackForUrl(
const GURL& url,
const std::optional<CookiePartitionKey>& cookie_partition_key,
CookieChangeCallback callback) override;
[[nodiscard]] std::unique_ptr<CookieChangeSubscription>
AddCallbackForAllChanges(CookieChangeCallback callback) override;
void DispatchChange(const CookieChangeInfo& change, bool notify_global_hooks);
private:
class Subscription : public base::LinkNode<Subscription>,
public CookieChangeSubscription {
public:
Subscription(base::WeakPtr<CookieMonsterChangeDispatcher> change_dispatcher,
std::string domain_key,
std::string name_key,
GURL url,
CookiePartitionKeyCollection cookie_partition_key_collection,
net::CookieChangeCallback callback);
Subscription(const Subscription&) = delete;
Subscription& operator=(const Subscription&) = delete;
~Subscription() override;
const std::string& domain_key() const { return domain_key_; }
const std::string& name_key() const { return name_key_; }
void DispatchChange(const CookieChangeInfo& change,
const CookieAccessDelegate* cookie_access_delegate);
private:
base::WeakPtr<CookieMonsterChangeDispatcher> change_dispatcher_;
const std::string domain_key_;
const std::string name_key_;
const GURL url_;
const CookiePartitionKeyCollection cookie_partition_key_collection_;
const net::CookieChangeCallback callback_;
void DoDispatchChange(const CookieChangeInfo& change) const;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<Subscription> weak_ptr_factory_{this};
};
using SubscriptionList = base::LinkedList<Subscription>;
using CookieNameMap = std::map<std::string, SubscriptionList>;
using CookieDomainMap = std::map<std::string, CookieNameMap>;
void DispatchChangeToDomainKey(const CookieChangeInfo& change,
const std::string& domain_key);
void DispatchChangeToNameKey(const CookieChangeInfo& change,
CookieNameMap& name_map,
const std::string& name_key);
void LinkSubscription(Subscription* subscription);
void UnlinkSubscription(Subscription* subscription);
raw_ptr<const CookieMonster> cookie_monster_;
CookieDomainMap cookie_domain_map_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<CookieMonsterChangeDispatcher> weak_ptr_factory_{this};
};
}
#endif