xref: /aosp_15_r20/external/cronet/net/cookies/cookie_change_dispatcher.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_COOKIES_COOKIE_CHANGE_DISPATCHER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_COOKIES_COOKIE_CHANGE_DISPATCHER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/cookies/canonical_cookie.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_access_result.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker class GURL;
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace net {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker class CanonicalCookie;
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // The publicly relevant reasons a cookie might be changed.
23*6777b538SAndroid Build Coastguard Worker enum class CookieChangeCause {
24*6777b538SAndroid Build Coastguard Worker   // The cookie was inserted.
25*6777b538SAndroid Build Coastguard Worker   INSERTED,
26*6777b538SAndroid Build Coastguard Worker   // The cookie was changed directly by a consumer's action.
27*6777b538SAndroid Build Coastguard Worker   EXPLICIT,
28*6777b538SAndroid Build Coastguard Worker   // The cookie was deleted, but no more details are known.
29*6777b538SAndroid Build Coastguard Worker   UNKNOWN_DELETION,
30*6777b538SAndroid Build Coastguard Worker   // The cookie was automatically removed due to an insert operation that
31*6777b538SAndroid Build Coastguard Worker   // overwrote it.
32*6777b538SAndroid Build Coastguard Worker   OVERWRITE,
33*6777b538SAndroid Build Coastguard Worker   // The cookie was automatically removed as it expired.
34*6777b538SAndroid Build Coastguard Worker   EXPIRED,
35*6777b538SAndroid Build Coastguard Worker   // The cookie was automatically evicted during garbage collection.
36*6777b538SAndroid Build Coastguard Worker   EVICTED,
37*6777b538SAndroid Build Coastguard Worker   // The cookie was overwritten with an already-expired expiration date.
38*6777b538SAndroid Build Coastguard Worker   EXPIRED_OVERWRITE
39*6777b538SAndroid Build Coastguard Worker };
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker struct NET_EXPORT CookieChangeInfo {
42*6777b538SAndroid Build Coastguard Worker   CookieChangeInfo();
43*6777b538SAndroid Build Coastguard Worker   CookieChangeInfo(const CanonicalCookie& cookie,
44*6777b538SAndroid Build Coastguard Worker                    CookieAccessResult access_result,
45*6777b538SAndroid Build Coastguard Worker                    CookieChangeCause cause);
46*6777b538SAndroid Build Coastguard Worker   ~CookieChangeInfo();
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   // The cookie that changed.
49*6777b538SAndroid Build Coastguard Worker   CanonicalCookie cookie;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   // The access result of the cookie at the time of the change.
52*6777b538SAndroid Build Coastguard Worker   CookieAccessResult access_result;
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   // The reason for the change.
55*6777b538SAndroid Build Coastguard Worker   CookieChangeCause cause = CookieChangeCause::EXPLICIT;
56*6777b538SAndroid Build Coastguard Worker };
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker // Return a string corresponding to the change cause.  For debugging/logging.
59*6777b538SAndroid Build Coastguard Worker NET_EXPORT const char* CookieChangeCauseToString(CookieChangeCause cause);
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker // Returns whether |cause| is one that could be a reason for deleting a cookie.
62*6777b538SAndroid Build Coastguard Worker // This function assumes that ChangeCause::EXPLICIT is a reason for deletion.
63*6777b538SAndroid Build Coastguard Worker NET_EXPORT bool CookieChangeCauseIsDeletion(CookieChangeCause cause);
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker // Called when a cookie is changed in a CookieStore.
66*6777b538SAndroid Build Coastguard Worker //
67*6777b538SAndroid Build Coastguard Worker // Receives the CanonicalCookie which was added to or removed from the store,
68*6777b538SAndroid Build Coastguard Worker // the CookieAccessSemantics of the cookie at the time of the change event,
69*6777b538SAndroid Build Coastguard Worker // and a CookieStore::ChangeCause indicating if the cookie was added, updated,
70*6777b538SAndroid Build Coastguard Worker // or removed.
71*6777b538SAndroid Build Coastguard Worker //
72*6777b538SAndroid Build Coastguard Worker // Note that the callback is called twice when a cookie is updated: the first
73*6777b538SAndroid Build Coastguard Worker // call communicates the removal of the existing cookie, and the second call
74*6777b538SAndroid Build Coastguard Worker // expresses the addition of the new cookie.
75*6777b538SAndroid Build Coastguard Worker //
76*6777b538SAndroid Build Coastguard Worker // The callback must not synchronously modify any cookie in the CookieStore
77*6777b538SAndroid Build Coastguard Worker // whose change it is observing.
78*6777b538SAndroid Build Coastguard Worker using CookieChangeCallback =
79*6777b538SAndroid Build Coastguard Worker     base::RepeatingCallback<void(const CookieChangeInfo&)>;
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker // Records a listener's interest in CookieStore changes.
82*6777b538SAndroid Build Coastguard Worker //
83*6777b538SAndroid Build Coastguard Worker // Each call to CookieChangeDispatcher::Add*() is a listener expressing an
84*6777b538SAndroid Build Coastguard Worker // interest in observing CookieStore changes. Each call creates a
85*6777b538SAndroid Build Coastguard Worker // CookieChangeSubscription instance whose ownership is passed to the listener.
86*6777b538SAndroid Build Coastguard Worker //
87*6777b538SAndroid Build Coastguard Worker // When the listener's interest disappears (usually at destruction time), the
88*6777b538SAndroid Build Coastguard Worker // listener must communicate this by destroying the CookieChangeSubscription
89*6777b538SAndroid Build Coastguard Worker // instance. The callback passed to the Add*() method will not to be called
90*6777b538SAndroid Build Coastguard Worker // after the returned handle is destroyed.
91*6777b538SAndroid Build Coastguard Worker //
92*6777b538SAndroid Build Coastguard Worker // CookieChangeSubscription instances do not keep the observed CookieStores
93*6777b538SAndroid Build Coastguard Worker // alive.
94*6777b538SAndroid Build Coastguard Worker //
95*6777b538SAndroid Build Coastguard Worker // Instances of this class are not thread-safe, and must be destroyed on the
96*6777b538SAndroid Build Coastguard Worker // same thread that they were obtained on.
97*6777b538SAndroid Build Coastguard Worker class CookieChangeSubscription {
98*6777b538SAndroid Build Coastguard Worker  public:
99*6777b538SAndroid Build Coastguard Worker   CookieChangeSubscription() = default;
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   CookieChangeSubscription(const CookieChangeSubscription&) = delete;
102*6777b538SAndroid Build Coastguard Worker   CookieChangeSubscription& operator=(const CookieChangeSubscription&) = delete;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker   virtual ~CookieChangeSubscription() = default;
105*6777b538SAndroid Build Coastguard Worker };
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker // Exposes changes to a CookieStore's contents.
108*6777b538SAndroid Build Coastguard Worker //
109*6777b538SAndroid Build Coastguard Worker // A component that wishes to react to changes in a CookieStore (the listener)
110*6777b538SAndroid Build Coastguard Worker // must register its interest (subscribe) by calling one of the Add*() methods
111*6777b538SAndroid Build Coastguard Worker // exposed by this interface.
112*6777b538SAndroid Build Coastguard Worker //
113*6777b538SAndroid Build Coastguard Worker // CookieChangeDispatch instances are intended to be embedded in CookieStore
114*6777b538SAndroid Build Coastguard Worker // implementations, so they are not intended to be created as standalone objects
115*6777b538SAndroid Build Coastguard Worker // on the heap.
116*6777b538SAndroid Build Coastguard Worker //
117*6777b538SAndroid Build Coastguard Worker // At the time of this writing (Q1 2018), using this interface has non-trivial
118*6777b538SAndroid Build Coastguard Worker // performance implications on all implementations. This issue should be fixed
119*6777b538SAndroid Build Coastguard Worker // by the end of 2018, at which point this warning should go away. Until then,
120*6777b538SAndroid Build Coastguard Worker // please understand and reason about the performance impact of your change if
121*6777b538SAndroid Build Coastguard Worker // you're adding uses of this to the codebase.
122*6777b538SAndroid Build Coastguard Worker class CookieChangeDispatcher {
123*6777b538SAndroid Build Coastguard Worker  public:
124*6777b538SAndroid Build Coastguard Worker   CookieChangeDispatcher() = default;
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker   CookieChangeDispatcher(const CookieChangeDispatcher&) = delete;
127*6777b538SAndroid Build Coastguard Worker   CookieChangeDispatcher& operator=(const CookieChangeDispatcher&) = delete;
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker   virtual ~CookieChangeDispatcher() = default;
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   // Observe changes to all cookies named `name` that would be sent in a
132*6777b538SAndroid Build Coastguard Worker   // request to `url`.
133*6777b538SAndroid Build Coastguard Worker   //
134*6777b538SAndroid Build Coastguard Worker   // If `cookie_partition_key` is nullopt, then we ignore all change events for
135*6777b538SAndroid Build Coastguard Worker   // partitioned cookies. Otherwise it only subscribes to change events for
136*6777b538SAndroid Build Coastguard Worker   // partitioned cookies with the same provided key.
137*6777b538SAndroid Build Coastguard Worker   // Unpartitioned cookies are not affected by the `cookie_partition_key`
138*6777b538SAndroid Build Coastguard Worker   // parameter.
139*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] virtual std::unique_ptr<CookieChangeSubscription>
140*6777b538SAndroid Build Coastguard Worker   AddCallbackForCookie(
141*6777b538SAndroid Build Coastguard Worker       const GURL& url,
142*6777b538SAndroid Build Coastguard Worker       const std::string& name,
143*6777b538SAndroid Build Coastguard Worker       const std::optional<CookiePartitionKey>& cookie_partition_key,
144*6777b538SAndroid Build Coastguard Worker       CookieChangeCallback callback) = 0;
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   // Observe changes to the cookies that would be sent for a request to `url`.
147*6777b538SAndroid Build Coastguard Worker   //
148*6777b538SAndroid Build Coastguard Worker   // If `cookie_partition_key` is nullopt, then we ignore all change events for
149*6777b538SAndroid Build Coastguard Worker   // partitioned cookies. Otherwise it only subscribes to change events for
150*6777b538SAndroid Build Coastguard Worker   // partitioned cookies with the same provided key.
151*6777b538SAndroid Build Coastguard Worker   // Unpartitioned cookies are not affected by the `cookie_partition_key`
152*6777b538SAndroid Build Coastguard Worker   // parameter.
153*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] virtual std::unique_ptr<CookieChangeSubscription>
154*6777b538SAndroid Build Coastguard Worker   AddCallbackForUrl(
155*6777b538SAndroid Build Coastguard Worker       const GURL& url,
156*6777b538SAndroid Build Coastguard Worker       const std::optional<CookiePartitionKey>& cookie_partition_key,
157*6777b538SAndroid Build Coastguard Worker       CookieChangeCallback callback) = 0;
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   // Observe all the CookieStore's changes.
160*6777b538SAndroid Build Coastguard Worker   //
161*6777b538SAndroid Build Coastguard Worker   // The callback will not observe a few bookkeeping changes.
162*6777b538SAndroid Build Coastguard Worker   // See kChangeCauseMapping in cookie_monster.cc for details.
163*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1225444): Add support for Partitioned cookies.
164*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] virtual std::unique_ptr<CookieChangeSubscription>
165*6777b538SAndroid Build Coastguard Worker   AddCallbackForAllChanges(CookieChangeCallback callback) = 0;
166*6777b538SAndroid Build Coastguard Worker };
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker }  // namespace net
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker #endif  // NET_COOKIES_COOKIE_CHANGE_DISPATCHER_H_
171