xref: /aosp_15_r20/external/cronet/net/cookies/cookie_monster_change_dispatcher.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_COOKIES_COOKIE_MONSTER_CHANGE_DISPATCHER_H_
6 #define NET_COOKIES_COOKIE_MONSTER_CHANGE_DISPATCHER_H_
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 
12 #include "base/callback_list.h"
13 #include "base/containers/linked_list.h"
14 #include "base/functional/callback.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/memory/scoped_refptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/task/single_thread_task_runner.h"
19 #include "base/threading/thread_checker.h"
20 #include "net/cookies/cookie_change_dispatcher.h"
21 #include "net/cookies/cookie_partition_key_collection.h"
22 #include "url/gurl.h"
23 
24 namespace net {
25 
26 class CookieAccessDelegate;
27 class CookieMonster;
28 
29 // CookieChangeDispatcher implementation used by CookieMonster.
30 class CookieMonsterChangeDispatcher : public CookieChangeDispatcher {
31  public:
32   using CookieChangeCallbackList =
33       base::RepeatingCallbackList<void(const CookieChangeInfo&)>;
34 
35   // Expects |cookie_monster| to outlive this.
36   explicit CookieMonsterChangeDispatcher(const CookieMonster* cookie_monster);
37 
38   CookieMonsterChangeDispatcher(const CookieMonsterChangeDispatcher&) = delete;
39   CookieMonsterChangeDispatcher& operator=(
40       const CookieMonsterChangeDispatcher&) = delete;
41 
42   ~CookieMonsterChangeDispatcher() override;
43 
44   // The key in CookieNameMap for a cookie name.
45   static std::string NameKey(std::string name);
46 
47   // The key in CookieDomainName for a cookie domain.
48   static std::string DomainKey(const std::string& domain);
49 
50   // The key in CookieDomainName for a listener URL.
51   static std::string DomainKey(const GURL& url);
52 
53   // net::CookieChangeDispatcher
54   [[nodiscard]] std::unique_ptr<CookieChangeSubscription> AddCallbackForCookie(
55       const GURL& url,
56       const std::string& name,
57       const std::optional<CookiePartitionKey>& cookie_partition_key,
58       CookieChangeCallback callback) override;
59   [[nodiscard]] std::unique_ptr<CookieChangeSubscription> AddCallbackForUrl(
60       const GURL& url,
61       const std::optional<CookiePartitionKey>& cookie_partition_key,
62       CookieChangeCallback callback) override;
63   [[nodiscard]] std::unique_ptr<CookieChangeSubscription>
64   AddCallbackForAllChanges(CookieChangeCallback callback) override;
65 
66   // |notify_global_hooks| is true if the function should run the
67   // global hooks in addition to the per-cookie hooks.
68   //
69   // TODO(pwnall): Remove |notify_global_hooks| and fix consumers.
70   void DispatchChange(const CookieChangeInfo& change, bool notify_global_hooks);
71 
72  private:
73   class Subscription : public base::LinkNode<Subscription>,
74                        public CookieChangeSubscription {
75    public:
76     Subscription(base::WeakPtr<CookieMonsterChangeDispatcher> change_dispatcher,
77                  std::string domain_key,
78                  std::string name_key,
79                  GURL url,
80                  CookiePartitionKeyCollection cookie_partition_key_collection,
81                  net::CookieChangeCallback callback);
82 
83     Subscription(const Subscription&) = delete;
84     Subscription& operator=(const Subscription&) = delete;
85 
86     ~Subscription() override;
87 
88     // The lookup key used in the domain subscription map.
89     //
90     // The empty string means no domain filtering.
domain_key()91     const std::string& domain_key() const { return domain_key_; }
92     // The lookup key used in the name subscription map.
93     //
94     // The empty string means no name filtering.
name_key()95     const std::string& name_key() const { return name_key_; }
96 
97     // Dispatches a cookie change notification if the listener is interested.
98     void DispatchChange(const CookieChangeInfo& change,
99                         const CookieAccessDelegate* cookie_access_delegate);
100 
101    private:
102     base::WeakPtr<CookieMonsterChangeDispatcher> change_dispatcher_;
103     const std::string domain_key_;  // kGlobalDomainKey means no filtering.
104     const std::string name_key_;    // kGlobalNameKey means no filtering.
105     const GURL url_;                // empty() means no URL-based filtering.
106     const CookiePartitionKeyCollection cookie_partition_key_collection_;
107     const net::CookieChangeCallback callback_;
108 
109     void DoDispatchChange(const CookieChangeInfo& change) const;
110 
111     // Used to post DoDispatchChange() calls to this subscription's thread.
112     scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
113 
114     THREAD_CHECKER(thread_checker_);
115 
116     // Used to cancel delayed calls to DoDispatchChange() when the subscription
117     // gets destroyed.
118     base::WeakPtrFactory<Subscription> weak_ptr_factory_{this};
119   };
120 
121   // The last level of the subscription data structures.
122   using SubscriptionList = base::LinkedList<Subscription>;
123 
124   // Buckets subscriptions according to cookie names.
125   //
126   // Map keys are cookie names, as we only support exact name matching.
127   using CookieNameMap = std::map<std::string, SubscriptionList>;
128 
129   // Buckets subscriptions according to cookie domains.
130   //
131   // Map keys are the eTLD+1 of cookie domains. Cookies are either host-locked,
132   // or visible to all the subdomain of a given domain. A cookie's scope cannot
133   // exceed eTLD+1, so we stop there.
134   using CookieDomainMap = std::map<std::string, CookieNameMap>;
135 
136   void DispatchChangeToDomainKey(const CookieChangeInfo& change,
137                                  const std::string& domain_key);
138 
139   void DispatchChangeToNameKey(const CookieChangeInfo& change,
140                                CookieNameMap& name_map,
141                                const std::string& name_key);
142 
143   // Inserts a subscription into the map.
144   //
145   // Called by the AddCallback* methods, after creating the Subscription.
146   void LinkSubscription(Subscription* subscription);
147 
148   // Removes a subscription from the map.
149   //
150   // Called by the Subscription destructor.
151   void UnlinkSubscription(Subscription* subscription);
152 
153   raw_ptr<const CookieMonster> cookie_monster_;
154 
155   CookieDomainMap cookie_domain_map_;
156 
157   THREAD_CHECKER(thread_checker_);
158 
159   // Vends weak pointers to subscriptions.
160   base::WeakPtrFactory<CookieMonsterChangeDispatcher> weak_ptr_factory_{this};
161 };
162 
163 }  // namespace net
164 
165 #endif  // NET_COOKIES_COOKIE_MONSTER_CHANGE_DISPATCHER_H_
166