1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef IOS_NET_COOKIES_COOKIE_STORE_IOS_H_
6 #define IOS_NET_COOKIES_COOKIE_STORE_IOS_H_
13 #include "base/callback.h"
14 #include "base/cancelable_callback.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/threading/thread_checker.h"
17 #include "base/time/time.h"
18 #include "ios/net/cookies/cookie_cache.h"
19 #include "net/cookies/cookie_monster.h"
20 #include "net/cookies/cookie_store.h"
33 class CookieCreationTimeManager
;
35 // Observer for system cookie notifications.
36 class CookieNotificationObserver
{
38 // Called when any cookie is added, deleted or changed in the system store.
39 virtual void OnSystemCookiesChanged() = 0;
40 // Called when the cookie policy changes.
41 virtual void OnSystemCookiePolicyChanged() = 0;
44 // The CookieStoreIOS is an implementation of CookieStore relying on
45 // NSHTTPCookieStorage, ensuring that the cookies are consistent between the
46 // network stack and the UIWebViews.
47 // On iOS, the Chrome CookieMonster is not used in conjunction with UIWebView,
48 // because UIWebView expects the cookies to be in the shared
49 // NSHTTPCookieStorage. In particular, javascript may read and write cookies
51 // CookieStoreIOS is not thread safe.
53 // At any given time, a CookieStoreIOS can either be synchronized with the
54 // system cookie store or not. If a CookieStoreIOS is not synchronized with the
55 // system store, changes are written back to the backing CookieStore. If a
56 // CookieStoreIOS is synchronized with the system store, changes are written
57 // directly to the system cookie store, then propagated to the backing store by
58 // OnSystemCookiesChanged, which is called by the system store once the change
59 // to the system store is written back.
61 // To unsynchronize, CookieStoreIOS copies the system cookie store into its
62 // backing CookieStore. To synchronize, CookieStoreIOS clears the system cookie
63 // store, copies its backing CookieStore into the system cookie store.
64 class CookieStoreIOS
: public net::CookieStore
,
65 public CookieNotificationObserver
{
67 explicit CookieStoreIOS(
68 net::CookieMonster::PersistentCookieStore
* persistent_store
);
70 enum CookiePolicy
{ ALLOW
, BLOCK
};
72 // Must be called on the thread where CookieStoreIOS instances live.
73 static void SetCookiePolicy(CookiePolicy setting
);
75 // Create an instance of CookieStoreIOS that is generated from the cookies
76 // stored in the system NSHTTPCookieStorage. The caller is responsible for
77 // deleting the cookie store.
78 // Apple does not persist the cookies' creation dates in the system store,
79 // so callers should not expect these values to be populated.
80 static CookieStoreIOS
* CreateCookieStoreFromNSHTTPCookieStorage();
82 // As there is only one system store, only one CookieStoreIOS at a time may
83 // be synchronized with it.
84 static void SwitchSynchronizedStore(CookieStoreIOS
* old_store
,
85 CookieStoreIOS
* new_store
);
87 // Must be called when the state of the system cookie store changes.
88 static void NotifySystemCookiesChanged();
90 // Saves the cookies to the cookie monster.
91 // Note: ignores the write cookie operation if |write_on_flush_| is false.
92 void Flush(const base::Closure
& callback
);
94 // Unsynchronizes the cookie store if it is currently synchronized.
97 // Only one cookie store may enable metrics.
98 void SetMetricsEnabled();
100 // Sets the delay between flushes. Only used in tests.
101 void set_flush_delay_for_testing(base::TimeDelta delay
) {
102 flush_delay_
= delay
;
105 // Inherited CookieStore methods.
106 void SetCookieWithOptionsAsync(const GURL
& url
,
107 const std::string
& cookie_line
,
108 const net::CookieOptions
& options
,
109 const SetCookiesCallback
& callback
) override
;
110 void GetCookiesWithOptionsAsync(const GURL
& url
,
111 const net::CookieOptions
& options
,
112 const GetCookiesCallback
& callback
) override
;
113 void GetAllCookiesForURLAsync(const GURL
& url
,
114 const GetCookieListCallback
& callback
) override
;
115 void DeleteCookieAsync(const GURL
& url
,
116 const std::string
& cookie_name
,
117 const base::Closure
& callback
) override
;
118 net::CookieMonster
* GetCookieMonster() override
;
119 void DeleteAllCreatedBetweenAsync(const base::Time
& delete_begin
,
120 const base::Time
& delete_end
,
121 const DeleteCallback
& callback
) override
;
122 void DeleteAllCreatedBetweenForHostAsync(
123 const base::Time delete_begin
,
124 const base::Time delete_end
,
126 const DeleteCallback
& callback
) override
;
127 void DeleteSessionCookiesAsync(const DeleteCallback
& callback
) override
;
129 scoped_ptr
<CookieChangedSubscription
> AddCallbackForCookie(
131 const std::string
& name
,
132 const CookieChangedCallback
& callback
) override
;
135 ~CookieStoreIOS() override
;
139 friend struct CookieStoreIOSTestTraits
;
141 enum SynchronizationState
{
142 NOT_SYNCHRONIZED
, // Uses CookieMonster as backend.
143 SYNCHRONIZING
, // Moves from NSHTTPCookieStorage to CookieMonster.
144 SYNCHRONIZED
// Uses NSHTTPCookieStorage as backend.
147 // Cookie fliter for DeleteCookiesWithFilter().
148 // Takes a cookie and a creation time and returns true if the cookie must be
150 typedef base::Callback
<bool(NSHTTPCookie
*, base::Time
)> CookieFilterFunction
;
152 // Clears the system cookie store.
153 void ClearSystemStore();
154 // Changes the synchronization of the store.
155 // If |synchronized| is true, then the system cookie store is used as a
156 // backend, else |cookie_monster_| is used. Cookies are moved from one to
157 // the other accordingly.
158 void SetSynchronizedWithSystemStore(bool synchronized
);
159 // Returns true if the system cookie store policy is
160 // |NSHTTPCookieAcceptPolicyAlways|.
161 bool SystemCookiesAllowed();
162 // Converts |cookies| to NSHTTPCookie and add them to the system store.
163 void AddCookiesToSystemStore(const net::CookieList
& cookies
);
164 // Copies the cookies to the backing CookieMonster. If the cookie store is not
165 // synchronized with the system store, this is a no-op.
166 void WriteToCookieMonster(NSArray
* system_cookies
);
167 // Runs all the pending tasks.
168 void RunAllPendingTasks();
170 // Inherited CookieNotificationObserver methods.
171 void OnSystemCookiesChanged() override
;
172 void OnSystemCookiePolicyChanged() override
;
174 void DeleteCookiesWithFilter(const CookieFilterFunction
& filter
,
175 const DeleteCallback
& callback
);
177 scoped_refptr
<net::CookieMonster
> cookie_monster_
;
178 scoped_ptr
<CookieCreationTimeManager
> creation_time_manager_
;
179 bool metrics_enabled_
;
180 base::TimeDelta flush_delay_
;
181 base::CancelableClosure flush_closure_
;
183 SynchronizationState synchronization_state_
;
184 // Tasks received when SYNCHRONIZING are queued and run when SYNCHRONIZED.
185 std::vector
<base::Closure
> tasks_pending_synchronization_
;
187 base::ThreadChecker thread_checker_
;
189 // Cookie notification methods.
190 // The cookie cache is updated from both the system store and the
191 // CookieStoreIOS' own mutators. Changes when the CookieStoreIOS is
192 // synchronized are signalled by the system store; changes when the
193 // CookieStoreIOS is not synchronized are signalled by the appropriate
194 // mutators on CookieStoreIOS. The cookie cache tracks the system store when
195 // the CookieStoreIOS is synchronized and the CookieStore when the
196 // CookieStoreIOS is not synchronized.
198 // Fetches any cookies named |name| that would be sent with a request for
199 // |url| from the system cookie store and pushes them onto the back of the
200 // vector pointed to by |cookies|. Returns true if any cookies were pushed
201 // onto the vector, and false otherwise.
202 bool GetSystemCookies(const GURL
& url
,
203 const std::string
& name
,
204 std::vector
<net::CanonicalCookie
>* cookies
);
206 // Updates the cookie cache with the current set of system cookies named
207 // |name| that would be sent with a request for |url|. Returns whether the
209 // |out_removed_cookies|, if not null, will be populated with the cookies that
211 // |out_changed_cookies|, if not null, will be populated with the cookies that
213 bool UpdateCacheForCookieFromSystem(
215 const std::string
& name
,
216 std::vector
<net::CanonicalCookie
>* out_removed_cookies
,
217 std::vector
<net::CanonicalCookie
>* out_added_cookies
);
219 // Runs all callbacks registered for cookies named |name| that would be sent
220 // with a request for |url|.
221 // All cookies in |cookies| must have the name equal to |name|.
222 void RunCallbacksForCookies(const GURL
& url
,
223 const std::string
& name
,
224 const std::vector
<net::CanonicalCookie
>& cookies
,
227 // Called by this CookieStoreIOS' internal CookieMonster instance when
228 // GetAllCookiesForURLAsync() completes. Updates the cookie cache and runs
229 // callbacks if the cache changed.
230 void GotCookieListFor(const std::pair
<GURL
, std::string
> key
,
231 const net::CookieList
& cookies
);
233 // Fetches new values for all (url, name) pairs that have hooks registered,
234 // asynchronously invoking callbacks if necessary.
235 void UpdateCachesFromCookieMonster();
237 // Called after cookies are cleared from NSHTTPCookieStorage so that cookies
238 // can be cleared from .binarycookies file. |callback| is called after all the
239 // cookies are deleted (with the total number of cookies deleted).
240 // |num_deleted| contains the number of cookies deleted from
241 // NSHTTPCookieStorage.
242 void DidClearNSHTTPCookieStorageCookies(const DeleteCallback
& callback
,
244 // Called after cookies are cleared from .binarycookies files. |callback| is
245 // called after all the cookies are deleted with the total number of cookies
247 // |num_deleted_from_nshttp_cookie_storage| contains the number of cookies
248 // deleted from NSHTTPCookieStorage.
249 void DidClearBinaryCookiesFileCookies(
250 const DeleteCallback
& callback
,
251 int num_deleted_from_nshttp_cookie_storage
);
253 // Callback-wrapping:
254 // When this CookieStoreIOS object is synchronized with the system store,
255 // OnSystemCookiesChanged is responsible for updating the cookie cache (and
256 // hence running callbacks).
258 // When this CookieStoreIOS object is not synchronized (or is synchronizing),
259 // the various mutator methods (SetCookieWithOptionsAsync &c) instead store
260 // their state in a CookieMonster object to be written back when the system
261 // store synchronizes. To deliver notifications in a timely manner, the
262 // mutators have to ensure that hooks get run, but only after the changes have
263 // been written back to CookieMonster. To do this, the mutators wrap the
264 // user-supplied callback in a callback which schedules an asynchronous task
265 // to synchronize the cache and run callbacks, then calls through to the
266 // user-specified callback.
268 // These three UpdateCachesAfter functions are responsible for scheduling an
269 // asynchronous cache update (using UpdateCachesFromCookieMonster()) and
270 // calling the provided callback.
272 void UpdateCachesAfterSet(const SetCookiesCallback
& callback
, bool success
);
273 void UpdateCachesAfterDelete(const DeleteCallback
& callback
, int num_deleted
);
274 void UpdateCachesAfterClosure(const base::Closure
& callback
);
276 // These three functions are used for wrapping user-supplied callbacks given
277 // to CookieStoreIOS mutator methods. Given a callback, they return a new
278 // callback that invokes UpdateCachesFromCookieMonster() to schedule an
279 // asynchronous synchronization of the cookie cache and then calls the
280 // original callback.
282 SetCookiesCallback
WrapSetCallback(const SetCookiesCallback
& callback
);
283 DeleteCallback
WrapDeleteCallback(const DeleteCallback
& callback
);
284 base::Closure
WrapClosure(const base::Closure
& callback
);
286 // Cached values of system cookies. Only cookies which have an observer added
287 // with AddCallbackForCookie are kept in this cache.
288 scoped_ptr
<CookieCache
> cookie_cache_
;
290 // Callbacks for cookie changes installed by AddCallbackForCookie.
291 typedef std::map
<std::pair
<GURL
, std::string
>, CookieChangedCallbackList
*>
292 CookieChangedHookMap
;
293 CookieChangedHookMap hook_map_
;
295 DISALLOW_COPY_AND_ASSIGN(CookieStoreIOS
);
300 #endif // IOS_NET_COOKIES_COOKIE_STORE_IOS_H_