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

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: Sync and cleanup. 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(const EvictedDomainCookieCounter::EvictedCookie& ec,
32 const Time& reinstatement_time) OVERRIDE;
33 virtual Time CurrentTime() OVERRIDE;
34 };
35
36 DelegateImpl::DelegateImpl() {}
37
38 void DelegateImpl::Report(const EvictedDomainCookieCounter::EvictedCookie& ec,
mmenke 2013/03/29 15:22:16 evicted_cookies (See comment in header about varia
huangs 2013/04/02 19:21:52 Done.
39 const Time& reinstatement_time) {
40 TimeDelta reinstatement_delay(reinstatement_time - ec.eviction_time_);
41 // Need to duplicate HISTOGRAM_CUSTOM_TIMES(), since it is a macro that
42 // defines a static variable.
43 if (ec.is_google_) {
44 HISTOGRAM_CUSTOM_TIMES("Cookie.ReinstatedCookiesGoogle",
45 reinstatement_delay,
46 TimeDelta::FromSeconds(1),
47 TimeDelta::FromDays(7),
48 50);
49 } else {
50 HISTOGRAM_CUSTOM_TIMES("Cookie.ReinstatedCookiesOther",
51 reinstatement_delay,
52 TimeDelta::FromSeconds(1),
53 TimeDelta::FromDays(7),
54 50);
55 }
56 }
57
58 Time DelegateImpl::CurrentTime() {
59 return Time::Now();
60 }
61
62 } // namespace
63
64 EvictedDomainCookieCounter::EvictedDomainCookieCounter(
65 scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate)
66 : next_cookie_monster_delegate_(next_cookie_monster_delegate),
67 delegate_(new DelegateImpl),
68 max_size_(kMaxEvictedDomainCookies),
69 purge_count_(kPurgeEvictedDomainCookies) {
70 }
71
72 EvictedDomainCookieCounter::EvictedDomainCookieCounter(
73 scoped_refptr<net::CookieMonster::Delegate> next_cookie_monster_delegate,
74 scoped_ptr<Delegate> delegate,
75 size_t max_size,
76 size_t purge_count)
77 : next_cookie_monster_delegate_(next_cookie_monster_delegate),
78 delegate_(delegate.Pass()),
79 max_size_(max_size),
80 purge_count_(purge_count) {
81 DCHECK(delegate_);
82 DCHECK(purge_count < max_size_);
mmenke 2013/03/29 15:22:16 DCHECK_LT
huangs 2013/04/02 19:21:52 Done.
83 }
84
85 EvictedDomainCookieCounter::~EvictedDomainCookieCounter() {
86 STLDeleteContainerPairSecondPointers(evicted_cookies_.begin(),
87 evicted_cookies_.end());
88 }
89
90 size_t EvictedDomainCookieCounter::GetStorageSize() const {
91 return evicted_cookies_.size();
92 }
93
94 void EvictedDomainCookieCounter::OnCookieChanged(const net::CanonicalCookie& cc,
95 bool removed,
96 ChangeCause cause) {
97 EvictedDomainCookieCounter::EvictedCookieKey key(GetKey(cc));
98 Time current(delegate_->CurrentTime());
99 if (removed) {
100 if (cause == net::CookieMonster::Delegate::CHANGE_COOKIE_EVICTED)
101 StoreEvictedCookie(key, cc, current);
102 } else { // Includes adds or updates.
103 ProcessNewCookie(key, cc, current);
104 }
105
106 if (next_cookie_monster_delegate_)
107 next_cookie_monster_delegate_->OnCookieChanged(cc, removed, cause);
108 }
109
110 // static
111 EvictedDomainCookieCounter::EvictedCookieKey
112 EvictedDomainCookieCounter::GetKey(const net::CanonicalCookie& cc) {
113 return cc.Domain() + ";" + cc.Path() + ";" + cc.Name();
114 }
115
116 void EvictedDomainCookieCounter::GarbageCollect(const Time& current) {
117 if (evicted_cookies_.size() <= max_size_)
118 return;
119
120 // From |evicted_cookies_|, removed all expired cookies, and remove cookies
121 // with the oldest |eviction_time_| so that |size_goal| is attained.
122 size_t size_goal = max_size_ - purge_count_;
123 // Bound on number of non-expired cookies to remove.
124 size_t remove_quota = evicted_cookies_.size() - size_goal;
125 DCHECK(remove_quota > 0);
mmenke 2013/03/29 15:22:16 DCHECK_GT is preferred, as it will output more on
huangs 2013/04/02 19:21:52 Done.
126
127 std::vector<EvictedCookieMap::iterator> remove_list;
128 remove_list.reserve(evicted_cookies_.size());
129
130 EvictedCookieMap::iterator it = evicted_cookies_.begin();
131 while (it != evicted_cookies_.end()) {
132 if (it->second->is_expired(current)) {
133 delete it->second;
134 evicted_cookies_.erase(it++); // Post-increment idiom for in-loop removal.
135 if (remove_quota)
136 --remove_quota;
137 } else {
138 if (remove_quota) // Don't bother storing if quota met.
139 remove_list.push_back(it);
140 ++it;
141 }
142 }
143
144 // Comparator for sorting, to make recently evicted cookies appear earlier.
145 struct {
146 bool operator() (const EvictedCookieMap::iterator ec1,
147 const EvictedCookieMap::iterator ec2) {
148 return ec1->second->eviction_time_ < ec2->second->eviction_time_;
149 }
150 } comparator;
151
152 // Free the oldest |remove_quota| non-expired cookies.
153 std::partial_sort(remove_list.begin(), remove_list.begin() + remove_quota,
154 remove_list.end(), comparator);
155 for (size_t i = 0; i < remove_quota; ++i) {
156 delete remove_list[i]->second;
157 evicted_cookies_.erase(remove_list[i]);
158 }
159
160 // Apply stricter check if non-expired cookies were deleted.
161 DCHECK(remove_quota ? evicted_cookies_.size() == size_goal :
162 evicted_cookies_.size() <= size_goal);
163 }
164
165 void EvictedDomainCookieCounter::StoreEvictedCookie(
166 const EvictedCookieKey& key,
167 const net::CanonicalCookie& cc,
168 const Time& current) {
169 bool is_google = google_util::IsGoogleHostname(
170 cc.Domain(), google_util::ALLOW_SUBDOMAIN);
171 EvictedCookie* ec = new EvictedCookie(current, cc.ExpiryDate(), is_google);
mmenke 2013/03/29 15:22:16 evicted_cookies
huangs 2013/04/02 19:21:52 Done.
172 std::pair<EvictedCookieMap::iterator, bool> prev_entry =
173 evicted_cookies_.insert(EvictedCookieMap::value_type(key, ec));
174 if (!prev_entry.second) {
175 NOTREACHED();
176 delete prev_entry.first->second;
177 prev_entry.first->second = ec;
178 }
179
180 GarbageCollect(current);
181 }
182
183 void EvictedDomainCookieCounter::ProcessNewCookie(
184 const EvictedCookieKey& key,
185 const net::CanonicalCookie& cc,
186 const Time& current) {
187 EvictedCookieMap::iterator it = evicted_cookies_.find(key);
188 if (it != evicted_cookies_.end()) {
189 if (!it->second->is_expired(current))
190 delegate_->Report(*it->second, current); // Reinstatement.
191 delete it->second;
192 evicted_cookies_.erase(it);
193 }
194 }
195
196 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698