Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / storage / browser / quota / usage_tracker.cc
blob528725d7f7092ecab3a1d53dee3efd92bc6e5571
1 // Copyright 2013 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.
5 #include "storage/browser/quota/usage_tracker.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/stl_util.h"
11 #include "storage/browser/quota/client_usage_tracker.h"
12 #include "storage/browser/quota/storage_monitor.h"
14 namespace storage {
16 namespace {
18 void DidGetGlobalUsageForLimitedGlobalUsage(const UsageCallback& callback,
19 int64 total_global_usage,
20 int64 global_unlimited_usage) {
21 callback.Run(total_global_usage - global_unlimited_usage);
24 } // namespace
26 UsageTracker::UsageTracker(const QuotaClientList& clients,
27 StorageType type,
28 SpecialStoragePolicy* special_storage_policy,
29 StorageMonitor* storage_monitor)
30 : type_(type),
31 storage_monitor_(storage_monitor),
32 weak_factory_(this) {
33 for (const auto& client : clients) {
34 if (client->DoesSupport(type)) {
35 client_tracker_map_[client->id()] =
36 new ClientUsageTracker(this, client, type, special_storage_policy,
37 storage_monitor_);
42 UsageTracker::~UsageTracker() {
43 STLDeleteValues(&client_tracker_map_);
46 ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) {
47 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id);
48 if (found != client_tracker_map_.end())
49 return found->second;
50 return nullptr;
53 void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) {
54 if (global_usage_callbacks_.HasCallbacks()) {
55 global_usage_callbacks_.Add(base::Bind(
56 &DidGetGlobalUsageForLimitedGlobalUsage, callback));
57 return;
60 if (!global_limited_usage_callbacks_.Add(callback))
61 return;
63 AccumulateInfo* info = new AccumulateInfo;
64 // Calling GetGlobalLimitedUsage(accumulator) may synchronously
65 // return if the usage is cached, which may in turn dispatch
66 // the completion callback before we finish looping over
67 // all clients (because info->pending_clients may reach 0
68 // during the loop).
69 // To avoid this, we add one more pending client as a sentinel
70 // and fire the sentinel callback at the end.
71 info->pending_clients = client_tracker_map_.size() + 1;
72 UsageCallback accumulator = base::Bind(
73 &UsageTracker::AccumulateClientGlobalLimitedUsage,
74 weak_factory_.GetWeakPtr(), base::Owned(info));
76 for (const auto& client_id_and_tracker : client_tracker_map_)
77 client_id_and_tracker.second->GetGlobalLimitedUsage(accumulator);
79 // Fire the sentinel as we've now called GetGlobalUsage for all clients.
80 accumulator.Run(0);
83 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
84 if (!global_usage_callbacks_.Add(callback))
85 return;
87 AccumulateInfo* info = new AccumulateInfo;
88 // Calling GetGlobalUsage(accumulator) may synchronously
89 // return if the usage is cached, which may in turn dispatch
90 // the completion callback before we finish looping over
91 // all clients (because info->pending_clients may reach 0
92 // during the loop).
93 // To avoid this, we add one more pending client as a sentinel
94 // and fire the sentinel callback at the end.
95 info->pending_clients = client_tracker_map_.size() + 1;
96 GlobalUsageCallback accumulator = base::Bind(
97 &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(),
98 base::Owned(info));
100 for (const auto& client_id_and_tracker : client_tracker_map_)
101 client_id_and_tracker.second->GetGlobalUsage(accumulator);
103 // Fire the sentinel as we've now called GetGlobalUsage for all clients.
104 accumulator.Run(0, 0);
107 void UsageTracker::GetHostUsage(const std::string& host,
108 const UsageCallback& callback) {
109 if (!host_usage_callbacks_.Add(host, callback))
110 return;
112 AccumulateInfo* info = new AccumulateInfo;
113 // Calling GetHostUsage(accumulator) may synchronously
114 // return if the usage is cached, which may in turn dispatch
115 // the completion callback before we finish looping over
116 // all clients (because info->pending_clients may reach 0
117 // during the loop).
118 // To avoid this, we add one more pending client as a sentinel
119 // and fire the sentinel callback at the end.
120 info->pending_clients = client_tracker_map_.size() + 1;
121 UsageCallback accumulator = base::Bind(
122 &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(),
123 base::Owned(info), host);
125 for (const auto& client_id_and_tracker : client_tracker_map_)
126 client_id_and_tracker.second->GetHostUsage(host, accumulator);
128 // Fire the sentinel as we've now called GetHostUsage for all clients.
129 accumulator.Run(0);
132 void UsageTracker::UpdateUsageCache(
133 QuotaClient::ID client_id, const GURL& origin, int64 delta) {
134 ClientUsageTracker* client_tracker = GetClientTracker(client_id);
135 DCHECK(client_tracker);
136 client_tracker->UpdateUsageCache(origin, delta);
139 void UsageTracker::GetCachedHostsUsage(
140 std::map<std::string, int64>* host_usage) const {
141 DCHECK(host_usage);
142 host_usage->clear();
143 for (const auto& client_id_and_tracker : client_tracker_map_)
144 client_id_and_tracker.second->GetCachedHostsUsage(host_usage);
147 void UsageTracker::GetCachedOrigins(std::set<GURL>* origins) const {
148 DCHECK(origins);
149 origins->clear();
150 for (const auto& client_id_and_tracker : client_tracker_map_)
151 client_id_and_tracker.second->GetCachedOrigins(origins);
154 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id,
155 const GURL& origin,
156 bool enabled) {
157 ClientUsageTracker* client_tracker = GetClientTracker(client_id);
158 DCHECK(client_tracker);
160 client_tracker->SetUsageCacheEnabled(origin, enabled);
163 void UsageTracker::AccumulateClientGlobalLimitedUsage(AccumulateInfo* info,
164 int64 limited_usage) {
165 info->usage += limited_usage;
166 if (--info->pending_clients)
167 return;
169 // All the clients have returned their usage data. Dispatch the
170 // pending callbacks.
171 global_limited_usage_callbacks_.Run(info->usage);
174 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info,
175 int64 usage,
176 int64 unlimited_usage) {
177 info->usage += usage;
178 info->unlimited_usage += unlimited_usage;
179 if (--info->pending_clients)
180 return;
182 // Defend against confusing inputs from clients.
183 if (info->usage < 0)
184 info->usage = 0;
186 // TODO(michaeln): The unlimited number is not trustworthy, it
187 // can get out of whack when apps are installed or uninstalled.
188 if (info->unlimited_usage > info->usage)
189 info->unlimited_usage = info->usage;
190 else if (info->unlimited_usage < 0)
191 info->unlimited_usage = 0;
193 // All the clients have returned their usage data. Dispatch the
194 // pending callbacks.
195 global_usage_callbacks_.Run(info->usage, info->unlimited_usage);
198 void UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info,
199 const std::string& host,
200 int64 usage) {
201 info->usage += usage;
202 if (--info->pending_clients)
203 return;
205 // Defend against confusing inputs from clients.
206 if (info->usage < 0)
207 info->usage = 0;
209 // All the clients have returned their usage data. Dispatch the
210 // pending callbacks.
211 host_usage_callbacks_.Run(host, info->usage);
214 } // namespace storage