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> |
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 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; | 22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; |
| 23 typedef ClientUsageTracker::OriginSetByHost OriginSetByHost; |
23 | 24 |
24 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, | 25 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, |
25 const GURL& origin, | 26 const GURL& origin, |
26 int64 usage) { | 27 int64 usage) { |
27 accumulator.Run(origin, usage); | 28 accumulator.Run(origin, usage); |
28 } | 29 } |
29 | 30 |
30 void DidGetHostUsage(const UsageCallback& callback, | 31 void DidGetHostUsage(const UsageCallback& callback, |
31 int64 cached_usage, | 32 int64 cached_usage, |
32 int64 non_cached_usage) { | 33 int64 non_cached_usage) { |
33 DCHECK_GE(cached_usage, 0); | 34 DCHECK_GE(cached_usage, 0); |
34 DCHECK_GE(non_cached_usage, 0); | 35 DCHECK_GE(non_cached_usage, 0); |
35 callback.Run(cached_usage + non_cached_usage); | 36 callback.Run(cached_usage + non_cached_usage); |
36 } | 37 } |
37 | 38 |
38 void NoopHostUsageCallback(int64 usage) {} | 39 void NoopHostUsageCallback(int64 usage) {} |
39 | 40 |
| 41 bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, |
| 42 const std::string& host, |
| 43 const GURL& origin) { |
| 44 OriginSetByHost::iterator found = origins_by_host->find(host); |
| 45 if (found == origins_by_host->end()) |
| 46 return false; |
| 47 |
| 48 if (!found->second.erase(origin)) |
| 49 return false; |
| 50 |
| 51 if (found->second.empty()) |
| 52 origins_by_host->erase(host); |
| 53 return true; |
| 54 } |
| 55 |
| 56 bool OriginSetContainsOrigin(const OriginSetByHost& origins, |
| 57 const std::string& host, |
| 58 const GURL& origin) { |
| 59 OriginSetByHost::const_iterator itr = origins.find(host); |
| 60 return itr != origins.end() && ContainsKey(itr->second, origin); |
| 61 } |
| 62 |
40 } // namespace | 63 } // namespace |
41 | 64 |
42 // UsageTracker ---------------------------------------------------------- | 65 // UsageTracker ---------------------------------------------------------- |
43 | 66 |
44 UsageTracker::UsageTracker(const QuotaClientList& clients, | 67 UsageTracker::UsageTracker(const QuotaClientList& clients, |
45 StorageType type, | 68 StorageType type, |
46 SpecialStoragePolicy* special_storage_policy) | 69 SpecialStoragePolicy* special_storage_policy) |
47 : type_(type), | 70 : type_(type), |
48 weak_factory_(this) { | 71 weak_factory_(this) { |
49 for (QuotaClientList::const_iterator iter = clients.begin(); | 72 for (QuotaClientList::const_iterator iter = clients.begin(); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } | 218 } |
196 | 219 |
197 // ClientUsageTracker ---------------------------------------------------- | 220 // ClientUsageTracker ---------------------------------------------------- |
198 | 221 |
199 ClientUsageTracker::ClientUsageTracker( | 222 ClientUsageTracker::ClientUsageTracker( |
200 UsageTracker* tracker, QuotaClient* client, StorageType type, | 223 UsageTracker* tracker, QuotaClient* client, StorageType type, |
201 SpecialStoragePolicy* special_storage_policy) | 224 SpecialStoragePolicy* special_storage_policy) |
202 : tracker_(tracker), | 225 : tracker_(tracker), |
203 client_(client), | 226 client_(client), |
204 type_(type), | 227 type_(type), |
205 global_usage_(0), | 228 global_limited_usage_(0), |
206 global_unlimited_usage_(0), | 229 global_unlimited_usage_(0), |
207 global_usage_retrieved_(false), | 230 global_usage_retrieved_(false), |
208 special_storage_policy_(special_storage_policy) { | 231 special_storage_policy_(special_storage_policy) { |
209 DCHECK(tracker_); | 232 DCHECK(tracker_); |
210 DCHECK(client_); | 233 DCHECK(client_); |
211 if (special_storage_policy_) | 234 if (special_storage_policy_) |
212 special_storage_policy_->AddObserver(this); | 235 special_storage_policy_->AddObserver(this); |
213 } | 236 } |
214 | 237 |
215 ClientUsageTracker::~ClientUsageTracker() { | 238 ClientUsageTracker::~ClientUsageTracker() { |
216 if (special_storage_policy_) | 239 if (special_storage_policy_) |
217 special_storage_policy_->RemoveObserver(this); | 240 special_storage_policy_->RemoveObserver(this); |
218 } | 241 } |
219 | 242 |
220 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | 243 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { |
221 if (global_usage_retrieved_ && non_cached_origins_by_host_.empty()) { | 244 if (global_usage_retrieved_ && |
222 callback.Run(global_usage_, global_unlimited_usage_); | 245 non_cached_limited_origins_by_host_.empty() && |
| 246 non_cached_unlimited_origins_by_host_.empty()) { |
| 247 callback.Run(global_limited_usage_ + global_unlimited_usage_, |
| 248 global_unlimited_usage_); |
223 return; | 249 return; |
224 } | 250 } |
225 | 251 |
226 client_->GetOriginsForType(type_, base::Bind( | 252 client_->GetOriginsForType(type_, base::Bind( |
227 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), | 253 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), |
228 callback)); | 254 callback)); |
229 } | 255 } |
230 | 256 |
231 void ClientUsageTracker::GetHostUsage( | 257 void ClientUsageTracker::GetHostUsage( |
232 const std::string& host, const UsageCallback& callback) { | 258 const std::string& host, const UsageCallback& callback) { |
233 if (ContainsKey(cached_hosts_, host) && | 259 if (ContainsKey(cached_hosts_, host) && |
234 !ContainsKey(non_cached_origins_by_host_, host)) { | 260 !ContainsKey(non_cached_limited_origins_by_host_, host) && |
| 261 !ContainsKey(non_cached_unlimited_origins_by_host_, host)) { |
235 // TODO(kinuko): Drop host_usage_map_ cache periodically. | 262 // TODO(kinuko): Drop host_usage_map_ cache periodically. |
236 callback.Run(GetCachedHostUsage(host)); | 263 callback.Run(GetCachedHostUsage(host)); |
237 return; | 264 return; |
238 } | 265 } |
239 | 266 |
240 if (!host_usage_accumulators_.Add(host, base::Bind( | 267 if (!host_usage_accumulators_.Add(host, base::Bind( |
241 &DidGetHostUsage, callback))) | 268 &DidGetHostUsage, callback))) |
242 return; | 269 return; |
243 client_->GetOriginsForHost(type_, host, base::Bind( | 270 client_->GetOriginsForHost(type_, host, base::Bind( |
244 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); | 271 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); |
245 } | 272 } |
246 | 273 |
247 void ClientUsageTracker::UpdateUsageCache( | 274 void ClientUsageTracker::UpdateUsageCache( |
248 const GURL& origin, int64 delta) { | 275 const GURL& origin, int64 delta) { |
249 std::string host = net::GetHostOrSpecFromURL(origin); | 276 std::string host = net::GetHostOrSpecFromURL(origin); |
250 if (cached_hosts_.find(host) != cached_hosts_.end()) { | 277 if (cached_hosts_.find(host) != cached_hosts_.end()) { |
251 if (!IsUsageCacheEnabledForOrigin(origin)) | 278 if (!IsUsageCacheEnabledForOrigin(origin)) |
252 return; | 279 return; |
253 | 280 |
254 cached_usage_by_host_[host][origin] += delta; | 281 cached_usage_by_host_[host][origin] += delta; |
255 global_usage_ += delta; | |
256 if (IsStorageUnlimited(origin)) | 282 if (IsStorageUnlimited(origin)) |
257 global_unlimited_usage_ += delta; | 283 global_unlimited_usage_ += delta; |
| 284 else |
| 285 global_limited_usage_ += delta; |
258 DCHECK_GE(cached_usage_by_host_[host][origin], 0); | 286 DCHECK_GE(cached_usage_by_host_[host][origin], 0); |
259 DCHECK_GE(global_usage_, 0); | 287 DCHECK_GE(global_limited_usage_, 0); |
260 return; | 288 return; |
261 } | 289 } |
262 | 290 |
263 // We don't know about this host yet, so populate our cache for it. | 291 // We don't know about this host yet, so populate our cache for it. |
264 GetHostUsage(host, base::Bind(&NoopHostUsageCallback)); | 292 GetHostUsage(host, base::Bind(&NoopHostUsageCallback)); |
265 } | 293 } |
266 | 294 |
267 void ClientUsageTracker::GetCachedHostsUsage( | 295 void ClientUsageTracker::GetCachedHostsUsage( |
268 std::map<std::string, int64>* host_usage) const { | 296 std::map<std::string, int64>* host_usage) const { |
269 DCHECK(host_usage); | 297 DCHECK(host_usage); |
(...skipping 30 matching lines...) Expand all Loading... |
300 int64 usage = found->second; | 328 int64 usage = found->second; |
301 UpdateUsageCache(origin, -usage); | 329 UpdateUsageCache(origin, -usage); |
302 cached_usage_for_host.erase(found); | 330 cached_usage_for_host.erase(found); |
303 if (cached_usage_for_host.empty()) { | 331 if (cached_usage_for_host.empty()) { |
304 cached_usage_by_host_.erase(found_host); | 332 cached_usage_by_host_.erase(found_host); |
305 cached_hosts_.erase(host); | 333 cached_hosts_.erase(host); |
306 } | 334 } |
307 } | 335 } |
308 } | 336 } |
309 | 337 |
310 non_cached_origins_by_host_[host].insert(origin); | 338 if (IsStorageUnlimited(origin)) |
| 339 non_cached_unlimited_origins_by_host_[host].insert(origin); |
| 340 else |
| 341 non_cached_limited_origins_by_host_[host].insert(origin); |
311 } else { | 342 } else { |
312 // Erase |origin| from |non_cached_origins_| and invalidate the usage cache | 343 // Erase |origin| from |non_cached_origins_| and invalidate the usage cache |
313 // for the host. | 344 // for the host. |
314 OriginSetByHost::iterator found = non_cached_origins_by_host_.find(host); | 345 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, |
315 if (found == non_cached_origins_by_host_.end()) | 346 host, origin) || |
316 return; | 347 EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, |
317 | 348 host, origin)) { |
318 found->second.erase(origin); | |
319 if (found->second.empty()) { | |
320 non_cached_origins_by_host_.erase(found); | |
321 cached_hosts_.erase(host); | 349 cached_hosts_.erase(host); |
322 global_usage_retrieved_ = false; | 350 global_usage_retrieved_ = false; |
323 } | 351 } |
324 } | 352 } |
325 } | 353 } |
326 | 354 |
327 void ClientUsageTracker::DidGetOriginsForGlobalUsage( | 355 void ClientUsageTracker::DidGetOriginsForGlobalUsage( |
328 const GlobalUsageCallback& callback, | 356 const GlobalUsageCallback& callback, |
329 const std::set<GURL>& origins, StorageType type) { | 357 const std::set<GURL>& origins, StorageType type) { |
330 OriginSetByHost origins_by_host; | 358 OriginSetByHost origins_by_host; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 } | 458 } |
431 if (--info->pending_jobs) | 459 if (--info->pending_jobs) |
432 return; | 460 return; |
433 | 461 |
434 AddCachedHost(host); | 462 AddCachedHost(host); |
435 host_usage_accumulators_.Run( | 463 host_usage_accumulators_.Run( |
436 host, MakeTuple(info->cached_usage, info->non_cached_usage)); | 464 host, MakeTuple(info->cached_usage, info->non_cached_usage)); |
437 } | 465 } |
438 | 466 |
439 void ClientUsageTracker::AddCachedOrigin( | 467 void ClientUsageTracker::AddCachedOrigin( |
440 const GURL& origin, int64 usage) { | 468 const GURL& origin, int64 new_usage) { |
441 if (!IsUsageCacheEnabledForOrigin(origin)) | 469 if (!IsUsageCacheEnabledForOrigin(origin)) |
442 return; | 470 return; |
443 | 471 |
444 std::string host = net::GetHostOrSpecFromURL(origin); | 472 std::string host = net::GetHostOrSpecFromURL(origin); |
445 UsageMap::iterator iter = cached_usage_by_host_[host]. | 473 int64* usage = &cached_usage_by_host_[host][origin]; |
446 insert(UsageMap::value_type(origin, 0)).first; | 474 int64 delta = new_usage - *usage; |
447 int64 old_usage = iter->second; | 475 *usage = new_usage; |
448 iter->second = usage; | |
449 int64 delta = usage - old_usage; | |
450 if (delta) { | 476 if (delta) { |
451 global_usage_ += delta; | |
452 if (IsStorageUnlimited(origin)) | 477 if (IsStorageUnlimited(origin)) |
453 global_unlimited_usage_ += delta; | 478 global_unlimited_usage_ += delta; |
| 479 else |
| 480 global_limited_usage_ += delta; |
454 } | 481 } |
455 DCHECK_GE(iter->second, 0); | 482 DCHECK_GE(*usage, 0); |
456 DCHECK_GE(global_usage_, 0); | 483 DCHECK_GE(global_limited_usage_, 0); |
457 } | 484 } |
458 | 485 |
459 void ClientUsageTracker::AddCachedHost(const std::string& host) { | 486 void ClientUsageTracker::AddCachedHost(const std::string& host) { |
460 cached_hosts_.insert(host); | 487 cached_hosts_.insert(host); |
461 } | 488 } |
462 | 489 |
463 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { | 490 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { |
464 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); | 491 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); |
465 if (found == cached_usage_by_host_.end()) | 492 if (found == cached_usage_by_host_.end()) |
466 return 0; | 493 return 0; |
(...skipping 20 matching lines...) Expand all Loading... |
487 return false; | 514 return false; |
488 | 515 |
489 DCHECK(IsUsageCacheEnabledForOrigin(origin)); | 516 DCHECK(IsUsageCacheEnabledForOrigin(origin)); |
490 *usage = found->second; | 517 *usage = found->second; |
491 return true; | 518 return true; |
492 } | 519 } |
493 | 520 |
494 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( | 521 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( |
495 const GURL& origin) const { | 522 const GURL& origin) const { |
496 std::string host = net::GetHostOrSpecFromURL(origin); | 523 std::string host = net::GetHostOrSpecFromURL(origin); |
497 OriginSetByHost::const_iterator found = | 524 return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_, |
498 non_cached_origins_by_host_.find(host); | 525 host, origin) && |
499 return found == non_cached_origins_by_host_.end() || | 526 !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_, |
500 !ContainsKey(found->second, origin); | 527 host, origin); |
501 } | 528 } |
502 | 529 |
503 void ClientUsageTracker::OnGranted(const GURL& origin, | 530 void ClientUsageTracker::OnGranted(const GURL& origin, |
504 int change_flags) { | 531 int change_flags) { |
505 DCHECK(CalledOnValidThread()); | 532 DCHECK(CalledOnValidThread()); |
506 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { | 533 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { |
507 int64 usage = 0; | 534 int64 usage = 0; |
508 if (GetCachedOriginUsage(origin, &usage)) | 535 if (GetCachedOriginUsage(origin, &usage)) { |
509 global_unlimited_usage_ += usage; | 536 global_unlimited_usage_ += usage; |
| 537 global_limited_usage_ -= usage; |
| 538 } |
| 539 |
| 540 std::string host = net::GetHostOrSpecFromURL(origin); |
| 541 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, |
| 542 host, origin)) |
| 543 non_cached_unlimited_origins_by_host_[host].insert(origin); |
510 } | 544 } |
511 } | 545 } |
512 | 546 |
513 void ClientUsageTracker::OnRevoked(const GURL& origin, | 547 void ClientUsageTracker::OnRevoked(const GURL& origin, |
514 int change_flags) { | 548 int change_flags) { |
515 DCHECK(CalledOnValidThread()); | 549 DCHECK(CalledOnValidThread()); |
516 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { | 550 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { |
517 int64 usage = 0; | 551 int64 usage = 0; |
518 if (GetCachedOriginUsage(origin, &usage)) | 552 if (GetCachedOriginUsage(origin, &usage)) { |
519 global_unlimited_usage_ -= usage; | 553 global_unlimited_usage_ -= usage; |
| 554 global_limited_usage_ += usage; |
| 555 } |
| 556 |
| 557 std::string host = net::GetHostOrSpecFromURL(origin); |
| 558 if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, |
| 559 host, origin)) |
| 560 non_cached_limited_origins_by_host_[host].insert(origin); |
520 } | 561 } |
521 } | 562 } |
522 | 563 |
523 void ClientUsageTracker::OnCleared() { | 564 void ClientUsageTracker::OnCleared() { |
524 DCHECK(CalledOnValidThread()); | 565 DCHECK(CalledOnValidThread()); |
| 566 global_limited_usage_ += global_unlimited_usage_; |
525 global_unlimited_usage_ = 0; | 567 global_unlimited_usage_ = 0; |
| 568 |
| 569 for (OriginSetByHost::const_iterator host_itr = |
| 570 non_cached_unlimited_origins_by_host_.begin(); |
| 571 host_itr != non_cached_unlimited_origins_by_host_.end(); |
| 572 ++host_itr) { |
| 573 for (std::set<GURL>::const_iterator origin_itr = host_itr->second.begin(); |
| 574 origin_itr != host_itr->second.end(); |
| 575 ++origin_itr) |
| 576 non_cached_limited_origins_by_host_[host_itr->first].insert(*origin_itr); |
| 577 } |
| 578 non_cached_unlimited_origins_by_host_.clear(); |
526 } | 579 } |
527 | 580 |
528 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { | 581 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { |
529 if (type_ == kStorageTypeSyncable) | 582 if (type_ == kStorageTypeSyncable) |
530 return false; | 583 return false; |
531 return special_storage_policy_.get() && | 584 return special_storage_policy_.get() && |
532 special_storage_policy_->IsStorageUnlimited(origin); | 585 special_storage_policy_->IsStorageUnlimited(origin); |
533 } | 586 } |
534 | 587 |
535 } // namespace quota | 588 } // namespace quota |
OLD | NEW |