Chromium Code Reviews| 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; |
|
kinuko
2013/05/27 11:54:24
Feels slightly uneasy to use mutable ref...
tzik
2013/05/27 15:13:21
Do you feel easier if I change this to a pointer?
kinuko
2013/05/27 15:27:32
Ah, I like it better.
| |
| 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 itr = | |
| 570 non_cached_unlimited_origins_by_host_.begin(); | |
| 571 itr != non_cached_unlimited_origins_by_host_.end(); | |
| 572 ++itr) { | |
| 573 non_cached_limited_origins_by_host_[ | |
| 574 net::GetHostOrSpecFromURL(origin)].insert(*itr); | |
| 575 } | |
| 576 non_cached_unlimited_origins_by_host_.clear(); | |
| 526 } | 577 } |
| 527 | 578 |
| 528 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { | 579 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { |
| 529 if (type_ == kStorageTypeSyncable) | 580 if (type_ == kStorageTypeSyncable) |
| 530 return false; | 581 return false; |
| 531 return special_storage_policy_.get() && | 582 return special_storage_policy_.get() && |
| 532 special_storage_policy_->IsStorageUnlimited(origin); | 583 special_storage_policy_->IsStorageUnlimited(origin); |
| 533 } | 584 } |
| 534 | 585 |
| 535 } // namespace quota | 586 } // namespace quota |
| OLD | NEW |