| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Brought to you by the letter D and the number 2. | 
 |  | 
 | #ifndef NET_COOKIES_COOKIE_MONSTER_H_ | 
 | #define NET_COOKIES_COOKIE_MONSTER_H_ | 
 |  | 
 | #include <map> | 
 | #include <memory> | 
 | #include <set> | 
 | #include <string> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include "base/callback_forward.h" | 
 | #include "base/containers/circular_deque.h" | 
 | #include "base/gtest_prod_util.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/strings/string_piece.h" | 
 | #include "base/threading/thread_checker.h" | 
 | #include "base/time/time.h" | 
 | #include "net/base/net_export.h" | 
 | #include "net/cookies/canonical_cookie.h" | 
 | #include "net/cookies/cookie_constants.h" | 
 | #include "net/cookies/cookie_monster_change_dispatcher.h" | 
 | #include "net/cookies/cookie_store.h" | 
 | #include "net/log/net_log_with_source.h" | 
 | #include "starboard/types.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | namespace base { | 
 | class HistogramBase; | 
 | }  // namespace base | 
 |  | 
 | namespace net { | 
 |  | 
 | class ChannelIDService; | 
 | class CookieChangeDispatcher; | 
 |  | 
 | // The cookie monster is the system for storing and retrieving cookies. It has | 
 | // an in-memory list of all cookies, and synchronizes non-session cookies to an | 
 | // optional permanent storage that implements the PersistentCookieStore | 
 | // interface. | 
 | // | 
 | // Tasks may be deferred if all affected cookies are not yet loaded from the | 
 | // backing store. Otherwise, callbacks may be invoked immediately. | 
 | // | 
 | // A cookie task is either pending loading of the entire cookie store, or | 
 | // loading of cookies for a specific domain key (GetKey(), roughly eTLD+1). In | 
 | // the former case, the cookie callback will be queued in tasks_pending_ while | 
 | // PersistentCookieStore chain loads the cookie store on DB thread. In the | 
 | // latter case, the cookie callback will be queued in tasks_pending_for_key_ | 
 | // while PermanentCookieStore loads cookies for the specified domain key on DB | 
 | // thread. | 
 | class NET_EXPORT CookieMonster : public CookieStore { | 
 |  public: | 
 |   class PersistentCookieStore; | 
 |  | 
 |   // Terminology: | 
 |   //    * The 'top level domain' (TLD) of an internet domain name is | 
 |   //      the terminal "." free substring (e.g. "com" for google.com | 
 |   //      or world.std.com). | 
 |   //    * The 'effective top level domain' (eTLD) is the longest | 
 |   //      "." initiated terminal substring of an internet domain name | 
 |   //      that is controlled by a general domain registrar. | 
 |   //      (e.g. "co.uk" for news.bbc.co.uk). | 
 |   //    * The 'effective top level domain plus one' (eTLD+1) is the | 
 |   //      shortest "." delimited terminal substring of an internet | 
 |   //      domain name that is not controlled by a general domain | 
 |   //      registrar (e.g. "bbc.co.uk" for news.bbc.co.uk, or | 
 |   //      "google.com" for news.google.com).  The general assumption | 
 |   //      is that all hosts and domains under an eTLD+1 share some | 
 |   //      administrative control. | 
 |  | 
 |   // CookieMap is the central data structure of the CookieMonster.  It | 
 |   // is a map whose values are pointers to CanonicalCookie data | 
 |   // structures (the data structures are owned by the CookieMonster | 
 |   // and must be destroyed when removed from the map).  The key is based on the | 
 |   // effective domain of the cookies.  If the domain of the cookie has an | 
 |   // eTLD+1, that is the key for the map.  If the domain of the cookie does not | 
 |   // have an eTLD+1, the key of the map is the host the cookie applies to (it is | 
 |   // not legal to have domain cookies without an eTLD+1).  This rule | 
 |   // excludes cookies for, e.g, ".com", ".co.uk", or ".internalnetwork". | 
 |   // This behavior is the same as the behavior in Firefox v 3.6.10. | 
 |  | 
 |   // NOTE(deanm): | 
 |   // I benchmarked hash_multimap vs multimap.  We're going to be query-heavy | 
 |   // so it would seem like hashing would help.  However they were very | 
 |   // close, with multimap being a tiny bit faster.  I think this is because | 
 |   // our map is at max around 1000 entries, and the additional complexity | 
 |   // for the hashing might not overcome the O(log(1000)) for querying | 
 |   // a multimap.  Also, multimap is standard, another reason to use it. | 
 |   // TODO(rdsmith): This benchmark should be re-done now that we're allowing | 
 |   // substantially more entries in the map. | 
 |   using CookieMap = | 
 |       std::multimap<std::string, std::unique_ptr<CanonicalCookie>>; | 
 |   using CookieMapItPair = std::pair<CookieMap::iterator, CookieMap::iterator>; | 
 |   using CookieItVector = std::vector<CookieMap::iterator>; | 
 |  | 
 |   // Cookie garbage collection thresholds.  Based off of the Mozilla defaults. | 
 |   // When the number of cookies gets to k{Domain,}MaxCookies | 
 |   // purge down to k{Domain,}MaxCookies - k{Domain,}PurgeCookies. | 
 |   // It might seem scary to have a high purge value, but really it's not. | 
 |   // You just make sure that you increase the max to cover the increase | 
 |   // in purge, and we would have been purging the same number of cookies. | 
 |   // We're just going through the garbage collection process less often. | 
 |   // Note that the DOMAIN values are per eTLD+1; see comment for the | 
 |   // CookieMap typedef.  So, e.g., the maximum number of cookies allowed for | 
 |   // google.com and all of its subdomains will be 150-180. | 
 |   // | 
 |   // Any cookies accessed more recently than kSafeFromGlobalPurgeDays will not | 
 |   // be evicted by global garbage collection, even if we have more than | 
 |   // kMaxCookies.  This does not affect domain garbage collection. | 
 |   static const size_t kDomainMaxCookies; | 
 |   static const size_t kDomainPurgeCookies; | 
 |   static const size_t kMaxCookies; | 
 |   static const size_t kPurgeCookies; | 
 |  | 
 |   // Quota for cookies with {low, medium, high} priorities within a domain. | 
 |   static const size_t kDomainCookiesQuotaLow; | 
 |   static const size_t kDomainCookiesQuotaMedium; | 
 |   static const size_t kDomainCookiesQuotaHigh; | 
 |  | 
 |   // The store passed in should not have had Init() called on it yet. This | 
 |   // class will take care of initializing it. The backing store is NOT owned by | 
 |   // this class, but it must remain valid for the duration of the cookie | 
 |   // monster's existence. If |store| is NULL, then no backing store will be | 
 |   // updated. |channel_id_service| is a non-owninng pointer for the | 
 |   // corresponding ChannelIDService used with this CookieStore. The | 
 |   // |channel_id_service| must outlive the CookieMonster. |net_log| must outlive | 
 |   // the CookieMonster. Both |channel_id_service| and |net_log| can be null. | 
 |   CookieMonster(scoped_refptr<PersistentCookieStore> store, | 
 |                 ChannelIDService* channel_id_service, | 
 |                 NetLog* net_log); | 
 |  | 
 |   // Only used during unit testing. | 
 |   // |net_log| must outlive the CookieMonster. | 
 |   CookieMonster(scoped_refptr<PersistentCookieStore> store, | 
 |                 base::TimeDelta last_access_threshold, | 
 |                 NetLog* net_log); | 
 |  | 
 |   ~CookieMonster() override; | 
 |  | 
 |   // Writes all the cookies in |list| into the store, replacing all cookies | 
 |   // currently present in store. | 
 |   // This method does not flush the backend. | 
 |   // TODO(rdsmith, mmenke): Do not use this function; it is deprecated | 
 |   // and should be removed. | 
 |   // See https://codereview.chromium.org/2882063002/#msg64. | 
 |   void SetAllCookiesAsync(const CookieList& list, SetCookiesCallback callback); | 
 |  | 
 |   // CookieStore implementation. | 
 |   void SetCookieWithOptionsAsync(const GURL& url, | 
 |                                  const std::string& cookie_line, | 
 |                                  const CookieOptions& options, | 
 |                                  SetCookiesCallback callback) override; | 
 |   void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, | 
 |                                bool secure_source, | 
 |                                bool modify_http_only, | 
 |                                SetCookiesCallback callback) override; | 
 |   void GetCookieListWithOptionsAsync(const GURL& url, | 
 |                                      const CookieOptions& options, | 
 |                                      GetCookieListCallback callback) override; | 
 |   void GetAllCookiesAsync(GetCookieListCallback callback) override; | 
 |   void DeleteCookieAsync(const GURL& url, | 
 |                          const std::string& cookie_name, | 
 |                          base::OnceClosure callback) override; | 
 |   void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie, | 
 |                                   DeleteCallback callback) override; | 
 |   void DeleteAllCreatedInTimeRangeAsync( | 
 |       const CookieDeletionInfo::TimeRange& creation_range, | 
 |       DeleteCallback callback) override; | 
 |   void DeleteAllMatchingInfoAsync(CookieDeletionInfo delete_info, | 
 |                                   DeleteCallback callback) override; | 
 |   void DeleteSessionCookiesAsync(DeleteCallback) override; | 
 |   void FlushStore(base::OnceClosure callback) override; | 
 |   void SetForceKeepSessionState() override; | 
 |   CookieChangeDispatcher& GetChangeDispatcher() override; | 
 |  | 
 |   // Resets the list of cookieable schemes to the supplied schemes. Does | 
 |   // nothing if called after first use of the instance (i.e. after the | 
 |   // instance initialization process). | 
 |   void SetCookieableSchemes(const std::vector<std::string>& schemes); | 
 |  | 
 |   // Enables writing session cookies into the cookie database. If this this | 
 |   // method is called, it must be called before first use of the instance | 
 |   // (i.e. as part of the instance initialization process). | 
 |   void SetPersistSessionCookies(bool persist_session_cookies); | 
 |  | 
 |   // Determines if the scheme of the URL is a scheme that cookies will be | 
 |   // stored for. | 
 |   bool IsCookieableScheme(const std::string& scheme); | 
 |  | 
 |   // The default list of schemes the cookie monster can handle. | 
 |   static const char* const kDefaultCookieableSchemes[]; | 
 |   static const int kDefaultCookieableSchemesCount; | 
 |  | 
 |   bool IsEphemeral() override; | 
 |  | 
 |   void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd, | 
 |                        const std::string& parent_absolute_name) const override; | 
 |  | 
 |   // Find a key based on the given domain, which will be used to find all | 
 |   // cookies potentially relevant to it. This is used for lookup in cookies_ as | 
 |   // well as for PersistentCookieStore::LoadCookiesForKey. See comment on keys | 
 |   // before the CookieMap typedef. | 
 |   static std::string GetKey(base::StringPiece domain); | 
 |  | 
 |  private: | 
 |   CookieMonster(scoped_refptr<PersistentCookieStore> store, | 
 |                 ChannelIDService* channel_id_service, | 
 |                 base::TimeDelta last_access_threshold, | 
 |                 NetLog* net_log); | 
 |  | 
 |   // For garbage collection constants. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, GarbageCollectionTriggers); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, | 
 |                            GarbageCollectWithSecureCookiesOnly); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestGCTimes); | 
 |  | 
 |   // For validation of key values. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestDomainTree); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestImport); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, GetKey); | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestGetKey); | 
 |  | 
 |   // For FindCookiesForKey. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, ShortLivedSessionCookies); | 
 |  | 
 |   // For CookieSource histogram enum. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, CookieSourceHistogram); | 
 |  | 
 |   // For kSafeFromGlobalPurgeDays in CookieStore. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, EvictSecureCookies); | 
 |  | 
 |   // For CookieDeleteEquivalent histogram enum. | 
 |   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, | 
 |                            CookieDeleteEquivalentHistogramTest); | 
 |  | 
 |   // Internal reasons for deletion, used to populate informative histograms | 
 |   // and to provide a public cause for onCookieChange notifications. | 
 |   // | 
 |   // If you add or remove causes from this list, please be sure to also update | 
 |   // the CookieChangeCause mapping inside ChangeCauseMapping. New items (if | 
 |   // necessary) should be added at the end of the list, just before | 
 |   // DELETE_COOKIE_LAST_ENTRY. | 
 |   enum DeletionCause { | 
 |     DELETE_COOKIE_EXPLICIT = 0, | 
 |     DELETE_COOKIE_OVERWRITE = 1, | 
 |     DELETE_COOKIE_EXPIRED = 2, | 
 |     DELETE_COOKIE_EVICTED = 3, | 
 |     DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE = 4, | 
 |     DELETE_COOKIE_DONT_RECORD = 5,  // For final cleanup after flush to store. | 
 |  | 
 |     // Cookies evicted during domain-level garbage collection. | 
 |     DELETE_COOKIE_EVICTED_DOMAIN = 6, | 
 |  | 
 |     // Cookies evicted during global garbage collection (which takes place after | 
 |     // domain-level garbage collection fails to bring the cookie store under | 
 |     // the overall quota. | 
 |     DELETE_COOKIE_EVICTED_GLOBAL = 7, | 
 |  | 
 |     // #8 was DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE | 
 |     // #9 was DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE | 
 |  | 
 |     // A common idiom is to remove a cookie by overwriting it with an | 
 |     // already-expired expiration date. This captures that case. | 
 |     DELETE_COOKIE_EXPIRED_OVERWRITE = 10, | 
 |  | 
 |     // Cookies are not allowed to contain control characters in the name or | 
 |     // value. However, we used to allow them, so we are now evicting any such | 
 |     // cookies as we load them. See http://crbug.com/238041. | 
 |     DELETE_COOKIE_CONTROL_CHAR = 11, | 
 |  | 
 |     // When strict secure cookies is enabled, non-secure cookies are evicted | 
 |     // right after expired cookies. | 
 |     DELETE_COOKIE_NON_SECURE = 12, | 
 |  | 
 |     DELETE_COOKIE_LAST_ENTRY = 13 | 
 |   }; | 
 |  | 
 |   // This enum is used to generate a histogramed bitmask measureing the types | 
 |   // of stored cookies. Please do not reorder the list when adding new entries. | 
 |   // New items MUST be added at the end of the list, just before | 
 |   // COOKIE_TYPE_LAST_ENTRY; | 
 |   enum CookieType { | 
 |     COOKIE_TYPE_SAME_SITE = 0, | 
 |     COOKIE_TYPE_HTTPONLY, | 
 |     COOKIE_TYPE_SECURE, | 
 |     COOKIE_TYPE_LAST_ENTRY | 
 |   }; | 
 |  | 
 |   // Used to populate a histogram containing information about the | 
 |   // sources of Secure and non-Secure cookies: that is, whether such | 
 |   // cookies are set by origins with cryptographic or non-cryptographic | 
 |   // schemes. Please do not reorder the list when adding new | 
 |   // entries. New items MUST be added at the end of the list, just | 
 |   // before COOKIE_SOURCE_LAST_ENTRY. | 
 |   // | 
 |   // COOKIE_SOURCE_(NON)SECURE_COOKIE_(NON)CRYPTOGRAPHIC_SCHEME means | 
 |   // that a cookie was set or overwritten from a URL with the given type | 
 |   // of scheme. This enum should not be used when cookies are *cleared*, | 
 |   // because its purpose is to understand if Chrome can deprecate the | 
 |   // ability of HTTP urls to set/overwrite Secure cookies. | 
 |   enum CookieSource { | 
 |     COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME = 0, | 
 |     COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, | 
 |     COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, | 
 |     COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, | 
 |     COOKIE_SOURCE_LAST_ENTRY | 
 |   }; | 
 |  | 
 |   // Used to populate a histogram for cookie setting in the "delete equivalent" | 
 |   // step. Measures total attempts to delete an equivalent cookie, and | 
 |   // categorizes the outcome. | 
 |   // | 
 |   // * COOKIE_DELETE_EQUIVALENT_ATTEMPT is incremented each time a cookie is | 
 |   //   set, causing the equivalent deletion algorithm to execute. | 
 |   // | 
 |   // * COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE is incremented when a non-secure | 
 |   //   cookie is ignored because an equivalent, but secure, cookie already | 
 |   //   exists. | 
 |   // | 
 |   // * COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED is incremented when a cookie | 
 |   //   is skipped due to `secure` rules (e.g. whenever | 
 |   //   COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE is incremented), but would have | 
 |   //   caused a deletion without those rules. | 
 |   // | 
 |   //   TODO(mkwst): Now that we've shipped strict secure cookie checks, we don't | 
 |   //   need this value anymore. | 
 |   // | 
 |   // * COOKIE_DELETE_EQUIVALENT_FOUND is incremented each time an equivalent | 
 |   //   cookie is found (and deleted). | 
 |   // | 
 |   // * COOKIE_DELETE_EQUIVALENT_FOUND_WITH_SAME_VALUE is incremented each time | 
 |   //   an equivalent cookie that also shared the same value with the new cookie | 
 |   //   is found (and deleted). | 
 |   // | 
 |   // Please do not reorder or remove entries. New entries must be added to the | 
 |   // end of the list, just before COOKIE_DELETE_EQUIVALENT_LAST_ENTRY. | 
 |   enum CookieDeleteEquivalent { | 
 |     COOKIE_DELETE_EQUIVALENT_ATTEMPT = 0, | 
 |     COOKIE_DELETE_EQUIVALENT_FOUND, | 
 |     COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE, | 
 |     COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED, | 
 |     COOKIE_DELETE_EQUIVALENT_FOUND_WITH_SAME_VALUE, | 
 |     COOKIE_DELETE_EQUIVALENT_LAST_ENTRY | 
 |   }; | 
 |  | 
 |   // The number of days since last access that cookies will not be subject | 
 |   // to global garbage collection. | 
 |   static const int kSafeFromGlobalPurgeDays; | 
 |  | 
 |   // Record statistics every kRecordStatisticsIntervalSeconds of uptime. | 
 |   static const int kRecordStatisticsIntervalSeconds = 10 * 60; | 
 |  | 
 |   // Sets a canonical cookie, deletes equivalents and performs garbage | 
 |   // collection.  |source_secure| indicates if the cookie is being set | 
 |   // from a secure source (e.g. a cryptographic scheme). | 
 |   // |modify_http_only| indicates if this setting operation is allowed | 
 |   // to affect http_only cookies. | 
 |   void SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cookie, | 
 |                           bool secure_source, | 
 |                           bool can_modify_httponly, | 
 |                           SetCookiesCallback callback); | 
 |  | 
 |   void GetAllCookies(GetCookieListCallback callback); | 
 |  | 
 |   void GetCookieListWithOptions(const GURL& url, | 
 |                                 const CookieOptions& options, | 
 |                                 GetCookieListCallback callback); | 
 |  | 
 |   void DeleteAllCreatedInTimeRange( | 
 |       const CookieDeletionInfo::TimeRange& creation_range, | 
 |       DeleteCallback callback); | 
 |  | 
 |   void DeleteAllMatchingInfo(net::CookieDeletionInfo delete_info, | 
 |                              DeleteCallback callback); | 
 |  | 
 |   void SetCookieWithOptions(const GURL& url, | 
 |                             const std::string& cookie_line, | 
 |                             const CookieOptions& options, | 
 |                             SetCookiesCallback callback); | 
 |  | 
 |   void DeleteCookie(const GURL& url, | 
 |                     const std::string& cookie_name, | 
 |                     base::OnceClosure callback); | 
 |  | 
 |   void DeleteCanonicalCookie(const CanonicalCookie& cookie, | 
 |                              DeleteCallback callback); | 
 |  | 
 |   void DeleteSessionCookies(DeleteCallback callback); | 
 |  | 
 |   // The first access to the cookie store initializes it. This method should be | 
 |   // called before any access to the cookie store. | 
 |   void MarkCookieStoreAsInitialized(); | 
 |  | 
 |   // Fetches all cookies if the backing store exists and they're not already | 
 |   // being fetched. | 
 |   void FetchAllCookiesIfNecessary(); | 
 |  | 
 |   // Fetches all cookies from the backing store. | 
 |   void FetchAllCookies(); | 
 |  | 
 |   // Whether all cookies should be fetched as soon as any is requested. | 
 |   bool ShouldFetchAllCookiesWhenFetchingAnyCookie(); | 
 |  | 
 |   // Stores cookies loaded from the backing store and invokes any deferred | 
 |   // calls. |beginning_time| should be the moment PersistentCookieStore::Load | 
 |   // was invoked and is used for reporting histogram_time_blocked_on_load_. | 
 |   // See PersistentCookieStore::Load for details on the contents of cookies. | 
 |   void OnLoaded(base::TimeTicks beginning_time, | 
 |                 std::vector<std::unique_ptr<CanonicalCookie>> cookies); | 
 |  | 
 |   // Stores cookies loaded from the backing store and invokes the deferred | 
 |   // task(s) pending loading of cookies associated with the domain key | 
 |   // (GetKey, roughly eTLD+1). Called when all cookies for the domain key have | 
 |   // been loaded from DB. See PersistentCookieStore::Load for details on the | 
 |   // contents of cookies. | 
 |   void OnKeyLoaded(const std::string& key, | 
 |                    std::vector<std::unique_ptr<CanonicalCookie>> cookies); | 
 |  | 
 |   // Stores the loaded cookies. | 
 |   void StoreLoadedCookies( | 
 |       std::vector<std::unique_ptr<CanonicalCookie>> cookies); | 
 |  | 
 |   // Invokes deferred calls. | 
 |   void InvokeQueue(); | 
 |  | 
 |   // Checks that |cookies_| matches our invariants, and tries to repair any | 
 |   // inconsistencies. (In other words, it does not have duplicate cookies). | 
 |   void EnsureCookiesMapIsValid(); | 
 |  | 
 |   // Checks for any duplicate cookies for CookieMap key |key| which lie between | 
 |   // |begin| and |end|. If any are found, all but the most recent are deleted. | 
 |   void TrimDuplicateCookiesForKey(const std::string& key, | 
 |                                   CookieMap::iterator begin, | 
 |                                   CookieMap::iterator end); | 
 |  | 
 |   void SetDefaultCookieableSchemes(); | 
 |  | 
 |   void FindCookiesForHostAndDomain(const GURL& url, | 
 |                                    const CookieOptions& options, | 
 |                                    std::vector<CanonicalCookie*>* cookies); | 
 |  | 
 |   void FindCookiesForKey(const std::string& key, | 
 |                          const GURL& url, | 
 |                          const CookieOptions& options, | 
 |                          const base::Time& current, | 
 |                          std::vector<CanonicalCookie*>* cookies); | 
 |  | 
 |   // Delete any cookies that are equivalent to |ecc| (same path, domain, etc). | 
 |   // |source_secure| indicates if the source may override existing secure | 
 |   // cookies. | 
 |   // | 
 |   // If |skip_httponly| is true, httponly cookies will not be deleted.  The | 
 |   // return value will be true if |skip_httponly| skipped an httponly cookie or | 
 |   // the cookie to delete was Secure and the scheme of |ecc| is insecure.  |key| | 
 |   // is the key to find the cookie in cookies_; see the comment before the | 
 |   // CookieMap typedef for details. | 
 |   // | 
 |   // If a cookie is deleted, and its value matches |ecc|'s value, then | 
 |   // |creation_date_to_inherit| will be set to that cookie's creation date. | 
 |   // | 
 |   // NOTE: There should never be more than a single matching equivalent cookie. | 
 |   bool DeleteAnyEquivalentCookie(const std::string& key, | 
 |                                  const CanonicalCookie& ecc, | 
 |                                  bool source_secure, | 
 |                                  bool skip_httponly, | 
 |                                  bool already_expired, | 
 |                                  base::Time* creation_date_to_inherit); | 
 |  | 
 |   // Inserts |cc| into cookies_. Returns an iterator that points to the inserted | 
 |   // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid. | 
 |   CookieMap::iterator InternalInsertCookie(const std::string& key, | 
 |                                            std::unique_ptr<CanonicalCookie> cc, | 
 |                                            bool sync_to_store); | 
 |  | 
 |   // Sets all cookies from |list| after deleting any equivalent cookie. | 
 |   // For data gathering purposes, this routine is treated as if it is | 
 |   // restoring saved cookies; some statistics are not gathered in this case. | 
 |   void SetAllCookies(CookieList list, SetCookiesCallback callback); | 
 |  | 
 |   void InternalUpdateCookieAccessTime(CanonicalCookie* cc, | 
 |                                       const base::Time& current_time); | 
 |  | 
 |   // |deletion_cause| argument is used for collecting statistics and choosing | 
 |   // the correct CookieChangeCause for OnCookieChange notifications. Guarantee: | 
 |   // All iterators to cookies_, except for the deleted entry, remain valid. | 
 |   void InternalDeleteCookie(CookieMap::iterator it, | 
 |                             bool sync_to_store, | 
 |                             DeletionCause deletion_cause); | 
 |  | 
 |   // If the number of cookies for CookieMap key |key|, or globally, are | 
 |   // over the preset maximums above, garbage collect, first for the host and | 
 |   // then globally.  See comments above garbage collection threshold | 
 |   // constants for details. | 
 |   // | 
 |   // Returns the number of cookies deleted (useful for debugging). | 
 |   size_t GarbageCollect(const base::Time& current, const std::string& key); | 
 |  | 
 |   // Helper for GarbageCollect(). Deletes up to |purge_goal| cookies with a | 
 |   // priority less than or equal to |priority| from |cookies|, while ensuring | 
 |   // that at least the |to_protect| most-recent cookies are retained. | 
 |   // |protected_secure_cookies| specifies whether or not secure cookies should | 
 |   // be protected from deletion. | 
 |   // | 
 |   // |cookies| must be sorted from least-recent to most-recent. | 
 |   // | 
 |   // Returns the number of cookies deleted. | 
 |   size_t PurgeLeastRecentMatches(CookieItVector* cookies, | 
 |                                  CookiePriority priority, | 
 |                                  size_t to_protect, | 
 |                                  size_t purge_goal, | 
 |                                  bool protect_secure_cookies); | 
 |  | 
 |   // Helper for GarbageCollect(); can be called directly as well.  Deletes all | 
 |   // expired cookies in |itpair|.  If |cookie_its| is non-NULL, all the | 
 |   // non-expired cookies from |itpair| are appended to |cookie_its|. | 
 |   // | 
 |   // Returns the number of cookies deleted. | 
 |   size_t GarbageCollectExpired(const base::Time& current, | 
 |                                const CookieMapItPair& itpair, | 
 |                                CookieItVector* cookie_its); | 
 |  | 
 |   // Helper for GarbageCollect(). Deletes all cookies in the range specified by | 
 |   // [|it_begin|, |it_end|). Returns the number of cookies deleted. | 
 |   size_t GarbageCollectDeleteRange(const base::Time& current, | 
 |                                    DeletionCause cause, | 
 |                                    CookieItVector::iterator cookie_its_begin, | 
 |                                    CookieItVector::iterator cookie_its_end); | 
 |  | 
 |   // Helper for GarbageCollect(). Deletes cookies in |cookie_its| from least to | 
 |   // most recently used, but only before |safe_date|. Also will stop deleting | 
 |   // when the number of remaining cookies hits |purge_goal|. | 
 |   // | 
 |   // Sets |earliest_time| to be the earliest last access time of a cookie that | 
 |   // was not deleted, or base::Time() if no such cookie exists. | 
 |   size_t GarbageCollectLeastRecentlyAccessed(const base::Time& current, | 
 |                                              const base::Time& safe_date, | 
 |                                              size_t purge_goal, | 
 |                                              CookieItVector cookie_its, | 
 |                                              base::Time* earliest_time); | 
 |  | 
 |   bool HasCookieableScheme(const GURL& url); | 
 |  | 
 |   // Statistics support | 
 |  | 
 |   // This function should be called repeatedly, and will record | 
 |   // statistics if a sufficient time period has passed. | 
 |   void RecordPeriodicStats(const base::Time& current_time); | 
 |  | 
 |   // Initialize the above variables; should only be called from | 
 |   // the constructor. | 
 |   void InitializeHistograms(); | 
 |  | 
 |   // The resolution of our time isn't enough, so we do something | 
 |   // ugly and increment when we've seen the same time twice. | 
 |   base::Time CurrentTime(); | 
 |  | 
 |   // Defers the callback until the full coookie database has been loaded. If | 
 |   // it's already been loaded, runs the callback synchronously. | 
 |   void DoCookieCallback(base::OnceClosure callback); | 
 |  | 
 |   // Defers the callback until the cookies relevant to given URL have been | 
 |   // loaded. If they've already been loaded, runs the callback synchronously. | 
 |   void DoCookieCallbackForURL(base::OnceClosure callback, const GURL& url); | 
 |  | 
 |   // Defers the callback until the cookies relevant to given host or domain | 
 |   // have been loaded. If they've already been loaded, runs the callback | 
 |   // synchronously. | 
 |   void DoCookieCallbackForHostOrDomain(base::OnceClosure callback, | 
 |                                        base::StringPiece host_or_domain); | 
 |  | 
 |   // Histogram variables; see CookieMonster::InitializeHistograms() in | 
 |   // cookie_monster.cc for details. | 
 |   base::HistogramBase* histogram_expiration_duration_minutes_; | 
 |   base::HistogramBase* histogram_count_; | 
 |   base::HistogramBase* histogram_cookie_type_; | 
 |   base::HistogramBase* histogram_cookie_source_scheme_; | 
 |   base::HistogramBase* histogram_cookie_delete_equivalent_; | 
 |   base::HistogramBase* histogram_time_blocked_on_load_; | 
 |  | 
 |   CookieMap cookies_; | 
 |  | 
 |   CookieMonsterChangeDispatcher change_dispatcher_; | 
 |  | 
 |   // Indicates whether the cookie store has been initialized. | 
 |   bool initialized_; | 
 |  | 
 |   // Indicates whether the cookie store has started fetching all cookies. | 
 |   bool started_fetching_all_cookies_; | 
 |   // Indicates whether the cookie store has finished fetching all cookies. | 
 |   bool finished_fetching_all_cookies_; | 
 |  | 
 |   // List of domain keys that have been loaded from the DB. | 
 |   std::set<std::string> keys_loaded_; | 
 |  | 
 |   // Map of domain keys to their associated task queues. These tasks are blocked | 
 |   // until all cookies for the associated domain key eTLD+1 are loaded from the | 
 |   // backend store. | 
 |   std::map<std::string, base::circular_deque<base::OnceClosure>> | 
 |       tasks_pending_for_key_; | 
 |  | 
 |   // Queues tasks that are blocked until all cookies are loaded from the backend | 
 |   // store. | 
 |   base::circular_deque<base::OnceClosure> tasks_pending_; | 
 |  | 
 |   // Once a global cookie task has been seen, all per-key tasks must be put in | 
 |   // |tasks_pending_| instead of |tasks_pending_for_key_| to ensure a reasonable | 
 |   // view of the cookie store. This is more to ensure fancy cookie export/import | 
 |   // code has a consistent view of the CookieStore, rather than out of concern | 
 |   // for typical use. | 
 |   bool seen_global_task_; | 
 |  | 
 |   NetLogWithSource net_log_; | 
 |  | 
 |   scoped_refptr<PersistentCookieStore> store_; | 
 |  | 
 |   base::Time last_time_seen_; | 
 |  | 
 |   // Minimum delay after updating a cookie's LastAccessDate before we will | 
 |   // update it again. | 
 |   const base::TimeDelta last_access_threshold_; | 
 |  | 
 |   // Approximate date of access time of least recently accessed cookie | 
 |   // in |cookies_|.  Note that this is not guaranteed to be accurate, only a) | 
 |   // to be before or equal to the actual time, and b) to be accurate | 
 |   // immediately after a garbage collection that scans through all the cookies | 
 |   // (When garbage collection does not scan through all cookies, it may not be | 
 |   // updated). This value is used to determine whether global garbage collection | 
 |   // might find cookies to purge. Note: The default Time() constructor will | 
 |   // create a value that compares earlier than any other time value, which is | 
 |   // wanted.  Thus this value is not initialized. | 
 |   base::Time earliest_access_time_; | 
 |  | 
 |   std::vector<std::string> cookieable_schemes_; | 
 |  | 
 |   ChannelIDService* channel_id_service_; | 
 |  | 
 |   base::Time last_statistic_record_time_; | 
 |  | 
 |   bool persist_session_cookies_; | 
 |  | 
 |   THREAD_CHECKER(thread_checker_); | 
 |  | 
 |   base::WeakPtrFactory<CookieMonster> weak_ptr_factory_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(CookieMonster); | 
 | }; | 
 |  | 
 | typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore> | 
 |     RefcountedPersistentCookieStore; | 
 |  | 
 | class NET_EXPORT CookieMonster::PersistentCookieStore | 
 |     : public RefcountedPersistentCookieStore { | 
 |  public: | 
 |   typedef base::Callback<void(std::vector<std::unique_ptr<CanonicalCookie>>)> | 
 |       LoadedCallback; | 
 |  | 
 |   // Initializes the store and retrieves the existing cookies. This will be | 
 |   // called only once at startup. The callback will return all the cookies | 
 |   // that are not yet returned to CookieMonster by previous priority loads. | 
 |   // | 
 |   // |loaded_callback| may not be NULL. | 
 |   // |net_log| is a NetLogWithSource that may be copied if the persistent | 
 |   // store wishes to log NetLog events. | 
 |   virtual void Load(const LoadedCallback& loaded_callback, | 
 |                     const NetLogWithSource& net_log) = 0; | 
 |  | 
 |   // Does a priority load of all cookies for the domain key (eTLD+1). The | 
 |   // callback will return all the cookies that are not yet returned by previous | 
 |   // loads, which includes cookies for the requested domain key if they are not | 
 |   // already returned, plus all cookies that are chain-loaded and not yet | 
 |   // returned to CookieMonster. | 
 |   // | 
 |   // |loaded_callback| may not be NULL. | 
 |   virtual void LoadCookiesForKey(const std::string& key, | 
 |                                  const LoadedCallback& loaded_callback) = 0; | 
 |  | 
 |   virtual void AddCookie(const CanonicalCookie& cc) = 0; | 
 |   virtual void UpdateCookieAccessTime(const CanonicalCookie& cc) = 0; | 
 |   virtual void DeleteCookie(const CanonicalCookie& cc) = 0; | 
 |  | 
 |   // Instructs the store to not discard session only cookies on shutdown. | 
 |   virtual void SetForceKeepSessionState() = 0; | 
 |  | 
 |   // Sets a callback that will be run before the store flushes.  If |callback| | 
 |   // performs any async operations, the store will not wait for those to finish | 
 |   // before flushing. | 
 |   virtual void SetBeforeFlushCallback(base::RepeatingClosure callback) = 0; | 
 |  | 
 |   // Flushes the store and posts |callback| when complete. |callback| may be | 
 |   // NULL. | 
 |   virtual void Flush(base::OnceClosure callback) = 0; | 
 |  | 
 |  protected: | 
 |   PersistentCookieStore() {} | 
 |   virtual ~PersistentCookieStore() {} | 
 |  | 
 |  private: | 
 |   friend class base::RefCountedThreadSafe<PersistentCookieStore>; | 
 |   DISALLOW_COPY_AND_ASSIGN(PersistentCookieStore); | 
 | }; | 
 |  | 
 | }  // namespace net | 
 |  | 
 | #endif  // NET_COOKIES_COOKIE_MONSTER_H_ |