OLD | NEW |
---|---|
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> |
(...skipping 11 matching lines...) Expand all Loading... | |
22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; | 22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; |
23 typedef ClientUsageTracker::OriginSetByHost OriginSetByHost; | 23 typedef ClientUsageTracker::OriginSetByHost OriginSetByHost; |
24 | 24 |
25 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, | 25 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, |
26 const GURL& origin, | 26 const GURL& origin, |
27 int64 usage) { | 27 int64 usage) { |
28 accumulator.Run(origin, usage); | 28 accumulator.Run(origin, usage); |
29 } | 29 } |
30 | 30 |
31 void DidGetHostUsage(const UsageCallback& callback, | 31 void DidGetHostUsage(const UsageCallback& callback, |
32 int64 cached_usage, | 32 int64 limited_usage, |
33 int64 non_cached_usage) { | 33 int64 unlimited_usage) { |
34 DCHECK_GE(cached_usage, 0); | 34 DCHECK_GE(limited_usage, 0); |
35 DCHECK_GE(non_cached_usage, 0); | 35 DCHECK_GE(unlimited_usage, 0); |
36 callback.Run(cached_usage + non_cached_usage); | 36 callback.Run(limited_usage + unlimited_usage); |
37 } | 37 } |
38 | 38 |
39 void NoopHostUsageCallback(int64 usage) {} | 39 void NoopHostUsageCallback(int64 usage) {} |
40 | 40 |
41 bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, | 41 bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, |
42 const std::string& host, | 42 const std::string& host, |
43 const GURL& origin) { | 43 const GURL& origin) { |
44 OriginSetByHost::iterator found = origins_by_host->find(host); | 44 OriginSetByHost::iterator found = origins_by_host->find(host); |
45 if (found == origins_by_host->end()) | 45 if (found == origins_by_host->end()) |
46 return false; | 46 return false; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
88 } | 88 } |
89 | 89 |
90 ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) { | 90 ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) { |
91 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); | 91 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); |
92 if (found != client_tracker_map_.end()) | 92 if (found != client_tracker_map_.end()) |
93 return found->second; | 93 return found->second; |
94 return NULL; | 94 return NULL; |
95 } | 95 } |
96 | 96 |
97 void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { | 97 void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { |
98 GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage, callback)); | 98 if (global_usage_callbacks_.HasCallbacks()) { |
99 global_usage_callbacks_.Add(base::Bind( | |
100 &DidGetGlobalUsageForLimitedGlobalUsage, callback)); | |
101 return; | |
102 } | |
103 | |
104 if (!global_limited_usage_callbacks_.Add(callback)) | |
105 return; | |
106 | |
107 AccumulateInfo* info = new AccumulateInfo; | |
108 // Calling GetGlobalLimitedUsage(accumulator) may synchronously | |
109 // return if the usage is cached, which may in turn dispatch | |
110 // the completion callback before we finish looping over | |
111 // all clients (because info->pending_clients may reach 0 | |
112 // during the loop). | |
113 // To avoid this, we add one more pending client as a sentinel | |
114 // and fire the sentinel callback at the end. | |
115 info->pending_clients = client_tracker_map_.size() + 1; | |
116 UsageCallback accumulator = base::Bind( | |
117 &UsageTracker::AccumulateClientGlobalLimitedUsage, | |
118 weak_factory_.GetWeakPtr(), base::Owned(info)); | |
119 | |
120 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); | |
121 iter != client_tracker_map_.end(); | |
122 ++iter) | |
123 iter->second->GetGlobalLimitedUsage(accumulator); | |
124 | |
125 // Fire the sentinel as we've now called GetGlobalUsage for all clients. | |
126 accumulator.Run(0); | |
kinuko
2013/05/30 05:56:32
Hmm, can we possibly cleanup this pattern in a sep
| |
99 } | 127 } |
100 | 128 |
101 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | 129 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { |
102 if (!global_usage_callbacks_.Add(callback)) | 130 if (!global_usage_callbacks_.Add(callback)) |
103 return; | 131 return; |
104 | 132 |
105 AccumulateInfo* info = new AccumulateInfo; | 133 AccumulateInfo* info = new AccumulateInfo; |
106 // Calling GetGlobalUsage(accumulator) may synchronously | 134 // Calling GetGlobalUsage(accumulator) may synchronously |
107 // return if the usage is cached, which may in turn dispatch | 135 // return if the usage is cached, which may in turn dispatch |
108 // the completion callback before we finish looping over | 136 // the completion callback before we finish looping over |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 | 207 |
180 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, | 208 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, |
181 const GURL& origin, | 209 const GURL& origin, |
182 bool enabled) { | 210 bool enabled) { |
183 ClientUsageTracker* client_tracker = GetClientTracker(client_id); | 211 ClientUsageTracker* client_tracker = GetClientTracker(client_id); |
184 DCHECK(client_tracker); | 212 DCHECK(client_tracker); |
185 | 213 |
186 client_tracker->SetUsageCacheEnabled(origin, enabled); | 214 client_tracker->SetUsageCacheEnabled(origin, enabled); |
187 } | 215 } |
188 | 216 |
217 void UsageTracker::AccumulateClientGlobalLimitedUsage(AccumulateInfo* info, | |
218 int64 limited_usage) { | |
219 info->usage += limited_usage; | |
220 if (--info->pending_clients) | |
221 return; | |
222 | |
223 // All the clients have returned their usage data. Dispatch the | |
224 // pending callbacks. | |
225 global_limited_usage_callbacks_.Run(MakeTuple(info->usage)); | |
226 } | |
227 | |
189 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, | 228 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, |
190 int64 usage, | 229 int64 usage, |
191 int64 unlimited_usage) { | 230 int64 unlimited_usage) { |
192 info->usage += usage; | 231 info->usage += usage; |
193 info->unlimited_usage += unlimited_usage; | 232 info->unlimited_usage += unlimited_usage; |
194 | |
195 if (--info->pending_clients) | 233 if (--info->pending_clients) |
196 return; | 234 return; |
197 | 235 |
198 // Defend against confusing inputs from clients. | 236 // Defend against confusing inputs from clients. |
199 if (info->usage < 0) | 237 if (info->usage < 0) |
200 info->usage = 0; | 238 info->usage = 0; |
201 | 239 |
202 // TODO(michaeln): The unlimited number is not trustworthy, it | 240 // TODO(michaeln): The unlimited number is not trustworthy, it |
203 // can get out of whack when apps are installed or uninstalled. | 241 // can get out of whack when apps are installed or uninstalled. |
204 if (info->unlimited_usage > info->usage) | 242 if (info->unlimited_usage > info->usage) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 DCHECK(client_); | 281 DCHECK(client_); |
244 if (special_storage_policy_) | 282 if (special_storage_policy_) |
245 special_storage_policy_->AddObserver(this); | 283 special_storage_policy_->AddObserver(this); |
246 } | 284 } |
247 | 285 |
248 ClientUsageTracker::~ClientUsageTracker() { | 286 ClientUsageTracker::~ClientUsageTracker() { |
249 if (special_storage_policy_) | 287 if (special_storage_policy_) |
250 special_storage_policy_->RemoveObserver(this); | 288 special_storage_policy_->RemoveObserver(this); |
251 } | 289 } |
252 | 290 |
291 void ClientUsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { | |
292 if (!global_usage_retrieved_) { | |
293 GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage, | |
294 callback)); | |
295 return; | |
296 } | |
297 | |
298 if (non_cached_limited_origins_by_host_.empty()) { | |
299 callback.Run(global_limited_usage_); | |
300 return; | |
301 } | |
302 | |
303 AccumulateInfo* info = new AccumulateInfo; | |
304 info->pending_jobs = non_cached_limited_origins_by_host_.size() + 1; | |
305 UsageCallback accumulator = base::Bind( | |
306 &ClientUsageTracker::AccumulateLimitedOriginUsage, AsWeakPtr(), | |
307 base::Owned(info), callback); | |
308 | |
309 for (OriginSetByHost::iterator host_itr = | |
310 non_cached_limited_origins_by_host_.begin(); | |
311 host_itr != non_cached_limited_origins_by_host_.end(); ++host_itr) { | |
312 for (std::set<GURL>::iterator origin_itr = host_itr->second.begin(); | |
313 origin_itr != host_itr->second.end(); ++origin_itr) | |
314 client_->GetOriginUsage(*origin_itr, type_, accumulator); | |
315 } | |
316 | |
317 accumulator.Run(global_limited_usage_); | |
318 } | |
319 | |
253 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | 320 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { |
254 if (global_usage_retrieved_ && | 321 if (global_usage_retrieved_ && |
255 non_cached_limited_origins_by_host_.empty() && | 322 non_cached_limited_origins_by_host_.empty() && |
256 non_cached_unlimited_origins_by_host_.empty()) { | 323 non_cached_unlimited_origins_by_host_.empty()) { |
257 callback.Run(global_limited_usage_ + global_unlimited_usage_, | 324 callback.Run(global_limited_usage_ + global_unlimited_usage_, |
258 global_unlimited_usage_); | 325 global_unlimited_usage_); |
259 return; | 326 return; |
260 } | 327 } |
261 | 328 |
262 client_->GetOriginsForType(type_, base::Bind( | 329 client_->GetOriginsForType(type_, base::Bind( |
263 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), | 330 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), |
264 callback)); | 331 callback)); |
265 } | 332 } |
266 | 333 |
267 void ClientUsageTracker::GetHostUsage( | 334 void ClientUsageTracker::GetHostUsage( |
268 const std::string& host, const UsageCallback& callback) { | 335 const std::string& host, const UsageCallback& callback) { |
269 if (ContainsKey(cached_hosts_, host) && | 336 if (ContainsKey(cached_hosts_, host) && |
270 !ContainsKey(non_cached_limited_origins_by_host_, host) && | 337 !ContainsKey(non_cached_limited_origins_by_host_, host) && |
271 !ContainsKey(non_cached_unlimited_origins_by_host_, host)) { | 338 !ContainsKey(non_cached_unlimited_origins_by_host_, host)) { |
272 // TODO(kinuko): Drop host_usage_map_ cache periodically. | 339 // TODO(kinuko): Drop host_usage_map_ cache periodically. |
273 callback.Run(GetCachedHostUsage(host)); | 340 callback.Run(GetCachedHostUsage(host)); |
274 return; | 341 return; |
275 } | 342 } |
276 | 343 |
277 if (!host_usage_accumulators_.Add(host, base::Bind( | 344 if (!host_usage_accumulators_.Add( |
278 &DidGetHostUsage, callback))) | 345 host, base::Bind(&DidGetHostUsage, callback))) |
279 return; | 346 return; |
280 client_->GetOriginsForHost(type_, host, base::Bind( | 347 client_->GetOriginsForHost(type_, host, base::Bind( |
281 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); | 348 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); |
282 } | 349 } |
283 | 350 |
284 void ClientUsageTracker::UpdateUsageCache( | 351 void ClientUsageTracker::UpdateUsageCache( |
285 const GURL& origin, int64 delta) { | 352 const GURL& origin, int64 delta) { |
286 std::string host = net::GetHostOrSpecFromURL(origin); | 353 std::string host = net::GetHostOrSpecFromURL(origin); |
287 if (cached_hosts_.find(host) != cached_hosts_.end()) { | 354 if (cached_hosts_.find(host) != cached_hosts_.end()) { |
288 if (!IsUsageCacheEnabledForOrigin(origin)) | 355 if (!IsUsageCacheEnabledForOrigin(origin)) |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, | 422 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, |
356 host, origin) || | 423 host, origin) || |
357 EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, | 424 EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, |
358 host, origin)) { | 425 host, origin)) { |
359 cached_hosts_.erase(host); | 426 cached_hosts_.erase(host); |
360 global_usage_retrieved_ = false; | 427 global_usage_retrieved_ = false; |
361 } | 428 } |
362 } | 429 } |
363 } | 430 } |
364 | 431 |
432 void ClientUsageTracker::AccumulateLimitedOriginUsage( | |
433 AccumulateInfo* info, | |
434 const UsageCallback& callback, | |
435 int64 usage) { | |
436 info->limited_usage += usage; | |
437 if (--info->pending_jobs) | |
438 return; | |
439 | |
440 callback.Run(info->limited_usage); | |
441 } | |
442 | |
365 void ClientUsageTracker::DidGetOriginsForGlobalUsage( | 443 void ClientUsageTracker::DidGetOriginsForGlobalUsage( |
366 const GlobalUsageCallback& callback, | 444 const GlobalUsageCallback& callback, |
367 const std::set<GURL>& origins) { | 445 const std::set<GURL>& origins) { |
368 OriginSetByHost origins_by_host; | 446 OriginSetByHost origins_by_host; |
369 for (std::set<GURL>::const_iterator itr = origins.begin(); | 447 for (std::set<GURL>::const_iterator itr = origins.begin(); |
370 itr != origins.end(); ++itr) | 448 itr != origins.end(); ++itr) |
371 origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr); | 449 origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr); |
372 | 450 |
373 AccumulateInfo* info = new AccumulateInfo; | 451 AccumulateInfo* info = new AccumulateInfo; |
374 // Getting host usage may synchronously return the result if the usage is | 452 // Getting host usage may synchronously return the result if the usage is |
(...skipping 12 matching lines...) Expand all Loading... | |
387 GetUsageForOrigins(itr->first, itr->second); | 465 GetUsageForOrigins(itr->first, itr->second); |
388 } | 466 } |
389 | 467 |
390 // Fire the sentinel as we've now called GetUsageForOrigins for all clients. | 468 // Fire the sentinel as we've now called GetUsageForOrigins for all clients. |
391 accumulator.Run(0, 0); | 469 accumulator.Run(0, 0); |
392 } | 470 } |
393 | 471 |
394 void ClientUsageTracker::AccumulateHostUsage( | 472 void ClientUsageTracker::AccumulateHostUsage( |
395 AccumulateInfo* info, | 473 AccumulateInfo* info, |
396 const GlobalUsageCallback& callback, | 474 const GlobalUsageCallback& callback, |
397 int64 cached_usage, | 475 int64 limited_usage, |
398 int64 non_cached_usage) { | 476 int64 unlimited_usage) { |
399 info->cached_usage += cached_usage; | 477 info->limited_usage += limited_usage; |
400 info->non_cached_usage += non_cached_usage; | 478 info->unlimited_usage += unlimited_usage; |
401 if (--info->pending_jobs) | 479 if (--info->pending_jobs) |
402 return; | 480 return; |
403 | 481 |
404 int64 total_usage = info->cached_usage + info->non_cached_usage; | 482 DCHECK_GE(info->limited_usage, 0); |
405 int64 unlimited_usage = global_unlimited_usage_ + info->non_cached_usage; | 483 DCHECK_GE(info->unlimited_usage, 0); |
406 | |
407 DCHECK_GE(total_usage, 0); | |
408 DCHECK_GE(unlimited_usage, 0); | |
409 if (unlimited_usage > total_usage) | |
410 unlimited_usage = total_usage; | |
411 | 484 |
412 global_usage_retrieved_ = true; | 485 global_usage_retrieved_ = true; |
413 callback.Run(total_usage, unlimited_usage); | 486 callback.Run(info->limited_usage + info->unlimited_usage, |
487 info->unlimited_usage); | |
414 } | 488 } |
415 | 489 |
416 void ClientUsageTracker::DidGetOriginsForHostUsage( | 490 void ClientUsageTracker::DidGetOriginsForHostUsage( |
417 const std::string& host, | 491 const std::string& host, |
418 const std::set<GURL>& origins) { | 492 const std::set<GURL>& origins) { |
419 GetUsageForOrigins(host, origins); | 493 GetUsageForOrigins(host, origins); |
420 } | 494 } |
421 | 495 |
422 void ClientUsageTracker::GetUsageForOrigins( | 496 void ClientUsageTracker::GetUsageForOrigins( |
423 const std::string& host, | 497 const std::string& host, |
(...skipping 27 matching lines...) Expand all Loading... | |
451 } | 525 } |
452 | 526 |
453 void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, | 527 void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, |
454 const std::string& host, | 528 const std::string& host, |
455 const GURL& origin, | 529 const GURL& origin, |
456 int64 usage) { | 530 int64 usage) { |
457 if (!origin.is_empty()) { | 531 if (!origin.is_empty()) { |
458 if (usage < 0) | 532 if (usage < 0) |
459 usage = 0; | 533 usage = 0; |
460 | 534 |
461 if (IsUsageCacheEnabledForOrigin(origin)) { | 535 if (IsStorageUnlimited(origin)) |
462 info->cached_usage += usage; | 536 info->unlimited_usage += usage; |
537 else | |
538 info->limited_usage += usage; | |
539 if (IsUsageCacheEnabledForOrigin(origin)) | |
463 AddCachedOrigin(origin, usage); | 540 AddCachedOrigin(origin, usage); |
464 } else { | |
465 info->non_cached_usage += usage; | |
466 } | |
467 } | 541 } |
468 if (--info->pending_jobs) | 542 if (--info->pending_jobs) |
469 return; | 543 return; |
470 | 544 |
471 AddCachedHost(host); | 545 AddCachedHost(host); |
472 host_usage_accumulators_.Run( | 546 host_usage_accumulators_.Run( |
473 host, MakeTuple(info->cached_usage, info->non_cached_usage)); | 547 host, MakeTuple(info->limited_usage, info->unlimited_usage)); |
474 } | 548 } |
475 | 549 |
476 void ClientUsageTracker::AddCachedOrigin( | 550 void ClientUsageTracker::AddCachedOrigin( |
477 const GURL& origin, int64 new_usage) { | 551 const GURL& origin, int64 new_usage) { |
478 if (!IsUsageCacheEnabledForOrigin(origin)) | 552 DCHECK(IsUsageCacheEnabledForOrigin(origin)); |
479 return; | |
480 | 553 |
481 std::string host = net::GetHostOrSpecFromURL(origin); | 554 std::string host = net::GetHostOrSpecFromURL(origin); |
482 int64* usage = &cached_usage_by_host_[host][origin]; | 555 int64* usage = &cached_usage_by_host_[host][origin]; |
483 int64 delta = new_usage - *usage; | 556 int64 delta = new_usage - *usage; |
484 *usage = new_usage; | 557 *usage = new_usage; |
485 if (delta) { | 558 if (delta) { |
486 if (IsStorageUnlimited(origin)) | 559 if (IsStorageUnlimited(origin)) |
487 global_unlimited_usage_ += delta; | 560 global_unlimited_usage_ += delta; |
488 else | 561 else |
489 global_limited_usage_ += delta; | 562 global_limited_usage_ += delta; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 } | 661 } |
589 | 662 |
590 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { | 663 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { |
591 if (type_ == kStorageTypeSyncable) | 664 if (type_ == kStorageTypeSyncable) |
592 return false; | 665 return false; |
593 return special_storage_policy_.get() && | 666 return special_storage_policy_.get() && |
594 special_storage_policy_->IsStorageUnlimited(origin); | 667 special_storage_policy_->IsStorageUnlimited(origin); |
595 } | 668 } |
596 | 669 |
597 } // namespace quota | 670 } // namespace quota |
OLD | NEW |