14f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov// Copyright 2013 The Chromium Authors. All rights reserved.
28530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany// Use of this source code is governed by a BSD-style license that can be
38530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany// found in the LICENSE file.
48530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
58530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "storage/browser/quota/usage_tracker.h"
68530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
78530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include <algorithm>
88530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include <deque>
98530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include <set>
108530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include <string>
118530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include <vector>
128530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
138530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "base/bind.h"
148530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "base/message_loop/message_loop_proxy.h"
158530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "base/stl_util.h"
165d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include "net/base/net_util.h"
178530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "storage/browser/quota/storage_monitor.h"
188530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#include "storage/browser/quota/storage_observer.h"
190586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov
20c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryanynamespace storage {
21c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany
2267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukovnamespace {
23c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
2414dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovtypedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator;
255e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonovtypedef ClientUsageTracker::OriginSetByHost OriginSetByHost;
265e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov
2711f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukovvoid DidGetOriginUsage(const OriginUsageAccumulator& accumulator,
285cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov                       const GURL& origin,
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       int64 usage) {
308530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  accumulator.Run(origin, usage);
316afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany}
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DidGetHostUsage(const UsageCallback& callback,
3474737d595c4e3638b980bd88b0492247ae4318faAlexey Samsonov                     int64 limited_usage,
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                     int64 unlimited_usage) {
36b1cc4e448f35515e737ac4969aaa04f3fa3af10aKostya Serebryany  DCHECK_GE(limited_usage, 0);
37996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  DCHECK_GE(unlimited_usage, 0);
38996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  callback.Run(limited_usage + unlimited_usage);
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
40348bd12af55f560e0822e753788d8a51fa050c3fEvgeniy Stepanov
41348bd12af55f560e0822e753788d8a51fa050c3fEvgeniy Stepanovbool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host,
42348bd12af55f560e0822e753788d8a51fa050c3fEvgeniy Stepanov                              const std::string& host,
430586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov                              const GURL& origin) {
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  OriginSetByHost::iterator found = origins_by_host->find(host);
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (found == origins_by_host->end())
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return false;
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!found->second.erase(origin))
490586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov    return false;
500586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov
5167f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov  if (found->second.empty())
525cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov    origins_by_host->erase(host);
535e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov  return true;
545e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov}
555e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov
565cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukovbool OriginSetContainsOrigin(const OriginSetByHost& origins,
575e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov                             const std::string& host,
585e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov                             const GURL& origin) {
595e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov  OriginSetByHost::const_iterator itr = origins.find(host);
605cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov  return itr != origins.end() && ContainsKey(itr->second, origin);
6167f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov}
6267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov
6311f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukovvoid DidGetGlobalUsageForLimitedGlobalUsage(const UsageCallback& callback,
6411f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov                                            int64 total_global_usage,
6511f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov                                            int64 global_unlimited_usage) {
6611f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov  callback.Run(total_global_usage - global_unlimited_usage);
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // namespace
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// UsageTracker ----------------------------------------------------------
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesUsageTracker::UsageTracker(const QuotaClientList& clients,
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                           StorageType type,
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                           SpecialStoragePolicy* special_storage_policy,
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                           StorageMonitor* storage_monitor)
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : type_(type),
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      storage_monitor_(storage_monitor),
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      weak_factory_(this) {
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (QuotaClientList::const_iterator iter = clients.begin();
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      iter != clients.end();
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ++iter) {
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if ((*iter)->DoesSupport(type)) {
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      client_tracker_map_[(*iter)->id()] =
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          new ClientUsageTracker(this, *iter, type, special_storage_policy,
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                 storage_monitor_);
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesUsageTracker::~UsageTracker() {
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  STLDeleteValues(&client_tracker_map_);
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) {
962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ClientTrackerMap::iterator found = client_tracker_map_.find(client_id);
972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (found != client_tracker_map_.end())
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return found->second;
992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return NULL;
1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) {
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (global_usage_callbacks_.HasCallbacks()) {
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    global_usage_callbacks_.Add(base::Bind(
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        &DidGetGlobalUsageForLimitedGlobalUsage, callback));
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!global_limited_usage_callbacks_.Add(callback))
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  AccumulateInfo* info = new AccumulateInfo;
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Calling GetGlobalLimitedUsage(accumulator) may synchronously
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // return if the usage is cached, which may in turn dispatch
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // the completion callback before we finish looping over
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // all clients (because info->pending_clients may reach 0
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // during the loop).
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // To avoid this, we add one more pending client as a sentinel
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // and fire the sentinel callback at the end.
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  info->pending_clients = client_tracker_map_.size() + 1;
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  UsageCallback accumulator = base::Bind(
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      &UsageTracker::AccumulateClientGlobalLimitedUsage,
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      weak_factory_.GetWeakPtr(), base::Owned(info));
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (ClientTrackerMap::iterator iter = client_tracker_map_.begin();
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       iter != client_tracker_map_.end();
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       ++iter)
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    iter->second->GetGlobalLimitedUsage(accumulator);
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Fire the sentinel as we've now called GetGlobalUsage for all clients.
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  accumulator.Run(0);
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!global_usage_callbacks_.Add(callback))
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  AccumulateInfo* info = new AccumulateInfo;
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Calling GetGlobalUsage(accumulator) may synchronously
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // return if the usage is cached, which may in turn dispatch
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // the completion callback before we finish looping over
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // all clients (because info->pending_clients may reach 0
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // during the loop).
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // To avoid this, we add one more pending client as a sentinel
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // and fire the sentinel callback at the end.
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  info->pending_clients = client_tracker_map_.size() + 1;
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  GlobalUsageCallback accumulator = base::Bind(
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(),
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      base::Owned(info));
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (ClientTrackerMap::iterator iter = client_tracker_map_.begin();
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       iter != client_tracker_map_.end();
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       ++iter)
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    iter->second->GetGlobalUsage(accumulator);
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
15667505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // Fire the sentinel as we've now called GetGlobalUsage for all clients.
15767505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  accumulator.Run(0, 0);
15867505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov}
15967505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
16067505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonovvoid UsageTracker::GetHostUsage(const std::string& host,
16167505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov                                const UsageCallback& callback) {
16267505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  if (!host_usage_callbacks_.Add(host, callback))
16367505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov    return;
16467505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
16567505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  AccumulateInfo* info = new AccumulateInfo;
166a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  // Calling GetHostUsage(accumulator) may synchronously
16767505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // return if the usage is cached, which may in turn dispatch
16867505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // the completion callback before we finish looping over
16967505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // all clients (because info->pending_clients may reach 0
17067505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // during the loop).
17167505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // To avoid this, we add one more pending client as a sentinel
17267505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // and fire the sentinel callback at the end.
17367505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  info->pending_clients = client_tracker_map_.size() + 1;
17467505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  UsageCallback accumulator = base::Bind(
17567505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov      &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(),
17667505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov      base::Owned(info), host);
17767505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
17867505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  for (ClientTrackerMap::iterator iter = client_tracker_map_.begin();
17967505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov       iter != client_tracker_map_.end();
18067505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov       ++iter)
18167505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov    iter->second->GetHostUsage(host, accumulator);
18267505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
18367505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  // Fire the sentinel as we've now called GetHostUsage for all clients.
18467505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  accumulator.Run(0);
18567505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov}
18667505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
18767505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonovvoid UsageTracker::UpdateUsageCache(
18867505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov    QuotaClient::ID client_id, const GURL& origin, int64 delta) {
18967505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  ClientUsageTracker* client_tracker = GetClientTracker(client_id);
19067505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  DCHECK(client_tracker);
191a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  client_tracker->UpdateUsageCache(origin, delta);
192a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov}
19367505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov
19467505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonovvoid UsageTracker::GetCachedHostsUsage(
19567505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov    std::map<std::string, int64>* host_usage) const {
19667505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  DCHECK(host_usage);
19767505a8a0cf9621243ed21b67dfa041224c78e4bAlexey Samsonov  host_usage->clear();
198be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin();
199be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov       iter != client_tracker_map_.end(); ++iter) {
200be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov    iter->second->GetCachedHostsUsage(host_usage);
201be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  }
202be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov}
203be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
204be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukovvoid UsageTracker::GetCachedOrigins(std::set<GURL>* origins) const {
205be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  DCHECK(origins);
206be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  origins->clear();
207be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin();
208be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov       iter != client_tracker_map_.end(); ++iter) {
209be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov    iter->second->GetCachedOrigins(origins);
210a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  }
211be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov}
212be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
213a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanovvoid UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id,
214be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov                                        const GURL& origin,
215be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov                                        bool enabled) {
216be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  ClientUsageTracker* client_tracker = GetClientTracker(client_id);
217be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  DCHECK(client_tracker);
218be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
219be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  client_tracker->SetUsageCacheEnabled(origin, enabled);
220be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov}
221be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
222be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukovvoid UsageTracker::AccumulateClientGlobalLimitedUsage(AccumulateInfo* info,
223be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov                                                      int64 limited_usage) {
224be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  info->usage += limited_usage;
225be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  if (--info->pending_clients)
226be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov    return;
227be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
228a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  // All the clients have returned their usage data.  Dispatch the
229be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  // pending callbacks.
230be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  global_limited_usage_callbacks_.Run(MakeTuple(info->usage));
231be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov}
232be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
233be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukovvoid UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info,
234be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov                                               int64 usage,
235a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov                                               int64 unlimited_usage) {
236a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  info->usage += usage;
237be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  info->unlimited_usage += unlimited_usage;
238be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  if (--info->pending_clients)
239be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov    return;
240be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov
241be52366ff2500f11133fd6089f349e93bd5f4822Dmitry Vyukov  // Defend against confusing inputs from clients.
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (info->usage < 0)
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->usage = 0;
2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // TODO(michaeln): The unlimited number is not trustworthy, it
2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // can get out of whack when apps are installed or uninstalled.
2472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (info->unlimited_usage > info->usage)
2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->unlimited_usage = info->usage;
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  else if (info->unlimited_usage < 0)
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->unlimited_usage = 0;
2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // All the clients have returned their usage data.  Dispatch the
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // pending callbacks.
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage));
2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info,
2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                             const std::string& host,
2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                             int64 usage) {
2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  info->usage += usage;
2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (--info->pending_clients)
2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Defend against confusing inputs from clients.
2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (info->usage < 0)
2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->usage = 0;
2672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // All the clients have returned their usage data.  Dispatch the
2692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // pending callbacks.
2707cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  host_usage_callbacks_.Run(host, MakeTuple(info->usage));
2717cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov}
2727cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov
2737cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov// ClientUsageTracker ----------------------------------------------------
2745d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
2757cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy StepanovClientUsageTracker::ClientUsageTracker(
2765d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    UsageTracker* tracker, QuotaClient* client, StorageType type,
2777cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    SpecialStoragePolicy* special_storage_policy,
2787cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    StorageMonitor* storage_monitor)
2797cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    : tracker_(tracker),
280a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      client_(client),
281ff5d1fcdd74036fa15d96fafd487397ebf5f202eAlexey Samsonov      type_(type),
282ff5d1fcdd74036fa15d96fafd487397ebf5f202eAlexey Samsonov      storage_monitor_(storage_monitor),
283a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      global_limited_usage_(0),
284ff5d1fcdd74036fa15d96fafd487397ebf5f202eAlexey Samsonov      global_unlimited_usage_(0),
285ff5d1fcdd74036fa15d96fafd487397ebf5f202eAlexey Samsonov      global_usage_retrieved_(false),
2867cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov      special_storage_policy_(special_storage_policy) {
2877cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  DCHECK(tracker_);
2887cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  DCHECK(client_);
2895d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (special_storage_policy_.get())
2905d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    special_storage_policy_->AddObserver(this);
2915d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines}
2927cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov
2937cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy StepanovClientUsageTracker::~ClientUsageTracker() {
2947cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  if (special_storage_policy_.get())
2957cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    special_storage_policy_->RemoveObserver(this);
2967cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov}
2977cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov
2987cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanovvoid ClientUsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) {
2997cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  if (!global_usage_retrieved_) {
3005d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage,
3015d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines                              callback));
3025d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    return;
3037cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  }
3047cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov
3057cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  if (non_cached_limited_origins_by_host_.empty()) {
3067cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    callback.Run(global_limited_usage_);
3077cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov    return;
308a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  }
309a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
310a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  AccumulateInfo* info = new AccumulateInfo;
3117cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov  info->pending_jobs = non_cached_limited_origins_by_host_.size() + 1;
312ff5d1fcdd74036fa15d96fafd487397ebf5f202eAlexey Samsonov  UsageCallback accumulator = base::Bind(
313a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      &ClientUsageTracker::AccumulateLimitedOriginUsage, AsWeakPtr(),
3147cbbb2943527ff852bdace822c8592cfc7e450d7Evgeniy Stepanov      base::Owned(info), callback);
315b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
316b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  for (OriginSetByHost::iterator host_itr =
317b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov           non_cached_limited_origins_by_host_.begin();
318b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov       host_itr != non_cached_limited_origins_by_host_.end(); ++host_itr) {
319b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    for (std::set<GURL>::iterator origin_itr = host_itr->second.begin();
320b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov         origin_itr != host_itr->second.end(); ++origin_itr)
321b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      client_->GetOriginUsage(*origin_itr, type_, accumulator);
322b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  }
323b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
324b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  accumulator.Run(global_limited_usage_);
325b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
326b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
327b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
328b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  if (global_usage_retrieved_ &&
329b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      non_cached_limited_origins_by_host_.empty() &&
330b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      non_cached_unlimited_origins_by_host_.empty()) {
331b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    callback.Run(global_limited_usage_ + global_unlimited_usage_,
332b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov                 global_unlimited_usage_);
333b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    return;
334b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  }
335b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
3368ffd87791a5376d44edfa288cbf469702edbfa22Alexey Samsonov  client_->GetOriginsForType(type_, base::Bind(
3376afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany      &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(),
33844be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov      callback));
339996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov}
34067f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov
3415d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesvoid ClientUsageTracker::GetHostUsage(
3425d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    const std::string& host, const UsageCallback& callback) {
3435d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (ContainsKey(cached_hosts_, host) &&
3446afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany      !ContainsKey(non_cached_limited_origins_by_host_, host) &&
345a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      !ContainsKey(non_cached_unlimited_origins_by_host_, host)) {
346a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    // TODO(kinuko): Drop host_usage_map_ cache periodically.
3478530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    callback.Run(GetCachedHostUsage(host));
3488530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    return;
349a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  }
350c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
35144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  if (!host_usage_accumulators_.Add(
3528ffd87791a5376d44edfa288cbf469702edbfa22Alexey Samsonov          host, base::Bind(&DidGetHostUsage, callback)))
3538530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    return;
354c333dffb81f1d85483d657c254c17f636ab192c5Alexey Samsonov  client_->GetOriginsForHost(type_, host, base::Bind(
3556afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany      &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host));
35644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov}
357996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
35867f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukovvoid ClientUsageTracker::UpdateUsageCache(
3595d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    const GURL& origin, int64 delta) {
3605d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  std::string host = net::GetHostOrSpecFromURL(origin);
3615d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (cached_hosts_.find(host) != cached_hosts_.end()) {
3626afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany    if (!IsUsageCacheEnabledForOrigin(origin))
363a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      return;
364a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
3658530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    cached_usage_by_host_[host][origin] += delta;
3668530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    if (IsStorageUnlimited(origin))
367a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      global_unlimited_usage_ += delta;
368c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    else
36944be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov      global_limited_usage_ += delta;
370c333dffb81f1d85483d657c254c17f636ab192c5Alexey Samsonov    DCHECK_GE(cached_usage_by_host_[host][origin], 0);
3718530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany    DCHECK_GE(global_limited_usage_, 0);
372b1cc4e448f35515e737ac4969aaa04f3fa3af10aKostya Serebryany
3736afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany    // Notify the usage monitor that usage has changed. The storage monitor may
37444be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov    // be NULL during tests.
375996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    if (storage_monitor_) {
37667f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov      StorageObserver::Filter filter(type_, origin);
3775d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines      storage_monitor_->NotifyUsageChange(filter, delta);
3785d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    }
3795d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    return;
3806afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany  }
381a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
382a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  // We don't know about this host yet, so populate our cache for it.
3838530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  GetHostUsage(host, base::Bind(&ClientUsageTracker::DidGetHostUsageAfterUpdate,
3848530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany                                AsWeakPtr(), origin));
385a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov}
386c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
38744be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanovvoid ClientUsageTracker::GetCachedHostsUsage(
3881f5e23e3204961456d4c7a9b45060597d4ff69afAlexander Potapenko    std::map<std::string, int64>* host_usage) const {
3898530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  DCHECK(host_usage);
390b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin();
391b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov       host_iter != cached_usage_by_host_.end(); host_iter++) {
392b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    const std::string& host = host_iter->first;
393b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    (*host_usage)[host] += GetCachedHostUsage(host);
394b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  }
39567f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov}
396b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
397b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const {
398b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  DCHECK(origins);
399b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin();
400b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov       host_iter != cached_usage_by_host_.end(); host_iter++) {
401a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    const UsageMap& origin_map = host_iter->second;
402b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    for (UsageMap::const_iterator origin_iter = origin_map.begin();
403b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov         origin_iter != origin_map.end(); origin_iter++) {
404b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      origins->insert(origin_iter->first);
405b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    }
406b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  }
407b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
408b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
409b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin,
410b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov                                              bool enabled) {
41167f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov  std::string host = net::GetHostOrSpecFromURL(origin);
412b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  if (!enabled) {
413b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    // Erase |origin| from cache and subtract its usage.
414b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    HostUsageMap::iterator found_host = cached_usage_by_host_.find(host);
415b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    if (found_host != cached_usage_by_host_.end()) {
416b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      UsageMap& cached_usage_for_host = found_host->second;
417a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
418b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      UsageMap::iterator found = cached_usage_for_host.find(origin);
419b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      if (found != cached_usage_for_host.end()) {
420b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov        int64 usage = found->second;
421b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov        UpdateUsageCache(origin, -usage);
422b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov        cached_usage_for_host.erase(found);
423b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov        if (cached_usage_for_host.empty()) {
424b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov          cached_usage_by_host_.erase(found_host);
425b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov          cached_hosts_.erase(host);
426b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov        }
42767f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov      }
428b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    }
429b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
430b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    if (IsStorageUnlimited(origin))
431b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      non_cached_unlimited_origins_by_host_[host].insert(origin);
432b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    else
433a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      non_cached_limited_origins_by_host_[host].insert(origin);
434b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  } else {
435b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    // Erase |origin| from |non_cached_origins_| and invalidate the usage cache
436b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    // for the host.
437b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_,
438c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany                                 host, origin) ||
439c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany        EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_,
44044be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                                 host, origin)) {
441996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov      cached_hosts_.erase(host);
44267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov      global_usage_retrieved_ = false;
443a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    }
444c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  }
445b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
446a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
447c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid ClientUsageTracker::AccumulateLimitedOriginUsage(
448c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    AccumulateInfo* info,
449a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    const UsageCallback& callback,
450153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany    int64 usage) {
45144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  info->limited_usage += usage;
452153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  if (--info->pending_jobs)
453153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany    return;
454c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
455f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov  callback.Run(info->limited_usage);
45644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov}
457f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov
45867f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukovvoid ClientUsageTracker::DidGetOriginsForGlobalUsage(
459a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    const GlobalUsageCallback& callback,
460f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov    const std::set<GURL>& origins) {
461a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  OriginSetByHost origins_by_host;
462c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  for (std::set<GURL>::const_iterator itr = origins.begin();
463c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany       itr != origins.end(); ++itr)
464a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr);
465153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany
46644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  AccumulateInfo* info = new AccumulateInfo;
467153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  // Getting host usage may synchronously return the result if the usage is
468153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  // cached, which may in turn dispatch the completion callback before we finish
469c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  // looping over all hosts (because info->pending_jobs may reach 0 during the
470f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov  // loop).  To avoid this, we add one more pending host as a sentinel and
471f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov  // fire the sentinel callback at the end.
47244be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  info->pending_jobs = origins_by_host.size() + 1;
473f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov  HostUsageAccumulator accumulator =
47467f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov      base::Bind(&ClientUsageTracker::AccumulateHostUsage, AsWeakPtr(),
475a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov                 base::Owned(info), callback);
476f0c846b8ef61a5f4bc664c463d643bb8dedc3768Dmitry Vyukov
477a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  for (OriginSetByHost::iterator itr = origins_by_host.begin();
478c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany       itr != origins_by_host.end(); ++itr) {
479c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    if (host_usage_accumulators_.Add(itr->first, accumulator))
480a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov      GetUsageForOrigins(itr->first, itr->second);
481153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  }
48244be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov
483153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  // Fire the sentinel as we've now called GetUsageForOrigins for all clients.
484153ba3f41d8f6ad1641ae76cfdf01445cec9db89Kostya Serebryany  accumulator.Run(0, 0);
485b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
486b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
487b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::AccumulateHostUsage(
488b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    AccumulateInfo* info,
489b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    const GlobalUsageCallback& callback,
49067f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov    int64 limited_usage,
491b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    int64 unlimited_usage) {
492b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  info->limited_usage += limited_usage;
493b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  info->unlimited_usage += unlimited_usage;
494b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  if (--info->pending_jobs)
495b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    return;
496a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
497b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  DCHECK_GE(info->limited_usage, 0);
498b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  DCHECK_GE(info->unlimited_usage, 0);
499b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
500b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  global_usage_retrieved_ = true;
501b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  callback.Run(info->limited_usage + info->unlimited_usage,
502b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov               info->unlimited_usage);
503b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
504b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
505b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::DidGetOriginsForHostUsage(
50667f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov    const std::string& host,
507b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    const std::set<GURL>& origins) {
508b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  GetUsageForOrigins(host, origins);
509b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov}
510b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
511b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanovvoid ClientUsageTracker::GetUsageForOrigins(
512a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    const std::string& host,
513b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    const std::set<GURL>& origins) {
514b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  AccumulateInfo* info = new AccumulateInfo;
515b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  // Getting origin usage may synchronously return the result if the usage is
516b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  // cached, which may in turn dispatch the completion callback before we finish
517b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  // looping over all origins (because info->pending_jobs may reach 0 during the
518b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  // loop).  To avoid this, we add one more pending origin as a sentinel and
519b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  // fire the sentinel callback at the end.
520b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  info->pending_jobs = origins.size() + 1;
521b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  OriginUsageAccumulator accumulator =
52267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov      base::Bind(&ClientUsageTracker::AccumulateOriginUsage, AsWeakPtr(),
523b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov                 base::Owned(info), host);
524b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov
525b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov  for (std::set<GURL>::const_iterator itr = origins.begin();
526b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov       itr != origins.end(); ++itr) {
527b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    DCHECK_EQ(host, net::GetHostOrSpecFromURL(*itr));
528a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
529b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    int64 origin_usage = 0;
530b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    if (GetCachedOriginUsage(*itr, &origin_usage)) {
531b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov      accumulator.Run(*itr, origin_usage);
532b916e6a9b3efa4907b70a2dcd418c76b044171e7Evgeniy Stepanov    } else {
533c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany      client_->GetOriginUsage(*itr, type_, base::Bind(
534a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov          &DidGetOriginUsage, accumulator, *itr));
535a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    }
536a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  }
53744be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov
538996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  // Fire the sentinel as we've now called GetOriginUsage for all clients.
539c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  accumulator.Run(GURL(), 0);
540c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany}
541c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
542c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info,
54344be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                                               const std::string& host,
544c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany                                               const GURL& origin,
545996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                                               int64 usage) {
546c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  if (!origin.is_empty()) {
547c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    if (usage < 0)
548c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany      usage = 0;
549a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
550c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    if (IsStorageUnlimited(origin))
55144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov      info->unlimited_usage += usage;
552a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    else
553fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov      info->limited_usage += usage;
554fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov    if (IsUsageCacheEnabledForOrigin(origin))
555fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov      AddCachedOrigin(origin, usage);
556fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov  }
557fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov  if (--info->pending_jobs)
5585d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    return;
5595d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
56015832c2afc4f04fa558160441d1b01fb3f0ec08bAlexander Potapenko  AddCachedHost(host);
561fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov  host_usage_accumulators_.Run(
5625d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines      host, MakeTuple(info->limited_usage, info->unlimited_usage));
563fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov}
564fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov
565fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanovvoid ClientUsageTracker::DidGetHostUsageAfterUpdate(
566a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    const GURL& origin, int64 usage) {
567fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov  if (!storage_monitor_)
568fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov    return;
569a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
570fef660506e9e5703fedfee01d614abd4b741c738Evgeniy Stepanov  StorageObserver::Filter filter(type_, origin);
5719358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  storage_monitor_->NotifyUsageChange(filter, 0);
572cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov}
573cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov
5740586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukovvoid ClientUsageTracker::AddCachedOrigin(
5750586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov    const GURL& origin, int64 new_usage) {
5760586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov  DCHECK(IsUsageCacheEnabledForOrigin(origin));
5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5780586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov  std::string host = net::GetHostOrSpecFromURL(origin);
5790586dcc3e531d43dca6b5d226bac2d38b5ad64feDmitry Vyukov  int64* usage = &cached_usage_by_host_[host][origin];
580cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  int64 delta = new_usage - *usage;
581cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  *usage = new_usage;
5829358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  if (delta) {
5839358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    if (IsStorageUnlimited(origin))
584cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov      global_unlimited_usage_ += delta;
5859358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    else
5869358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      global_limited_usage_ += delta;
587cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  }
5889358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  DCHECK_GE(*usage, 0);
5899358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  DCHECK_GE(global_limited_usage_, 0);
5909358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov}
591cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov
5929358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovvoid ClientUsageTracker::AddCachedHost(const std::string& host) {
5939358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  cached_hosts_.insert(host);
594cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov}
5959358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
5969358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovint64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const {
597cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  HostUsageMap::const_iterator found = cached_usage_by_host_.find(host);
5989358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  if (found == cached_usage_by_host_.end())
5999358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    return 0;
6009358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
601cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  int64 usage = 0;
6029358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  const UsageMap& map = found->second;
6039358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  for (UsageMap::const_iterator iter = map.begin();
604cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov       iter != map.end(); ++iter) {
6059358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    usage += iter->second;
6069358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  }
607cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  return usage;
6089358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov}
6099358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6109358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovbool ClientUsageTracker::GetCachedOriginUsage(
611cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov    const GURL& origin,
6129358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    int64* usage) const {
6139358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  std::string host = net::GetHostOrSpecFromURL(origin);
614cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host);
6159358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  if (found_host == cached_usage_by_host_.end())
6169358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    return false;
617cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov
6189358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  UsageMap::const_iterator found = found_host->second.find(origin);
6199358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  if (found == found_host->second.end())
6209358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    return false;
6219358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6229358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  DCHECK(IsUsageCacheEnabledForOrigin(origin));
6239358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  *usage = found->second;
6245d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  return true;
6255d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines}
6265d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
6279358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovbool ClientUsageTracker::IsUsageCacheEnabledForOrigin(
6289358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    const GURL& origin) const {
6299358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  std::string host = net::GetHostOrSpecFromURL(origin);
6309358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_,
6319358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov                                  host, origin) &&
6329358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_,
6339358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov                               host, origin);
6349358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov}
6359358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6369358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovvoid ClientUsageTracker::OnGranted(const GURL& origin,
6375d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines                                   int change_flags) {
6385d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  DCHECK(CalledOnValidThread());
6395d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) {
6409358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    int64 usage = 0;
6419358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    if (GetCachedOriginUsage(origin, &usage)) {
6429358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      global_unlimited_usage_ += usage;
6439358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      global_limited_usage_ -= usage;
6449358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    }
6459358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6469358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    std::string host = net::GetHostOrSpecFromURL(origin);
647cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov    if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_,
6489358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov                                 host, origin))
6499358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      non_cached_unlimited_origins_by_host_[host].insert(origin);
6505d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  }
6515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines}
6525d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
6539358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovvoid ClientUsageTracker::OnRevoked(const GURL& origin,
6549358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov                                   int change_flags) {
655cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov  DCHECK(CalledOnValidThread());
6569358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) {
6579358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    int64 usage = 0;
6589358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    if (GetCachedOriginUsage(origin, &usage)) {
6599358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      global_unlimited_usage_ -= usage;
660cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov      global_limited_usage_ += usage;
6619358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov    }
6629358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6635d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    std::string host = net::GetHostOrSpecFromURL(origin);
6645d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_,
6655d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines                                 host, origin))
6669358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov      non_cached_limited_origins_by_host_[host].insert(origin);
6679358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  }
668cf39032f101dfb3b97b1dfc7b6d03f5d89dff266Evgeniy Stepanov}
6699358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov
6709358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanovvoid ClientUsageTracker::OnCleared() {
6719358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  DCHECK(CalledOnValidThread());
6729358c58d0aaf1b20f17362af354d4c3c1309276aEvgeniy Stepanov  global_limited_usage_ += global_unlimited_usage_;
6732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  global_unlimited_usage_ = 0;
6742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
6752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (OriginSetByHost::const_iterator host_itr =
6762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           non_cached_unlimited_origins_by_host_.begin();
6772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       host_itr != non_cached_unlimited_origins_by_host_.end();
6782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       ++host_itr) {
6792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    for (std::set<GURL>::const_iterator origin_itr = host_itr->second.begin();
6802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines         origin_itr != host_itr->second.end();
6812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines         ++origin_itr)
6822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      non_cached_limited_origins_by_host_[host_itr->first].insert(*origin_itr);
6832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
6842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  non_cached_unlimited_origins_by_host_.clear();
6852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
6862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
687a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanovbool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const {
688a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  if (type_ == kStorageTypeSyncable)
689a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov    return false;
690a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  return special_storage_policy_.get() &&
691a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov         special_storage_policy_->IsStorageUnlimited(origin);
692a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov}
693a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
694a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov}  // namespace storage
6952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines