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

Side by Side Diff: webkit/quota/usage_tracker.cc

Issue 15857002: [Quota][Clean up] Simplify usage aggregator in ClientUsageTracker (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: buildfix for android Created 7 years, 7 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
« no previous file with comments | « webkit/quota/usage_tracker.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/quota/usage_tracker.h" 5 #include "webkit/quota/usage_tracker.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/message_loop_proxy.h" 14 #include "base/message_loop_proxy.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "net/base/net_util.h" 16 #include "net/base/net_util.h"
17 17
18 namespace quota { 18 namespace quota {
19 19
20 namespace { 20 namespace {
21 21
22 bool SortByHost(const GURL& lhs, const GURL& rhs) { 22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator;
23 return net::GetHostOrSpecFromURL(lhs) > net::GetHostOrSpecFromURL(rhs); 23
24 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator,
25 const GURL& origin,
26 int64 usage) {
27 accumulator.Run(origin, usage);
24 } 28 }
25 29
30 void DidGetHostUsage(const UsageCallback& callback,
31 int64 cached_usage,
32 int64 non_cached_usage) {
33 DCHECK_GE(cached_usage, 0);
34 DCHECK_GE(non_cached_usage, 0);
35 callback.Run(cached_usage + non_cached_usage);
36 }
37
38 void NoopHostUsageCallback(int64 usage) {}
39
26 } // namespace 40 } // namespace
27 41
28 // A task class for getting the total amount of data used for a collection of
29 // origins. This class is self-destructed.
30 class ClientUsageTracker::GatherUsageTaskBase : public QuotaTask {
31 public:
32 GatherUsageTaskBase(
33 UsageTracker* tracker,
34 QuotaClient* client)
35 : QuotaTask(tracker),
36 client_(client),
37 tracker_(tracker),
38 current_gathered_usage_(0),
39 weak_factory_(this) {
40 DCHECK(tracker_);
41 DCHECK(client_);
42 client_tracker_ = base::AsWeakPtr(
43 tracker_->GetClientTracker(client_->id()));
44 DCHECK(client_tracker_.get());
45 }
46 virtual ~GatherUsageTaskBase() {}
47
48 // Get total usage for the given |origins|.
49 void GetUsageForOrigins(const std::set<GURL>& origins, StorageType type) {
50 DCHECK(original_task_runner()->BelongsToCurrentThread());
51 if (!client_tracker()) {
52 DeleteSoon();
53 return;
54 }
55 // We do not get usage for origins for which we have valid usage cache.
56 std::vector<GURL> origins_not_in_cache;
57 current_gathered_usage_ = client_tracker()->GetCachedOriginsUsage(
58 origins, &origins_not_in_cache);
59 if (origins_not_in_cache.empty()) {
60 CallCompleted();
61 DeleteSoon();
62 return;
63 }
64
65 // Sort them so we can detect when we've gathered all info for a particular
66 // host in DidGetUsage.
67 std::sort(origins_not_in_cache.begin(),
68 origins_not_in_cache.end(), SortByHost);
69
70 // First, fully populate the pending queue because GetOriginUsage may call
71 // the completion callback immediately.
72 for (std::vector<GURL>::const_iterator iter = origins_not_in_cache.begin();
73 iter != origins_not_in_cache.end(); iter++)
74 pending_origins_.push_back(*iter);
75
76 for (std::vector<GURL>::const_iterator iter = origins_not_in_cache.begin();
77 iter != origins_not_in_cache.end(); iter++)
78 client_->GetOriginUsage(
79 *iter,
80 tracker_->type(),
81 base::Bind(&GatherUsageTaskBase::DidGetUsage,
82 weak_factory_.GetWeakPtr()));
83 }
84
85 protected:
86 virtual void DidGetOriginUsage(const GURL& origin, int64 usage) {}
87
88 virtual void Aborted() OVERRIDE {
89 DeleteSoon();
90 }
91
92 UsageTracker* tracker() const { return tracker_; }
93 ClientUsageTracker* client_tracker() const { return client_tracker_.get(); }
94
95 int64 current_gathered_usage() const { return current_gathered_usage_; }
96
97 private:
98 void DidGetUsage(int64 usage) {
99 if (!client_tracker()) {
100 DeleteSoon();
101 return;
102 }
103
104 DCHECK(original_task_runner()->BelongsToCurrentThread());
105 DCHECK(!pending_origins_.empty());
106
107 // Defend against confusing inputs from QuotaClients.
108 DCHECK_GE(usage, 0);
109 if (usage < 0)
110 usage = 0;
111 current_gathered_usage_ += usage;
112
113 // This code assumes DidGetUsage callbacks are called in the same
114 // order as we dispatched GetOriginUsage calls.
115 const GURL& origin = pending_origins_.front();
116 std::string host = net::GetHostOrSpecFromURL(origin);
117 client_tracker_->AddCachedOrigin(origin, usage);
118
119 DidGetOriginUsage(origin, usage);
120
121 pending_origins_.pop_front();
122 if (pending_origins_.empty() ||
123 host != net::GetHostOrSpecFromURL(pending_origins_.front())) {
124 client_tracker_->AddCachedHost(host);
125 }
126
127 if (pending_origins_.empty()) {
128 // We're done.
129 CallCompleted();
130 DeleteSoon();
131 }
132 }
133
134 QuotaClient* client_;
135 UsageTracker* tracker_;
136 base::WeakPtr<ClientUsageTracker> client_tracker_;
137 std::deque<GURL> pending_origins_;
138 std::map<GURL, int64> origin_usage_map_;
139 int64 current_gathered_usage_;
140 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_;
141
142 DISALLOW_COPY_AND_ASSIGN(GatherUsageTaskBase);
143 };
144
145 // A task class for getting the total amount of data used for a given storage
146 // type. This class is self-destructed.
147 class ClientUsageTracker::GatherGlobalUsageTask
148 : public GatherUsageTaskBase {
149 public:
150 GatherGlobalUsageTask(
151 UsageTracker* tracker,
152 QuotaClient* client)
153 : GatherUsageTaskBase(tracker, client),
154 client_(client),
155 non_cached_global_usage_(0),
156 weak_factory_(this) {
157 DCHECK(tracker);
158 DCHECK(client);
159 }
160 virtual ~GatherGlobalUsageTask() {}
161
162 protected:
163 virtual void Run() OVERRIDE {
164 client_->GetOriginsForType(tracker()->type(),
165 base::Bind(&GatherUsageTaskBase::GetUsageForOrigins,
166 weak_factory_.GetWeakPtr()));
167 }
168
169 virtual void DidGetOriginUsage(const GURL& origin, int64 usage) OVERRIDE {
170 if (!client_tracker()->IsUsageCacheEnabledForOrigin(origin)) {
171 std::string host = net::GetHostOrSpecFromURL(origin);
172 non_cached_usage_by_host_[host] += usage;
173 non_cached_global_usage_ += usage;
174 }
175 }
176
177 virtual void Completed() OVERRIDE {
178 client_tracker()->GatherGlobalUsageComplete(current_gathered_usage(),
179 non_cached_global_usage_,
180 non_cached_usage_by_host_);
181 }
182
183 private:
184 QuotaClient* client_;
185 int64 non_cached_global_usage_;
186 std::map<std::string, int64> non_cached_usage_by_host_;
187 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_;
188
189 DISALLOW_COPY_AND_ASSIGN(GatherGlobalUsageTask);
190 };
191
192 // A task class for getting the total amount of data used for a given host.
193 // This class is self-destructed.
194 class ClientUsageTracker::GatherHostUsageTask
195 : public GatherUsageTaskBase {
196 public:
197 GatherHostUsageTask(
198 UsageTracker* tracker,
199 QuotaClient* client,
200 const std::string& host)
201 : GatherUsageTaskBase(tracker, client),
202 client_(client),
203 host_(host),
204 weak_factory_(this) {
205 DCHECK(client_);
206 }
207 virtual ~GatherHostUsageTask() {}
208
209 protected:
210 virtual void Run() OVERRIDE {
211 client_->GetOriginsForHost(tracker()->type(), host_,
212 base::Bind(&GatherUsageTaskBase::GetUsageForOrigins,
213 weak_factory_.GetWeakPtr()));
214 }
215
216 virtual void Completed() OVERRIDE {
217 client_tracker()->GatherHostUsageComplete(host_, current_gathered_usage());
218 }
219
220 private:
221 QuotaClient* client_;
222 std::string host_;
223 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_;
224
225 DISALLOW_COPY_AND_ASSIGN(GatherHostUsageTask);
226 };
227
228 // UsageTracker ---------------------------------------------------------- 42 // UsageTracker ----------------------------------------------------------
229 43
230 UsageTracker::UsageTracker(const QuotaClientList& clients, 44 UsageTracker::UsageTracker(const QuotaClientList& clients,
231 StorageType type, 45 StorageType type,
232 SpecialStoragePolicy* special_storage_policy) 46 SpecialStoragePolicy* special_storage_policy)
233 : type_(type), 47 : type_(type),
234 weak_factory_(this) { 48 weak_factory_(this) {
235 for (QuotaClientList::const_iterator iter = clients.begin(); 49 for (QuotaClientList::const_iterator iter = clients.begin();
236 iter != clients.end(); 50 iter != clients.end();
237 ++iter) { 51 ++iter) {
(...skipping 10 matching lines...) Expand all
248 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); 62 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id);
249 if (found != client_tracker_map_.end()) 63 if (found != client_tracker_map_.end())
250 return found->second; 64 return found->second;
251 return NULL; 65 return NULL;
252 } 66 }
253 67
254 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { 68 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
255 if (!global_usage_callbacks_.Add(callback)) 69 if (!global_usage_callbacks_.Add(callback))
256 return; 70 return;
257 71
258 TrackingInfo* info = new TrackingInfo; 72 AccumulateInfo* info = new AccumulateInfo;
259 // Calling GetGlobalUsage(accumulator) may synchronously 73 // Calling GetGlobalUsage(accumulator) may synchronously
260 // return if the usage is cached, which may in turn dispatch 74 // return if the usage is cached, which may in turn dispatch
261 // the completion callback before we finish looping over 75 // the completion callback before we finish looping over
262 // all clients (because info->pending_clients may reach 0 76 // all clients (because info->pending_clients may reach 0
263 // during the loop). 77 // during the loop).
264 // To avoid this, we add one more pending client as a sentinel 78 // To avoid this, we add one more pending client as a sentinel
265 // and fire the sentinel callback at the end. 79 // and fire the sentinel callback at the end.
266 info->pending_clients = client_tracker_map_.size() + 1; 80 info->pending_clients = client_tracker_map_.size() + 1;
267 GlobalUsageCallback accumulator = base::Bind( 81 GlobalUsageCallback accumulator = base::Bind(
268 &UsageTracker::DidGetClientGlobalUsage, weak_factory_.GetWeakPtr(), 82 &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(),
269 base::Owned(info)); 83 base::Owned(info));
270 84
271 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); 85 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin();
272 iter != client_tracker_map_.end(); 86 iter != client_tracker_map_.end();
273 ++iter) 87 ++iter)
274 iter->second->GetGlobalUsage(accumulator); 88 iter->second->GetGlobalUsage(accumulator);
275 89
276 // Fire the sentinel as we've now called GetGlobalUsage for all clients. 90 // Fire the sentinel as we've now called GetGlobalUsage for all clients.
277 accumulator.Run(0, 0); 91 accumulator.Run(0, 0);
278 } 92 }
279 93
280 void UsageTracker::GetHostUsage(const std::string& host, 94 void UsageTracker::GetHostUsage(const std::string& host,
281 const UsageCallback& callback) { 95 const UsageCallback& callback) {
282 if (!host_usage_callbacks_.Add(host, callback)) 96 if (!host_usage_callbacks_.Add(host, callback))
283 return; 97 return;
284 98
285 TrackingInfo* info = new TrackingInfo; 99 AccumulateInfo* info = new AccumulateInfo;
286 // Calling GetHostUsage(accumulator) may synchronously 100 // Calling GetHostUsage(accumulator) may synchronously
287 // return if the usage is cached, which may in turn dispatch 101 // return if the usage is cached, which may in turn dispatch
288 // the completion callback before we finish looping over 102 // the completion callback before we finish looping over
289 // all clients (because info->pending_clients may reach 0 103 // all clients (because info->pending_clients may reach 0
290 // during the loop). 104 // during the loop).
291 // To avoid this, we add one more pending client as a sentinel 105 // To avoid this, we add one more pending client as a sentinel
292 // and fire the sentinel callback at the end. 106 // and fire the sentinel callback at the end.
293 info->pending_clients = client_tracker_map_.size() + 1; 107 info->pending_clients = client_tracker_map_.size() + 1;
294 UsageCallback accumulator = base::Bind( 108 UsageCallback accumulator = base::Bind(
295 &UsageTracker::DidGetClientHostUsage, weak_factory_.GetWeakPtr(), 109 &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(),
296 base::Owned(info), host); 110 base::Owned(info), host);
297 111
298 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); 112 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin();
299 iter != client_tracker_map_.end(); 113 iter != client_tracker_map_.end();
300 ++iter) 114 ++iter)
301 iter->second->GetHostUsage(host, accumulator); 115 iter->second->GetHostUsage(host, accumulator);
302 116
303 // Fire the sentinel as we've now called GetHostUsage for all clients. 117 // Fire the sentinel as we've now called GetHostUsage for all clients.
304 accumulator.Run(0); 118 accumulator.Run(0);
305 } 119 }
(...skipping 26 matching lines...) Expand all
332 146
333 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, 147 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id,
334 const GURL& origin, 148 const GURL& origin,
335 bool enabled) { 149 bool enabled) {
336 ClientUsageTracker* client_tracker = GetClientTracker(client_id); 150 ClientUsageTracker* client_tracker = GetClientTracker(client_id);
337 DCHECK(client_tracker); 151 DCHECK(client_tracker);
338 152
339 client_tracker->SetUsageCacheEnabled(origin, enabled); 153 client_tracker->SetUsageCacheEnabled(origin, enabled);
340 } 154 }
341 155
342 void UsageTracker::DidGetClientGlobalUsage(TrackingInfo* info, 156 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info,
343 int64 usage, 157 int64 usage,
344 int64 unlimited_usage) { 158 int64 unlimited_usage) {
345 info->usage += usage; 159 info->usage += usage;
346 info->unlimited_usage += unlimited_usage; 160 info->unlimited_usage += unlimited_usage;
347 161
348 if (--info->pending_clients) 162 if (--info->pending_clients)
349 return; 163 return;
350 164
351 // Defend against confusing inputs from clients. 165 // Defend against confusing inputs from clients.
352 if (info->usage < 0) 166 if (info->usage < 0)
353 info->usage = 0; 167 info->usage = 0;
354 168
355 // TODO(michaeln): The unlimited number is not trustworthy, it 169 // TODO(michaeln): The unlimited number is not trustworthy, it
356 // can get out of whack when apps are installed or uninstalled. 170 // can get out of whack when apps are installed or uninstalled.
357 if (info->unlimited_usage > info->usage) 171 if (info->unlimited_usage > info->usage)
358 info->unlimited_usage = info->usage; 172 info->unlimited_usage = info->usage;
359 else if (info->unlimited_usage < 0) 173 else if (info->unlimited_usage < 0)
360 info->unlimited_usage = 0; 174 info->unlimited_usage = 0;
361 175
362 // All the clients have returned their usage data. Dispatch the 176 // All the clients have returned their usage data. Dispatch the
363 // pending callbacks. 177 // pending callbacks.
364 global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage)); 178 global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage));
365 } 179 }
366 180
367 void UsageTracker::DidGetClientHostUsage(TrackingInfo* info, 181 void UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info,
368 const std::string& host, 182 const std::string& host,
369 int64 usage) { 183 int64 usage) {
370 info->usage += usage; 184 info->usage += usage;
371 if (--info->pending_clients) 185 if (--info->pending_clients)
372 return; 186 return;
373 187
374 // Defend against confusing inputs from clients. 188 // Defend against confusing inputs from clients.
375 if (info->usage < 0) 189 if (info->usage < 0)
376 info->usage = 0; 190 info->usage = 0;
377 191
378 // All the clients have returned their usage data. Dispatch the 192 // All the clients have returned their usage data. Dispatch the
379 // pending callbacks. 193 // pending callbacks.
380 host_usage_callbacks_.Run(host, MakeTuple(info->usage)); 194 host_usage_callbacks_.Run(host, MakeTuple(info->usage));
381 } 195 }
382 196
383 // ClientUsageTracker ---------------------------------------------------- 197 // ClientUsageTracker ----------------------------------------------------
384 198
385 ClientUsageTracker::ClientUsageTracker( 199 ClientUsageTracker::ClientUsageTracker(
386 UsageTracker* tracker, QuotaClient* client, StorageType type, 200 UsageTracker* tracker, QuotaClient* client, StorageType type,
387 SpecialStoragePolicy* special_storage_policy) 201 SpecialStoragePolicy* special_storage_policy)
388 : tracker_(tracker), 202 : tracker_(tracker),
389 client_(client), 203 client_(client),
390 type_(type), 204 type_(type),
391 global_usage_(0), 205 global_usage_(0),
392 global_unlimited_usage_(0), 206 global_unlimited_usage_(0),
393 global_usage_retrieved_(false), 207 global_usage_retrieved_(false),
394 global_usage_task_(NULL),
395 special_storage_policy_(special_storage_policy) { 208 special_storage_policy_(special_storage_policy) {
396 DCHECK(tracker_); 209 DCHECK(tracker_);
397 DCHECK(client_); 210 DCHECK(client_);
398 if (special_storage_policy_) 211 if (special_storage_policy_)
399 special_storage_policy_->AddObserver(this); 212 special_storage_policy_->AddObserver(this);
400 } 213 }
401 214
402 ClientUsageTracker::~ClientUsageTracker() { 215 ClientUsageTracker::~ClientUsageTracker() {
403 if (special_storage_policy_) 216 if (special_storage_policy_)
404 special_storage_policy_->RemoveObserver(this); 217 special_storage_policy_->RemoveObserver(this);
405 } 218 }
406 219
407 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { 220 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
408 if (global_usage_retrieved_ && non_cached_origins_by_host_.empty()) { 221 if (global_usage_retrieved_ && non_cached_origins_by_host_.empty()) {
409 callback.Run(global_usage_, GetCachedGlobalUnlimitedUsage()); 222 callback.Run(global_usage_, global_unlimited_usage_);
410 return; 223 return;
411 } 224 }
412 DCHECK(!global_usage_callback_.HasCallbacks()); 225
413 global_usage_callback_.Add(callback); 226 client_->GetOriginsForType(type_, base::Bind(
414 global_usage_task_ = new GatherGlobalUsageTask(tracker_, client_); 227 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(),
415 global_usage_task_->Start(); 228 callback));
416 } 229 }
417 230
418 void ClientUsageTracker::GetHostUsage( 231 void ClientUsageTracker::GetHostUsage(
419 const std::string& host, const UsageCallback& callback) { 232 const std::string& host, const UsageCallback& callback) {
420 if (ContainsKey(cached_hosts_, host) && 233 if (ContainsKey(cached_hosts_, host) &&
421 !ContainsKey(non_cached_origins_by_host_, host)) { 234 !ContainsKey(non_cached_origins_by_host_, host)) {
422 // TODO(kinuko): Drop host_usage_map_ cache periodically. 235 // TODO(kinuko): Drop host_usage_map_ cache periodically.
423 callback.Run(GetCachedHostUsage(host)); 236 callback.Run(GetCachedHostUsage(host));
424 return; 237 return;
425 } 238 }
426 if (!host_usage_callbacks_.Add(host, callback) || global_usage_task_) 239
240 if (!host_usage_accumulators_.Add(host, base::Bind(
241 &DidGetHostUsage, callback)))
427 return; 242 return;
428 GatherHostUsageTask* task = new GatherHostUsageTask(tracker_, client_, host); 243 client_->GetOriginsForHost(type_, host, base::Bind(
429 host_usage_tasks_[host] = task; 244 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host));
430 task->Start();
431 } 245 }
432 246
433 void ClientUsageTracker::UpdateUsageCache( 247 void ClientUsageTracker::UpdateUsageCache(
434 const GURL& origin, int64 delta) { 248 const GURL& origin, int64 delta) {
435 std::string host = net::GetHostOrSpecFromURL(origin); 249 std::string host = net::GetHostOrSpecFromURL(origin);
436 if (cached_hosts_.find(host) != cached_hosts_.end()) { 250 if (cached_hosts_.find(host) != cached_hosts_.end()) {
437 if (!IsUsageCacheEnabledForOrigin(origin)) 251 if (!IsUsageCacheEnabledForOrigin(origin))
438 return; 252 return;
439 253
440 cached_usage_by_host_[host][origin] += delta; 254 cached_usage_by_host_[host][origin] += delta;
441 global_usage_ += delta; 255 global_usage_ += delta;
442 if (IsStorageUnlimited(origin)) 256 if (IsStorageUnlimited(origin))
443 global_unlimited_usage_ += delta; 257 global_unlimited_usage_ += delta;
444 DCHECK_GE(cached_usage_by_host_[host][origin], 0); 258 DCHECK_GE(cached_usage_by_host_[host][origin], 0);
445 DCHECK_GE(global_usage_, 0); 259 DCHECK_GE(global_usage_, 0);
446 return; 260 return;
447 } 261 }
448 262
449 // We don't know about this host yet, so populate our cache for it. 263 // We don't know about this host yet, so populate our cache for it.
450 GetHostUsage(host, 264 GetHostUsage(host, base::Bind(&NoopHostUsageCallback));
451 base::Bind(&ClientUsageTracker::NoopHostUsageCallback,
452 base::Unretained(this)));
453 } 265 }
454 266
455 void ClientUsageTracker::GetCachedHostsUsage( 267 void ClientUsageTracker::GetCachedHostsUsage(
456 std::map<std::string, int64>* host_usage) const { 268 std::map<std::string, int64>* host_usage) const {
457 DCHECK(host_usage); 269 DCHECK(host_usage);
458 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); 270 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin();
459 host_iter != cached_usage_by_host_.end(); host_iter++) { 271 host_iter != cached_usage_by_host_.end(); host_iter++) {
460 host_usage->operator[](host_iter->first) += 272 const std::string& host = host_iter->first;
461 GetCachedHostUsage(host_iter->first); 273 (*host_usage)[host] += GetCachedHostUsage(host);
462 } 274 }
463 } 275 }
464 276
465 void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { 277 void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const {
466 DCHECK(origins); 278 DCHECK(origins);
467 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); 279 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin();
468 host_iter != cached_usage_by_host_.end(); host_iter++) { 280 host_iter != cached_usage_by_host_.end(); host_iter++) {
469 const UsageMap& origin_map = host_iter->second; 281 const UsageMap& origin_map = host_iter->second;
470 for (UsageMap::const_iterator origin_iter = origin_map.begin(); 282 for (UsageMap::const_iterator origin_iter = origin_map.begin();
471 origin_iter != origin_map.end(); origin_iter++) { 283 origin_iter != origin_map.end(); origin_iter++) {
472 origins->insert(origin_iter->first); 284 origins->insert(origin_iter->first);
473 } 285 }
474 } 286 }
475 } 287 }
476 288
477 int64 ClientUsageTracker::GetCachedOriginsUsage(
478 const std::set<GURL>& origins,
479 std::vector<GURL>* origins_not_in_cache) {
480 DCHECK(origins_not_in_cache);
481
482 int64 usage = 0;
483 for (std::set<GURL>::const_iterator itr = origins.begin();
484 itr != origins.end(); ++itr) {
485 int64 origin_usage = 0;
486 if (GetCachedOriginUsage(*itr, &origin_usage))
487 usage += origin_usage;
488 else
489 origins_not_in_cache->push_back(*itr);
490 }
491 return usage;
492 }
493
494 void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, 289 void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin,
495 bool enabled) { 290 bool enabled) {
496 std::string host = net::GetHostOrSpecFromURL(origin); 291 std::string host = net::GetHostOrSpecFromURL(origin);
497 if (!enabled) { 292 if (!enabled) {
498 // Erase |origin| from cache and subtract its usage. 293 // Erase |origin| from cache and subtract its usage.
499 HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); 294 HostUsageMap::iterator found_host = cached_usage_by_host_.find(host);
500 if (found_host != cached_usage_by_host_.end()) { 295 if (found_host != cached_usage_by_host_.end()) {
501 UsageMap& cached_usage_for_host = found_host->second; 296 UsageMap& cached_usage_for_host = found_host->second;
502 297
503 UsageMap::iterator found = cached_usage_for_host.find(origin); 298 UsageMap::iterator found = cached_usage_for_host.find(origin);
(...skipping 18 matching lines...) Expand all
522 317
523 found->second.erase(origin); 318 found->second.erase(origin);
524 if (found->second.empty()) { 319 if (found->second.empty()) {
525 non_cached_origins_by_host_.erase(found); 320 non_cached_origins_by_host_.erase(found);
526 cached_hosts_.erase(host); 321 cached_hosts_.erase(host);
527 global_usage_retrieved_ = false; 322 global_usage_retrieved_ = false;
528 } 323 }
529 } 324 }
530 } 325 }
531 326
327 void ClientUsageTracker::DidGetOriginsForGlobalUsage(
328 const GlobalUsageCallback& callback,
329 const std::set<GURL>& origins, StorageType type) {
330 OriginSetByHost origins_by_host;
331 for (std::set<GURL>::const_iterator itr = origins.begin();
332 itr != origins.end(); ++itr)
333 origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr);
334
335 AccumulateInfo* info = new AccumulateInfo;
336 // Getting host usage may synchronously return the result if the usage is
337 // cached, which may in turn dispatch the completion callback before we finish
338 // looping over all hosts (because info->pending_jobs may reach 0 during the
339 // loop). To avoid this, we add one more pending host as a sentinel and
340 // fire the sentinel callback at the end.
341 info->pending_jobs = origins_by_host.size() + 1;
342 HostUsageAccumulator accumulator =
343 base::Bind(&ClientUsageTracker::AccumulateHostUsage, AsWeakPtr(),
344 base::Owned(info), callback);
345
346 for (OriginSetByHost::iterator itr = origins_by_host.begin();
347 itr != origins_by_host.end(); ++itr) {
348 if (host_usage_accumulators_.Add(itr->first, accumulator))
349 GetUsageForOrigins(itr->first, itr->second);
350 }
351
352 // Fire the sentinel as we've now called GetUsageForOrigins for all clients.
353 accumulator.Run(0, 0);
354 }
355
356 void ClientUsageTracker::AccumulateHostUsage(
357 AccumulateInfo* info,
358 const GlobalUsageCallback& callback,
359 int64 cached_usage,
360 int64 non_cached_usage) {
361 info->cached_usage += cached_usage;
362 info->non_cached_usage += non_cached_usage;
363 if (--info->pending_jobs)
364 return;
365
366 int64 total_usage = info->cached_usage + info->non_cached_usage;
367 int64 unlimited_usage = global_unlimited_usage_ + info->non_cached_usage;
368
369 DCHECK_GE(total_usage, 0);
370 DCHECK_GE(unlimited_usage, 0);
371 if (unlimited_usage > total_usage)
372 unlimited_usage = total_usage;
373
374 global_usage_retrieved_ = true;
375 callback.Run(total_usage, unlimited_usage);
376 }
377
378 void ClientUsageTracker::DidGetOriginsForHostUsage(
379 const std::string& host,
380 const std::set<GURL>& origins,
381 StorageType type) {
382 GetUsageForOrigins(host, origins);
383 }
384
385 void ClientUsageTracker::GetUsageForOrigins(
386 const std::string& host,
387 const std::set<GURL>& origins) {
388 AccumulateInfo* info = new AccumulateInfo;
389 // Getting origin usage may synchronously return the result if the usage is
390 // cached, which may in turn dispatch the completion callback before we finish
391 // looping over all origins (because info->pending_jobs may reach 0 during the
392 // loop). To avoid this, we add one more pending origin as a sentinel and
393 // fire the sentinel callback at the end.
394 info->pending_jobs = origins.size() + 1;
395 OriginUsageAccumulator accumulator =
396 base::Bind(&ClientUsageTracker::AccumulateOriginUsage, AsWeakPtr(),
397 base::Owned(info), host);
398
399 for (std::set<GURL>::const_iterator itr = origins.begin();
400 itr != origins.end(); ++itr) {
401 DCHECK_EQ(host, net::GetHostOrSpecFromURL(*itr));
402
403 int64 origin_usage = 0;
404 if (GetCachedOriginUsage(*itr, &origin_usage)) {
405 accumulator.Run(*itr, origin_usage);
406 } else {
407 client_->GetOriginUsage(*itr, type_, base::Bind(
408 &DidGetOriginUsage, accumulator, *itr));
409 }
410 }
411
412 // Fire the sentinel as we've now called GetOriginUsage for all clients.
413 accumulator.Run(GURL(), 0);
414 }
415
416 void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info,
417 const std::string& host,
418 const GURL& origin,
419 int64 usage) {
420 if (!origin.is_empty()) {
421 if (usage < 0)
422 usage = 0;
423
424 if (IsUsageCacheEnabledForOrigin(origin)) {
425 info->cached_usage += usage;
426 AddCachedOrigin(origin, usage);
427 } else {
428 info->non_cached_usage += usage;
429 }
430 }
431 if (--info->pending_jobs)
432 return;
433
434 AddCachedHost(host);
435 host_usage_accumulators_.Run(
436 host, MakeTuple(info->cached_usage, info->non_cached_usage));
437 }
438
532 void ClientUsageTracker::AddCachedOrigin( 439 void ClientUsageTracker::AddCachedOrigin(
533 const GURL& origin, int64 usage) { 440 const GURL& origin, int64 usage) {
534 if (!IsUsageCacheEnabledForOrigin(origin)) 441 if (!IsUsageCacheEnabledForOrigin(origin))
535 return; 442 return;
536 443
537 std::string host = net::GetHostOrSpecFromURL(origin); 444 std::string host = net::GetHostOrSpecFromURL(origin);
538 UsageMap::iterator iter = cached_usage_by_host_[host]. 445 UsageMap::iterator iter = cached_usage_by_host_[host].
539 insert(UsageMap::value_type(origin, 0)).first; 446 insert(UsageMap::value_type(origin, 0)).first;
540 int64 old_usage = iter->second; 447 int64 old_usage = iter->second;
541 iter->second = usage; 448 iter->second = usage;
542 int64 delta = usage - old_usage; 449 int64 delta = usage - old_usage;
543 if (delta) { 450 if (delta) {
544 global_usage_ += delta; 451 global_usage_ += delta;
545 if (IsStorageUnlimited(origin)) 452 if (IsStorageUnlimited(origin))
546 global_unlimited_usage_ += delta; 453 global_unlimited_usage_ += delta;
547 } 454 }
548 DCHECK_GE(iter->second, 0); 455 DCHECK_GE(iter->second, 0);
549 DCHECK_GE(global_usage_, 0); 456 DCHECK_GE(global_usage_, 0);
550 } 457 }
551 458
552 void ClientUsageTracker::AddCachedHost(const std::string& host) { 459 void ClientUsageTracker::AddCachedHost(const std::string& host) {
553 cached_hosts_.insert(host); 460 cached_hosts_.insert(host);
554 } 461 }
555 462
556 void ClientUsageTracker::GatherGlobalUsageComplete(
557 int64 global_usage,
558 int64 non_cached_global_usage,
559 const std::map<std::string, int64>& non_cached_host_usage) {
560 DCHECK(global_usage_task_ != NULL);
561 global_usage_task_ = NULL;
562 // TODO(kinuko): Record when it has retrieved the global usage.
563 global_usage_retrieved_ = true;
564
565 DCHECK(global_usage_callback_.HasCallbacks());
566 global_usage_callback_.Run(
567 MakeTuple(global_usage,
568 GetCachedGlobalUnlimitedUsage() + non_cached_global_usage));
569
570 for (HostUsageCallbackMap::iterator iter = host_usage_callbacks_.Begin();
571 iter != host_usage_callbacks_.End(); ++iter) {
572 int64 host_usage = GetCachedHostUsage(iter->first);
573 std::map<std::string, int64>::const_iterator found =
574 non_cached_host_usage.find(iter->first);
575 if (found != non_cached_host_usage.end())
576 host_usage += found->second;
577 iter->second.Run(MakeTuple(host_usage));
578 }
579 host_usage_callbacks_.Clear();
580 }
581
582 void ClientUsageTracker::GatherHostUsageComplete(const std::string& host,
583 int64 usage) {
584 DCHECK(host_usage_tasks_.find(host) != host_usage_tasks_.end());
585 host_usage_tasks_.erase(host);
586 host_usage_callbacks_.Run(host, MakeTuple(usage));
587 }
588
589 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { 463 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const {
590 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); 464 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host);
591 if (found == cached_usage_by_host_.end()) 465 if (found == cached_usage_by_host_.end())
592 return 0; 466 return 0;
593 467
594 int64 usage = 0; 468 int64 usage = 0;
595 const UsageMap& map = found->second; 469 const UsageMap& map = found->second;
596 for (UsageMap::const_iterator iter = map.begin(); 470 for (UsageMap::const_iterator iter = map.begin();
597 iter != map.end(); ++iter) { 471 iter != map.end(); ++iter) {
598 usage += iter->second; 472 usage += iter->second;
599 } 473 }
600 return usage; 474 return usage;
601 } 475 }
602 476
603 int64 ClientUsageTracker::GetCachedGlobalUnlimitedUsage() {
604 return global_unlimited_usage_;
605 }
606
607 bool ClientUsageTracker::GetCachedOriginUsage( 477 bool ClientUsageTracker::GetCachedOriginUsage(
608 const GURL& origin, 478 const GURL& origin,
609 int64* usage) const { 479 int64* usage) const {
610 std::string host = net::GetHostOrSpecFromURL(origin); 480 std::string host = net::GetHostOrSpecFromURL(origin);
611 HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); 481 HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host);
612 if (found_host == cached_usage_by_host_.end()) 482 if (found_host == cached_usage_by_host_.end())
613 return false; 483 return false;
614 484
615 UsageMap::const_iterator found = found_host->second.find(origin); 485 UsageMap::const_iterator found = found_host->second.find(origin);
616 if (found == found_host->second.end()) 486 if (found == found_host->second.end())
617 return false; 487 return false;
618 488
489 DCHECK(IsUsageCacheEnabledForOrigin(origin));
619 *usage = found->second; 490 *usage = found->second;
620 return true; 491 return true;
621 } 492 }
622 493
623 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( 494 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin(
624 const GURL& origin) const { 495 const GURL& origin) const {
625 std::string host = net::GetHostOrSpecFromURL(origin); 496 std::string host = net::GetHostOrSpecFromURL(origin);
626 OriginSetByHost::const_iterator found = 497 OriginSetByHost::const_iterator found =
627 non_cached_origins_by_host_.find(host); 498 non_cached_origins_by_host_.find(host);
628 return found == non_cached_origins_by_host_.end() || 499 return found == non_cached_origins_by_host_.end() ||
(...skipping 18 matching lines...) Expand all
647 if (GetCachedOriginUsage(origin, &usage)) 518 if (GetCachedOriginUsage(origin, &usage))
648 global_unlimited_usage_ -= usage; 519 global_unlimited_usage_ -= usage;
649 } 520 }
650 } 521 }
651 522
652 void ClientUsageTracker::OnCleared() { 523 void ClientUsageTracker::OnCleared() {
653 DCHECK(CalledOnValidThread()); 524 DCHECK(CalledOnValidThread());
654 global_unlimited_usage_ = 0; 525 global_unlimited_usage_ = 0;
655 } 526 }
656 527
657 void ClientUsageTracker::NoopHostUsageCallback(int64 usage) {}
658
659 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { 528 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const {
660 if (type_ == kStorageTypeSyncable) 529 if (type_ == kStorageTypeSyncable)
661 return false; 530 return false;
662 return special_storage_policy_.get() && 531 return special_storage_policy_.get() &&
663 special_storage_policy_->IsStorageUnlimited(origin); 532 special_storage_policy_->IsStorageUnlimited(origin);
664 } 533 }
665 534
666 } // namespace quota 535 } // namespace quota
OLDNEW
« no previous file with comments | « webkit/quota/usage_tracker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698