| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "webkit/quota/usage_tracker.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <deque> | |
| 9 #include <set> | |
| 10 #include <string> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/message_loop_proxy.h" | |
| 15 #include "base/stl_util.h" | |
| 16 #include "net/base/net_util.h" | |
| 17 | |
| 18 namespace quota { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; | |
| 23 typedef ClientUsageTracker::OriginSetByHost OriginSetByHost; | |
| 24 | |
| 25 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, | |
| 26 const GURL& origin, | |
| 27 int64 usage) { | |
| 28 accumulator.Run(origin, usage); | |
| 29 } | |
| 30 | |
| 31 void DidGetHostUsage(const UsageCallback& callback, | |
| 32 int64 cached_usage, | |
| 33 int64 non_cached_usage) { | |
| 34 DCHECK_GE(cached_usage, 0); | |
| 35 DCHECK_GE(non_cached_usage, 0); | |
| 36 callback.Run(cached_usage + non_cached_usage); | |
| 37 } | |
| 38 | |
| 39 void NoopHostUsageCallback(int64 usage) {} | |
| 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 | |
| 63 void DidGetGlobalUsageForLimitedGlobalUsage(const UsageCallback& callback, | |
| 64 int64 total_global_usage, | |
| 65 int64 global_unlimited_usage) { | |
| 66 callback.Run(total_global_usage - global_unlimited_usage); | |
| 67 } | |
| 68 | |
| 69 } // namespace | |
| 70 | |
| 71 // UsageTracker ---------------------------------------------------------- | |
| 72 | |
| 73 UsageTracker::UsageTracker(const QuotaClientList& clients, | |
| 74 StorageType type, | |
| 75 SpecialStoragePolicy* special_storage_policy) | |
| 76 : type_(type), | |
| 77 weak_factory_(this) { | |
| 78 for (QuotaClientList::const_iterator iter = clients.begin(); | |
| 79 iter != clients.end(); | |
| 80 ++iter) { | |
| 81 client_tracker_map_[(*iter)->id()] = | |
| 82 new ClientUsageTracker(this, *iter, type, special_storage_policy); | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 UsageTracker::~UsageTracker() { | |
| 87 STLDeleteValues(&client_tracker_map_); | |
| 88 } | |
| 89 | |
| 90 ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) { | |
| 91 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); | |
| 92 if (found != client_tracker_map_.end()) | |
| 93 return found->second; | |
| 94 return NULL; | |
| 95 } | |
| 96 | |
| 97 void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { | |
| 98 GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage, callback)); | |
| 99 } | |
| 100 | |
| 101 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | |
| 102 if (!global_usage_callbacks_.Add(callback)) | |
| 103 return; | |
| 104 | |
| 105 AccumulateInfo* info = new AccumulateInfo; | |
| 106 // Calling GetGlobalUsage(accumulator) may synchronously | |
| 107 // return if the usage is cached, which may in turn dispatch | |
| 108 // the completion callback before we finish looping over | |
| 109 // all clients (because info->pending_clients may reach 0 | |
| 110 // during the loop). | |
| 111 // To avoid this, we add one more pending client as a sentinel | |
| 112 // and fire the sentinel callback at the end. | |
| 113 info->pending_clients = client_tracker_map_.size() + 1; | |
| 114 GlobalUsageCallback accumulator = base::Bind( | |
| 115 &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(), | |
| 116 base::Owned(info)); | |
| 117 | |
| 118 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); | |
| 119 iter != client_tracker_map_.end(); | |
| 120 ++iter) | |
| 121 iter->second->GetGlobalUsage(accumulator); | |
| 122 | |
| 123 // Fire the sentinel as we've now called GetGlobalUsage for all clients. | |
| 124 accumulator.Run(0, 0); | |
| 125 } | |
| 126 | |
| 127 void UsageTracker::GetHostUsage(const std::string& host, | |
| 128 const UsageCallback& callback) { | |
| 129 if (!host_usage_callbacks_.Add(host, callback)) | |
| 130 return; | |
| 131 | |
| 132 AccumulateInfo* info = new AccumulateInfo; | |
| 133 // Calling GetHostUsage(accumulator) may synchronously | |
| 134 // return if the usage is cached, which may in turn dispatch | |
| 135 // the completion callback before we finish looping over | |
| 136 // all clients (because info->pending_clients may reach 0 | |
| 137 // during the loop). | |
| 138 // To avoid this, we add one more pending client as a sentinel | |
| 139 // and fire the sentinel callback at the end. | |
| 140 info->pending_clients = client_tracker_map_.size() + 1; | |
| 141 UsageCallback accumulator = base::Bind( | |
| 142 &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(), | |
| 143 base::Owned(info), host); | |
| 144 | |
| 145 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); | |
| 146 iter != client_tracker_map_.end(); | |
| 147 ++iter) | |
| 148 iter->second->GetHostUsage(host, accumulator); | |
| 149 | |
| 150 // Fire the sentinel as we've now called GetHostUsage for all clients. | |
| 151 accumulator.Run(0); | |
| 152 } | |
| 153 | |
| 154 void UsageTracker::UpdateUsageCache( | |
| 155 QuotaClient::ID client_id, const GURL& origin, int64 delta) { | |
| 156 ClientUsageTracker* client_tracker = GetClientTracker(client_id); | |
| 157 DCHECK(client_tracker); | |
| 158 client_tracker->UpdateUsageCache(origin, delta); | |
| 159 } | |
| 160 | |
| 161 void UsageTracker::GetCachedHostsUsage( | |
| 162 std::map<std::string, int64>* host_usage) const { | |
| 163 DCHECK(host_usage); | |
| 164 host_usage->clear(); | |
| 165 for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin(); | |
| 166 iter != client_tracker_map_.end(); ++iter) { | |
| 167 iter->second->GetCachedHostsUsage(host_usage); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 void UsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { | |
| 172 DCHECK(origins); | |
| 173 origins->clear(); | |
| 174 for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin(); | |
| 175 iter != client_tracker_map_.end(); ++iter) { | |
| 176 iter->second->GetCachedOrigins(origins); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, | |
| 181 const GURL& origin, | |
| 182 bool enabled) { | |
| 183 ClientUsageTracker* client_tracker = GetClientTracker(client_id); | |
| 184 DCHECK(client_tracker); | |
| 185 | |
| 186 client_tracker->SetUsageCacheEnabled(origin, enabled); | |
| 187 } | |
| 188 | |
| 189 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, | |
| 190 int64 usage, | |
| 191 int64 unlimited_usage) { | |
| 192 info->usage += usage; | |
| 193 info->unlimited_usage += unlimited_usage; | |
| 194 | |
| 195 if (--info->pending_clients) | |
| 196 return; | |
| 197 | |
| 198 // Defend against confusing inputs from clients. | |
| 199 if (info->usage < 0) | |
| 200 info->usage = 0; | |
| 201 | |
| 202 // TODO(michaeln): The unlimited number is not trustworthy, it | |
| 203 // can get out of whack when apps are installed or uninstalled. | |
| 204 if (info->unlimited_usage > info->usage) | |
| 205 info->unlimited_usage = info->usage; | |
| 206 else if (info->unlimited_usage < 0) | |
| 207 info->unlimited_usage = 0; | |
| 208 | |
| 209 // All the clients have returned their usage data. Dispatch the | |
| 210 // pending callbacks. | |
| 211 global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage)); | |
| 212 } | |
| 213 | |
| 214 void UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info, | |
| 215 const std::string& host, | |
| 216 int64 usage) { | |
| 217 info->usage += usage; | |
| 218 if (--info->pending_clients) | |
| 219 return; | |
| 220 | |
| 221 // Defend against confusing inputs from clients. | |
| 222 if (info->usage < 0) | |
| 223 info->usage = 0; | |
| 224 | |
| 225 // All the clients have returned their usage data. Dispatch the | |
| 226 // pending callbacks. | |
| 227 host_usage_callbacks_.Run(host, MakeTuple(info->usage)); | |
| 228 } | |
| 229 | |
| 230 // ClientUsageTracker ---------------------------------------------------- | |
| 231 | |
| 232 ClientUsageTracker::ClientUsageTracker( | |
| 233 UsageTracker* tracker, QuotaClient* client, StorageType type, | |
| 234 SpecialStoragePolicy* special_storage_policy) | |
| 235 : tracker_(tracker), | |
| 236 client_(client), | |
| 237 type_(type), | |
| 238 global_limited_usage_(0), | |
| 239 global_unlimited_usage_(0), | |
| 240 global_usage_retrieved_(false), | |
| 241 special_storage_policy_(special_storage_policy) { | |
| 242 DCHECK(tracker_); | |
| 243 DCHECK(client_); | |
| 244 if (special_storage_policy_) | |
| 245 special_storage_policy_->AddObserver(this); | |
| 246 } | |
| 247 | |
| 248 ClientUsageTracker::~ClientUsageTracker() { | |
| 249 if (special_storage_policy_) | |
| 250 special_storage_policy_->RemoveObserver(this); | |
| 251 } | |
| 252 | |
| 253 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | |
| 254 if (global_usage_retrieved_ && | |
| 255 non_cached_limited_origins_by_host_.empty() && | |
| 256 non_cached_unlimited_origins_by_host_.empty()) { | |
| 257 callback.Run(global_limited_usage_ + global_unlimited_usage_, | |
| 258 global_unlimited_usage_); | |
| 259 return; | |
| 260 } | |
| 261 | |
| 262 client_->GetOriginsForType(type_, base::Bind( | |
| 263 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), | |
| 264 callback)); | |
| 265 } | |
| 266 | |
| 267 void ClientUsageTracker::GetHostUsage( | |
| 268 const std::string& host, const UsageCallback& callback) { | |
| 269 if (ContainsKey(cached_hosts_, host) && | |
| 270 !ContainsKey(non_cached_limited_origins_by_host_, host) && | |
| 271 !ContainsKey(non_cached_unlimited_origins_by_host_, host)) { | |
| 272 // TODO(kinuko): Drop host_usage_map_ cache periodically. | |
| 273 callback.Run(GetCachedHostUsage(host)); | |
| 274 return; | |
| 275 } | |
| 276 | |
| 277 if (!host_usage_accumulators_.Add(host, base::Bind( | |
| 278 &DidGetHostUsage, callback))) | |
| 279 return; | |
| 280 client_->GetOriginsForHost(type_, host, base::Bind( | |
| 281 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); | |
| 282 } | |
| 283 | |
| 284 void ClientUsageTracker::UpdateUsageCache( | |
| 285 const GURL& origin, int64 delta) { | |
| 286 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 287 if (cached_hosts_.find(host) != cached_hosts_.end()) { | |
| 288 if (!IsUsageCacheEnabledForOrigin(origin)) | |
| 289 return; | |
| 290 | |
| 291 cached_usage_by_host_[host][origin] += delta; | |
| 292 if (IsStorageUnlimited(origin)) | |
| 293 global_unlimited_usage_ += delta; | |
| 294 else | |
| 295 global_limited_usage_ += delta; | |
| 296 DCHECK_GE(cached_usage_by_host_[host][origin], 0); | |
| 297 DCHECK_GE(global_limited_usage_, 0); | |
| 298 return; | |
| 299 } | |
| 300 | |
| 301 // We don't know about this host yet, so populate our cache for it. | |
| 302 GetHostUsage(host, base::Bind(&NoopHostUsageCallback)); | |
| 303 } | |
| 304 | |
| 305 void ClientUsageTracker::GetCachedHostsUsage( | |
| 306 std::map<std::string, int64>* host_usage) const { | |
| 307 DCHECK(host_usage); | |
| 308 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); | |
| 309 host_iter != cached_usage_by_host_.end(); host_iter++) { | |
| 310 const std::string& host = host_iter->first; | |
| 311 (*host_usage)[host] += GetCachedHostUsage(host); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { | |
| 316 DCHECK(origins); | |
| 317 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); | |
| 318 host_iter != cached_usage_by_host_.end(); host_iter++) { | |
| 319 const UsageMap& origin_map = host_iter->second; | |
| 320 for (UsageMap::const_iterator origin_iter = origin_map.begin(); | |
| 321 origin_iter != origin_map.end(); origin_iter++) { | |
| 322 origins->insert(origin_iter->first); | |
| 323 } | |
| 324 } | |
| 325 } | |
| 326 | |
| 327 void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, | |
| 328 bool enabled) { | |
| 329 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 330 if (!enabled) { | |
| 331 // Erase |origin| from cache and subtract its usage. | |
| 332 HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); | |
| 333 if (found_host != cached_usage_by_host_.end()) { | |
| 334 UsageMap& cached_usage_for_host = found_host->second; | |
| 335 | |
| 336 UsageMap::iterator found = cached_usage_for_host.find(origin); | |
| 337 if (found != cached_usage_for_host.end()) { | |
| 338 int64 usage = found->second; | |
| 339 UpdateUsageCache(origin, -usage); | |
| 340 cached_usage_for_host.erase(found); | |
| 341 if (cached_usage_for_host.empty()) { | |
| 342 cached_usage_by_host_.erase(found_host); | |
| 343 cached_hosts_.erase(host); | |
| 344 } | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 if (IsStorageUnlimited(origin)) | |
| 349 non_cached_unlimited_origins_by_host_[host].insert(origin); | |
| 350 else | |
| 351 non_cached_limited_origins_by_host_[host].insert(origin); | |
| 352 } else { | |
| 353 // Erase |origin| from |non_cached_origins_| and invalidate the usage cache | |
| 354 // for the host. | |
| 355 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, | |
| 356 host, origin) || | |
| 357 EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, | |
| 358 host, origin)) { | |
| 359 cached_hosts_.erase(host); | |
| 360 global_usage_retrieved_ = false; | |
| 361 } | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 void ClientUsageTracker::DidGetOriginsForGlobalUsage( | |
| 366 const GlobalUsageCallback& callback, | |
| 367 const std::set<GURL>& origins) { | |
| 368 OriginSetByHost origins_by_host; | |
| 369 for (std::set<GURL>::const_iterator itr = origins.begin(); | |
| 370 itr != origins.end(); ++itr) | |
| 371 origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr); | |
| 372 | |
| 373 AccumulateInfo* info = new AccumulateInfo; | |
| 374 // Getting host usage may synchronously return the result if the usage is | |
| 375 // cached, which may in turn dispatch the completion callback before we finish | |
| 376 // looping over all hosts (because info->pending_jobs may reach 0 during the | |
| 377 // loop). To avoid this, we add one more pending host as a sentinel and | |
| 378 // fire the sentinel callback at the end. | |
| 379 info->pending_jobs = origins_by_host.size() + 1; | |
| 380 HostUsageAccumulator accumulator = | |
| 381 base::Bind(&ClientUsageTracker::AccumulateHostUsage, AsWeakPtr(), | |
| 382 base::Owned(info), callback); | |
| 383 | |
| 384 for (OriginSetByHost::iterator itr = origins_by_host.begin(); | |
| 385 itr != origins_by_host.end(); ++itr) { | |
| 386 if (host_usage_accumulators_.Add(itr->first, accumulator)) | |
| 387 GetUsageForOrigins(itr->first, itr->second); | |
| 388 } | |
| 389 | |
| 390 // Fire the sentinel as we've now called GetUsageForOrigins for all clients. | |
| 391 accumulator.Run(0, 0); | |
| 392 } | |
| 393 | |
| 394 void ClientUsageTracker::AccumulateHostUsage( | |
| 395 AccumulateInfo* info, | |
| 396 const GlobalUsageCallback& callback, | |
| 397 int64 cached_usage, | |
| 398 int64 non_cached_usage) { | |
| 399 info->cached_usage += cached_usage; | |
| 400 info->non_cached_usage += non_cached_usage; | |
| 401 if (--info->pending_jobs) | |
| 402 return; | |
| 403 | |
| 404 int64 total_usage = info->cached_usage + info->non_cached_usage; | |
| 405 int64 unlimited_usage = global_unlimited_usage_ + info->non_cached_usage; | |
| 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 | |
| 412 global_usage_retrieved_ = true; | |
| 413 callback.Run(total_usage, unlimited_usage); | |
| 414 } | |
| 415 | |
| 416 void ClientUsageTracker::DidGetOriginsForHostUsage( | |
| 417 const std::string& host, | |
| 418 const std::set<GURL>& origins) { | |
| 419 GetUsageForOrigins(host, origins); | |
| 420 } | |
| 421 | |
| 422 void ClientUsageTracker::GetUsageForOrigins( | |
| 423 const std::string& host, | |
| 424 const std::set<GURL>& origins) { | |
| 425 AccumulateInfo* info = new AccumulateInfo; | |
| 426 // Getting origin usage may synchronously return the result if the usage is | |
| 427 // cached, which may in turn dispatch the completion callback before we finish | |
| 428 // looping over all origins (because info->pending_jobs may reach 0 during the | |
| 429 // loop). To avoid this, we add one more pending origin as a sentinel and | |
| 430 // fire the sentinel callback at the end. | |
| 431 info->pending_jobs = origins.size() + 1; | |
| 432 OriginUsageAccumulator accumulator = | |
| 433 base::Bind(&ClientUsageTracker::AccumulateOriginUsage, AsWeakPtr(), | |
| 434 base::Owned(info), host); | |
| 435 | |
| 436 for (std::set<GURL>::const_iterator itr = origins.begin(); | |
| 437 itr != origins.end(); ++itr) { | |
| 438 DCHECK_EQ(host, net::GetHostOrSpecFromURL(*itr)); | |
| 439 | |
| 440 int64 origin_usage = 0; | |
| 441 if (GetCachedOriginUsage(*itr, &origin_usage)) { | |
| 442 accumulator.Run(*itr, origin_usage); | |
| 443 } else { | |
| 444 client_->GetOriginUsage(*itr, type_, base::Bind( | |
| 445 &DidGetOriginUsage, accumulator, *itr)); | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 // Fire the sentinel as we've now called GetOriginUsage for all clients. | |
| 450 accumulator.Run(GURL(), 0); | |
| 451 } | |
| 452 | |
| 453 void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, | |
| 454 const std::string& host, | |
| 455 const GURL& origin, | |
| 456 int64 usage) { | |
| 457 if (!origin.is_empty()) { | |
| 458 if (usage < 0) | |
| 459 usage = 0; | |
| 460 | |
| 461 if (IsUsageCacheEnabledForOrigin(origin)) { | |
| 462 info->cached_usage += usage; | |
| 463 AddCachedOrigin(origin, usage); | |
| 464 } else { | |
| 465 info->non_cached_usage += usage; | |
| 466 } | |
| 467 } | |
| 468 if (--info->pending_jobs) | |
| 469 return; | |
| 470 | |
| 471 AddCachedHost(host); | |
| 472 host_usage_accumulators_.Run( | |
| 473 host, MakeTuple(info->cached_usage, info->non_cached_usage)); | |
| 474 } | |
| 475 | |
| 476 void ClientUsageTracker::AddCachedOrigin( | |
| 477 const GURL& origin, int64 new_usage) { | |
| 478 if (!IsUsageCacheEnabledForOrigin(origin)) | |
| 479 return; | |
| 480 | |
| 481 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 482 int64* usage = &cached_usage_by_host_[host][origin]; | |
| 483 int64 delta = new_usage - *usage; | |
| 484 *usage = new_usage; | |
| 485 if (delta) { | |
| 486 if (IsStorageUnlimited(origin)) | |
| 487 global_unlimited_usage_ += delta; | |
| 488 else | |
| 489 global_limited_usage_ += delta; | |
| 490 } | |
| 491 DCHECK_GE(*usage, 0); | |
| 492 DCHECK_GE(global_limited_usage_, 0); | |
| 493 } | |
| 494 | |
| 495 void ClientUsageTracker::AddCachedHost(const std::string& host) { | |
| 496 cached_hosts_.insert(host); | |
| 497 } | |
| 498 | |
| 499 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { | |
| 500 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); | |
| 501 if (found == cached_usage_by_host_.end()) | |
| 502 return 0; | |
| 503 | |
| 504 int64 usage = 0; | |
| 505 const UsageMap& map = found->second; | |
| 506 for (UsageMap::const_iterator iter = map.begin(); | |
| 507 iter != map.end(); ++iter) { | |
| 508 usage += iter->second; | |
| 509 } | |
| 510 return usage; | |
| 511 } | |
| 512 | |
| 513 bool ClientUsageTracker::GetCachedOriginUsage( | |
| 514 const GURL& origin, | |
| 515 int64* usage) const { | |
| 516 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 517 HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); | |
| 518 if (found_host == cached_usage_by_host_.end()) | |
| 519 return false; | |
| 520 | |
| 521 UsageMap::const_iterator found = found_host->second.find(origin); | |
| 522 if (found == found_host->second.end()) | |
| 523 return false; | |
| 524 | |
| 525 DCHECK(IsUsageCacheEnabledForOrigin(origin)); | |
| 526 *usage = found->second; | |
| 527 return true; | |
| 528 } | |
| 529 | |
| 530 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( | |
| 531 const GURL& origin) const { | |
| 532 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 533 return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_, | |
| 534 host, origin) && | |
| 535 !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_, | |
| 536 host, origin); | |
| 537 } | |
| 538 | |
| 539 void ClientUsageTracker::OnGranted(const GURL& origin, | |
| 540 int change_flags) { | |
| 541 DCHECK(CalledOnValidThread()); | |
| 542 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { | |
| 543 int64 usage = 0; | |
| 544 if (GetCachedOriginUsage(origin, &usage)) { | |
| 545 global_unlimited_usage_ += usage; | |
| 546 global_limited_usage_ -= usage; | |
| 547 } | |
| 548 | |
| 549 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 550 if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, | |
| 551 host, origin)) | |
| 552 non_cached_unlimited_origins_by_host_[host].insert(origin); | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 void ClientUsageTracker::OnRevoked(const GURL& origin, | |
| 557 int change_flags) { | |
| 558 DCHECK(CalledOnValidThread()); | |
| 559 if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { | |
| 560 int64 usage = 0; | |
| 561 if (GetCachedOriginUsage(origin, &usage)) { | |
| 562 global_unlimited_usage_ -= usage; | |
| 563 global_limited_usage_ += usage; | |
| 564 } | |
| 565 | |
| 566 std::string host = net::GetHostOrSpecFromURL(origin); | |
| 567 if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, | |
| 568 host, origin)) | |
| 569 non_cached_limited_origins_by_host_[host].insert(origin); | |
| 570 } | |
| 571 } | |
| 572 | |
| 573 void ClientUsageTracker::OnCleared() { | |
| 574 DCHECK(CalledOnValidThread()); | |
| 575 global_limited_usage_ += global_unlimited_usage_; | |
| 576 global_unlimited_usage_ = 0; | |
| 577 | |
| 578 for (OriginSetByHost::const_iterator host_itr = | |
| 579 non_cached_unlimited_origins_by_host_.begin(); | |
| 580 host_itr != non_cached_unlimited_origins_by_host_.end(); | |
| 581 ++host_itr) { | |
| 582 for (std::set<GURL>::const_iterator origin_itr = host_itr->second.begin(); | |
| 583 origin_itr != host_itr->second.end(); | |
| 584 ++origin_itr) | |
| 585 non_cached_limited_origins_by_host_[host_itr->first].insert(*origin_itr); | |
| 586 } | |
| 587 non_cached_unlimited_origins_by_host_.clear(); | |
| 588 } | |
| 589 | |
| 590 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { | |
| 591 if (type_ == kStorageTypeSyncable) | |
| 592 return false; | |
| 593 return special_storage_policy_.get() && | |
| 594 special_storage_policy_->IsStorageUnlimited(origin); | |
| 595 } | |
| 596 | |
| 597 } // namespace quota | |
| OLD | NEW |