Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Side by Side Diff: chrome/browser/net/evicted_domain_cookie_counter.cc

Issue 12805010: Implementing EvictedDomainCookieCounter to keep user metrics on cookie eviction and reinstatement. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Style and comment fixes; changing partial_sort() comparator to fix Linux build. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/browser/net/evicted_domain_cookie_counter.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h"
12 #include "base/string_util.h"
13 #include "chrome/browser/google/google_util.h"
14 #include "net/cookies/canonical_cookie.h"
15
16 namespace chrome_browser_net {
17
18 using base::Time;
19 using base::TimeDelta;
20
21 namespace {
22
23 const size_t kMaxEvictedDomainCookies = 500;
24 const size_t kPurgeEvictedDomainCookies = 100;
25
26 class DelegateImpl : public EvictedDomainCookieCounter::Delegate {
27 public:
28 DelegateImpl();
29
30 // EvictedDomainCookieCounter::Delegate implementation.
31 virtual void Report(
32 const EvictedDomainCookieCounter::EvictedCookie& evicted_cookie,
33 const Time& reinstatement_time) OVERRIDE;
34 virtual Time CurrentTime() const OVERRIDE;
35 };
36
37 DelegateImpl::DelegateImpl() {}
38
39 void DelegateImpl::Report(
40 const EvictedDomainCookieCounter::EvictedCookie& evicted_cookie,
41 const Time& reinstatement_time) {
42 TimeDelta reinstatement_delay(
43 reinstatement_time - evicted_cookie.eviction_time);
44 // Need to duplicate HISTOGRAM_CUSTOM_TIMES(), since it is a macro that
45 // defines a static variable.
46 if (evicted_cookie.is_google) {
47 HISTOGRAM_CUSTOM_TIMES("Cookie.ReinstatedCookiesGoogle",
48 reinstatement_delay,
49 TimeDelta::FromSeconds(1),
50 TimeDelta::FromDays(7),
51 50);
52 } else {
53 HISTOGRAM_CUSTOM_TIMES("Cookie.ReinstatedCookiesOther",
54 reinstatement_delay,
55 TimeDelta::FromSeconds(1),
56 TimeDelta::FromDays(7),
57 50);
58 }
59 }
60
61 Time DelegateImpl::CurrentTime() const {
62 return Time::Now();
63 }
64
65 } // namespace
66
67 EvictedDomainCookieCounter::EvictedDomainCookieCounter(
68 scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate)
69 : next_cookie_monster_delegate_(next_cookie_monster_delegate),
70 cookie_counter_delegate_(new DelegateImpl),
71 max_size_(kMaxEvictedDomainCookies),
72 purge_count_(kPurgeEvictedDomainCookies) {
73 }
74
75 EvictedDomainCookieCounter::EvictedDomainCookieCounter(
76 scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate,
77 scoped_ptr<Delegate> cookie_counter_delegate,
78 size_t max_size,
79 size_t purge_count)
80 : next_cookie_monster_delegate_(next_cookie_monster_delegate),
81 cookie_counter_delegate_(cookie_counter_delegate.Pass()),
82 max_size_(max_size),
83 purge_count_(purge_count) {
84 DCHECK(cookie_counter_delegate_);
85 DCHECK_LT(purge_count, max_size_);
86 }
87
88 EvictedDomainCookieCounter::~EvictedDomainCookieCounter() {
89 STLDeleteContainerPairSecondPointers(evicted_cookies_.begin(),
90 evicted_cookies_.end());
91 }
92
93 size_t EvictedDomainCookieCounter::GetStorageSize() const {
94 return evicted_cookies_.size();
95 }
96
97 void EvictedDomainCookieCounter::OnCookieChanged(
98 const net::CanonicalCookie& cookie,
99 bool removed,
100 ChangeCause cause) {
101 EvictedDomainCookieCounter::EvictedCookieKey key(GetKey(cookie));
102 Time current_time(cookie_counter_delegate_->CurrentTime());
103 if (removed) {
104 if (cause == net::CookieMonster::Delegate::CHANGE_COOKIE_EVICTED)
105 StoreEvictedCookie(key, cookie, current_time);
106 } else { // Includes adds or updates.
107 ProcessNewCookie(key, cookie, current_time);
108 }
109
110 if (next_cookie_monster_delegate_)
111 next_cookie_monster_delegate_->OnCookieChanged(cookie, removed, cause);
112 }
113
114 // static
115 EvictedDomainCookieCounter::EvictedCookieKey
116 EvictedDomainCookieCounter::GetKey(const net::CanonicalCookie& cookie) {
117 return cookie.Domain() + ";" + cookie.Path() + ";" + cookie.Name();
118 }
119
120 // static
121 // Comparator for sorting, to make recently evicted cookies appear earlier.
mmenke 2013/04/03 14:27:36 One more nit - function-level comments should go w
huangs 2013/04/03 15:42:15 Done.
122 bool EvictedDomainCookieCounter::CompareEvictedCookie(
huangs 2013/04/02 19:21:52 Making this a static member (instead of local func
123 const EvictedCookieMap::iterator evicted_cookie1,
124 const EvictedCookieMap::iterator evicted_cookie2) {
125 return evicted_cookie1->second->eviction_time
126 < evicted_cookie2->second->eviction_time;
127 }
128
129 void EvictedDomainCookieCounter::GarbageCollect(const Time& current_time) {
130 if (evicted_cookies_.size() <= max_size_)
131 return;
132
133 // From |evicted_cookies_|, removed all expired cookies, and remove cookies
134 // with the oldest |eviction_time| so that |size_goal| is attained.
135 size_t size_goal = max_size_ - purge_count_;
136 // Bound on number of non-expired cookies to remove.
137 size_t remove_quota = evicted_cookies_.size() - size_goal;
138 DCHECK_GT(remove_quota, static_cast<size_t>(0));
139
140 std::vector<EvictedCookieMap::iterator> remove_list;
141 remove_list.reserve(evicted_cookies_.size());
142
143 EvictedCookieMap::iterator it = evicted_cookies_.begin();
144 while (it != evicted_cookies_.end()) {
145 if (it->second->is_expired(current_time)) {
146 delete it->second;
147 evicted_cookies_.erase(it++); // Post-increment idiom for in-loop removal.
148 if (remove_quota)
149 --remove_quota;
150 } else {
151 if (remove_quota) // Don't bother storing if quota met.
152 remove_list.push_back(it);
153 ++it;
154 }
155 }
156
157 // Free the oldest |remove_quota| non-expired cookies.
158 std::partial_sort(remove_list.begin(), remove_list.begin() + remove_quota,
159 remove_list.end(), CompareEvictedCookie);
160 for (size_t i = 0; i < remove_quota; ++i) {
161 delete remove_list[i]->second;
162 evicted_cookies_.erase(remove_list[i]);
163 }
164
165 // Apply stricter check if non-expired cookies were deleted.
166 DCHECK(remove_quota ? evicted_cookies_.size() == size_goal :
167 evicted_cookies_.size() <= size_goal);
168 }
169
170 void EvictedDomainCookieCounter::StoreEvictedCookie(
171 const EvictedCookieKey& key,
172 const net::CanonicalCookie& cookie,
173 const Time& current_time) {
174 bool is_google = google_util::IsGoogleHostname(
175 cookie.Domain(), google_util::ALLOW_SUBDOMAIN);
176 EvictedCookie* evicted_cookie =
177 new EvictedCookie(current_time, cookie.ExpiryDate(), is_google);
178 std::pair<EvictedCookieMap::iterator, bool> prev_entry =
179 evicted_cookies_.insert(
180 EvictedCookieMap::value_type(key, evicted_cookie));
181 if (!prev_entry.second) {
182 NOTREACHED();
183 delete prev_entry.first->second;
184 prev_entry.first->second = evicted_cookie;
185 }
186
187 GarbageCollect(current_time);
188 }
189
190 void EvictedDomainCookieCounter::ProcessNewCookie(
191 const EvictedCookieKey& key,
192 const net::CanonicalCookie& cc,
193 const Time& current_time) {
194 EvictedCookieMap::iterator it = evicted_cookies_.find(key);
195 if (it != evicted_cookies_.end()) {
196 if (!it->second->is_expired(current_time)) // Reinstatement.
197 cookie_counter_delegate_->Report(*it->second, current_time);
198 delete it->second;
199 evicted_cookies_.erase(it);
200 }
201 }
202
203 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698