Home | History | Annotate | Download | only in net
      1 // Copyright 2013 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.
      4 
      5 #ifndef CHROME_BROWSER_NET_EVICTED_DOMAIN_COOKIE_COUNTER_H_
      6 #define CHROME_BROWSER_NET_EVICTED_DOMAIN_COOKIE_COUNTER_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/time/time.h"
     16 #include "net/cookies/cookie_monster.h"
     17 
     18 namespace net {
     19 class CanonicalCookie;
     20 }  // namespace net
     21 
     22 namespace chrome_browser_net {
     23 
     24 // The Evicted Domain Cookie Counter generates statistics on "wrongly evicted"
     25 // cookies, i.e., cookies that were "evicted" (on reaching domain cookie limit)
     26 // but are then "reinstated" later because they were important. A specific
     27 // scenario is as follows: a long-lived login session cookie gets evicted owing
     28 // to its age, thereby forcing the user to lose session, and is reinstated when
     29 // the user re-authenticates.
     30 //
     31 // A solution to the above problem is the Cookie Priority Field, which enables
     32 // servers to protect important cookies, thereby decreasing the chances that
     33 // these cookies are wrongly evicted. To measure the effectiveness of this
     34 // solution, we will compare eviction user metrics before vs. after the fix.
     35 //
     36 // Specifically, we wish to record user metrics on "reinstatement delay", i.e.,
     37 // the duration between eviction and reinstatement of cookie. We expect that
     38 // after the fix, average reinstatement delays will increase, since low priority
     39 // cookies are less likely to be reinstated after eviction.
     40 //
     41 // Metrics for Google domains are tracked separately.
     42 //
     43 class EvictedDomainCookieCounter : public net::CookieMonster::Delegate {
     44  public:
     45   // Structure to store sanitized data from CanonicalCookie.
     46   struct EvictedCookie {
     47     EvictedCookie(base::Time eviction_time_in,
     48                   base::Time expiry_time_in,
     49                   bool is_google_in)
     50         : eviction_time(eviction_time_in),
     51           expiry_time(expiry_time_in),
     52           is_google(is_google_in) {}
     53 
     54     bool is_expired(const base::Time& current_time) const {
     55       return !expiry_time.is_null() && current_time >= expiry_time;
     56     }
     57 
     58     base::Time eviction_time;
     59     base::Time expiry_time;
     60     bool is_google;
     61   };
     62 
     63   class Delegate {
     64    public:
     65     virtual ~Delegate() {}
     66 
     67     // Called when a stored evicted cookie is reinstated.
     68     virtual void Report(const EvictedCookie& evicted_cookie,
     69                         const base::Time& reinstatement_time) = 0;
     70 
     71     // Getter of time is placed here to enable mocks.
     72     virtual base::Time CurrentTime() const = 0;
     73   };
     74 
     75   // |next_cookie_monster_delegate| can be NULL.
     76   explicit EvictedDomainCookieCounter(
     77       scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate);
     78 
     79   // Constructor exposed for testing only.
     80   EvictedDomainCookieCounter(
     81       scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate,
     82       scoped_ptr<Delegate> cookie_counter_delegate,
     83       size_t max_size,
     84       size_t purge_count);
     85 
     86   // Returns the number of evicted cookies stored.
     87   size_t GetStorageSize() const;
     88 
     89   // CookieMonster::Delegate implementation.
     90   virtual void OnCookieChanged(const net::CanonicalCookie& cookie,
     91                                bool removed,
     92                                ChangeCause cause) OVERRIDE;
     93 
     94  private:
     95   // Identifier of an evicted cookie.
     96   typedef std::string EvictedCookieKey;
     97 
     98   // Storage class of evicted cookie.
     99   typedef std::map<EvictedCookieKey, EvictedCookie*> EvictedCookieMap;
    100 
    101   virtual ~EvictedDomainCookieCounter();
    102 
    103   // Computes key for |cookie| compatible with CanonicalCookie::IsEquivalent(),
    104   // i.e., IsEquivalent(a, b) ==> GetKey(a) == GetKey(b).
    105   static EvictedCookieKey GetKey(const net::CanonicalCookie& cookie);
    106 
    107   // Comparator for sorting, to make recently evicted cookies appear earlier.
    108   static bool CompareEvictedCookie(
    109       const EvictedCookieMap::iterator evicted_cookie1,
    110       const EvictedCookieMap::iterator evicted_cookie2);
    111 
    112   // If too many evicted cookies are stored, delete the expired ones, then
    113   // delete cookies that were evicted the longest, until size limit reached.
    114   void GarbageCollect(const base::Time& current_time);
    115 
    116   // Called when a cookie is evicted. Adds the evicted cookie to storage,
    117   // possibly replacing an existing equivalent cookie.
    118   void StoreEvictedCookie(const EvictedCookieKey& key,
    119                           const net::CanonicalCookie& cookie,
    120                           const base::Time& current_time);
    121 
    122   // Called when a new cookie is added. If reinstatement occurs, then notifies
    123   // |cookie_counter_delegate_| and then removes the evicted cookie.
    124   void ProcessNewCookie(const EvictedCookieKey& key,
    125                         const net::CanonicalCookie& cookie,
    126                         const base::Time& current_time);
    127 
    128   // Another delegate to forward events to.
    129   scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate_;
    130 
    131   scoped_ptr<Delegate> cookie_counter_delegate_;
    132 
    133   EvictedCookieMap evicted_cookies_;
    134 
    135   // Capacity of the evicted cookie storage, before garbage collection occurs.
    136   const size_t max_size_;
    137 
    138   // After garbage collection, size reduces to <= |max_size_| - |purge_count_|.
    139   const size_t purge_count_;
    140 
    141   DISALLOW_COPY_AND_ASSIGN(EvictedDomainCookieCounter);
    142 };
    143 
    144 }  // namespace chrome_browser_net
    145 
    146 #endif  // CHROME_BROWSER_NET_EVICTED_DOMAIN_COOKIE_COUNTER_H_
    147