OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/quota/usage_tracker.h" | 5 #include "webkit/quota/usage_tracker.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "net/base/net_util.h" | 16 #include "net/base/net_util.h" |
17 | 17 |
18 namespace quota { | 18 namespace quota { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 bool SortByHost(const GURL& lhs, const GURL& rhs) { | 22 typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; |
23 return net::GetHostOrSpecFromURL(lhs) > net::GetHostOrSpecFromURL(rhs); | 23 |
| 24 void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, |
| 25 const GURL& origin, |
| 26 int64 usage) { |
| 27 accumulator.Run(origin, usage); |
24 } | 28 } |
25 | 29 |
| 30 void DidGetHostUsage(const UsageCallback& callback, |
| 31 int64 cached_usage, |
| 32 int64 non_cached_usage) { |
| 33 DCHECK_GE(cached_usage, 0); |
| 34 DCHECK_GE(non_cached_usage, 0); |
| 35 callback.Run(cached_usage + non_cached_usage); |
| 36 } |
| 37 |
| 38 void NoopHostUsageCallback(int64 usage) {} |
| 39 |
26 } // namespace | 40 } // namespace |
27 | 41 |
28 // A task class for getting the total amount of data used for a collection of | |
29 // origins. This class is self-destructed. | |
30 class ClientUsageTracker::GatherUsageTaskBase : public QuotaTask { | |
31 public: | |
32 GatherUsageTaskBase( | |
33 UsageTracker* tracker, | |
34 QuotaClient* client) | |
35 : QuotaTask(tracker), | |
36 client_(client), | |
37 tracker_(tracker), | |
38 current_gathered_usage_(0), | |
39 weak_factory_(this) { | |
40 DCHECK(tracker_); | |
41 DCHECK(client_); | |
42 client_tracker_ = base::AsWeakPtr( | |
43 tracker_->GetClientTracker(client_->id())); | |
44 DCHECK(client_tracker_.get()); | |
45 } | |
46 virtual ~GatherUsageTaskBase() {} | |
47 | |
48 // Get total usage for the given |origins|. | |
49 void GetUsageForOrigins(const std::set<GURL>& origins, StorageType type) { | |
50 DCHECK(original_task_runner()->BelongsToCurrentThread()); | |
51 if (!client_tracker()) { | |
52 DeleteSoon(); | |
53 return; | |
54 } | |
55 // We do not get usage for origins for which we have valid usage cache. | |
56 std::vector<GURL> origins_not_in_cache; | |
57 current_gathered_usage_ = client_tracker()->GetCachedOriginsUsage( | |
58 origins, &origins_not_in_cache); | |
59 if (origins_not_in_cache.empty()) { | |
60 CallCompleted(); | |
61 DeleteSoon(); | |
62 return; | |
63 } | |
64 | |
65 // Sort them so we can detect when we've gathered all info for a particular | |
66 // host in DidGetUsage. | |
67 std::sort(origins_not_in_cache.begin(), | |
68 origins_not_in_cache.end(), SortByHost); | |
69 | |
70 // First, fully populate the pending queue because GetOriginUsage may call | |
71 // the completion callback immediately. | |
72 for (std::vector<GURL>::const_iterator iter = origins_not_in_cache.begin(); | |
73 iter != origins_not_in_cache.end(); iter++) | |
74 pending_origins_.push_back(*iter); | |
75 | |
76 for (std::vector<GURL>::const_iterator iter = origins_not_in_cache.begin(); | |
77 iter != origins_not_in_cache.end(); iter++) | |
78 client_->GetOriginUsage( | |
79 *iter, | |
80 tracker_->type(), | |
81 base::Bind(&GatherUsageTaskBase::DidGetUsage, | |
82 weak_factory_.GetWeakPtr())); | |
83 } | |
84 | |
85 protected: | |
86 virtual void DidGetOriginUsage(const GURL& origin, int64 usage) {} | |
87 | |
88 virtual void Aborted() OVERRIDE { | |
89 DeleteSoon(); | |
90 } | |
91 | |
92 UsageTracker* tracker() const { return tracker_; } | |
93 ClientUsageTracker* client_tracker() const { return client_tracker_.get(); } | |
94 | |
95 int64 current_gathered_usage() const { return current_gathered_usage_; } | |
96 | |
97 private: | |
98 void DidGetUsage(int64 usage) { | |
99 if (!client_tracker()) { | |
100 DeleteSoon(); | |
101 return; | |
102 } | |
103 | |
104 DCHECK(original_task_runner()->BelongsToCurrentThread()); | |
105 DCHECK(!pending_origins_.empty()); | |
106 | |
107 // Defend against confusing inputs from QuotaClients. | |
108 DCHECK_GE(usage, 0); | |
109 if (usage < 0) | |
110 usage = 0; | |
111 current_gathered_usage_ += usage; | |
112 | |
113 // This code assumes DidGetUsage callbacks are called in the same | |
114 // order as we dispatched GetOriginUsage calls. | |
115 const GURL& origin = pending_origins_.front(); | |
116 std::string host = net::GetHostOrSpecFromURL(origin); | |
117 client_tracker_->AddCachedOrigin(origin, usage); | |
118 | |
119 DidGetOriginUsage(origin, usage); | |
120 | |
121 pending_origins_.pop_front(); | |
122 if (pending_origins_.empty() || | |
123 host != net::GetHostOrSpecFromURL(pending_origins_.front())) { | |
124 client_tracker_->AddCachedHost(host); | |
125 } | |
126 | |
127 if (pending_origins_.empty()) { | |
128 // We're done. | |
129 CallCompleted(); | |
130 DeleteSoon(); | |
131 } | |
132 } | |
133 | |
134 QuotaClient* client_; | |
135 UsageTracker* tracker_; | |
136 base::WeakPtr<ClientUsageTracker> client_tracker_; | |
137 std::deque<GURL> pending_origins_; | |
138 std::map<GURL, int64> origin_usage_map_; | |
139 int64 current_gathered_usage_; | |
140 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_; | |
141 | |
142 DISALLOW_COPY_AND_ASSIGN(GatherUsageTaskBase); | |
143 }; | |
144 | |
145 // A task class for getting the total amount of data used for a given storage | |
146 // type. This class is self-destructed. | |
147 class ClientUsageTracker::GatherGlobalUsageTask | |
148 : public GatherUsageTaskBase { | |
149 public: | |
150 GatherGlobalUsageTask( | |
151 UsageTracker* tracker, | |
152 QuotaClient* client) | |
153 : GatherUsageTaskBase(tracker, client), | |
154 client_(client), | |
155 non_cached_global_usage_(0), | |
156 weak_factory_(this) { | |
157 DCHECK(tracker); | |
158 DCHECK(client); | |
159 } | |
160 virtual ~GatherGlobalUsageTask() {} | |
161 | |
162 protected: | |
163 virtual void Run() OVERRIDE { | |
164 client_->GetOriginsForType(tracker()->type(), | |
165 base::Bind(&GatherUsageTaskBase::GetUsageForOrigins, | |
166 weak_factory_.GetWeakPtr())); | |
167 } | |
168 | |
169 virtual void DidGetOriginUsage(const GURL& origin, int64 usage) OVERRIDE { | |
170 if (!client_tracker()->IsUsageCacheEnabledForOrigin(origin)) { | |
171 std::string host = net::GetHostOrSpecFromURL(origin); | |
172 non_cached_usage_by_host_[host] += usage; | |
173 non_cached_global_usage_ += usage; | |
174 } | |
175 } | |
176 | |
177 virtual void Completed() OVERRIDE { | |
178 client_tracker()->GatherGlobalUsageComplete(current_gathered_usage(), | |
179 non_cached_global_usage_, | |
180 non_cached_usage_by_host_); | |
181 } | |
182 | |
183 private: | |
184 QuotaClient* client_; | |
185 int64 non_cached_global_usage_; | |
186 std::map<std::string, int64> non_cached_usage_by_host_; | |
187 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_; | |
188 | |
189 DISALLOW_COPY_AND_ASSIGN(GatherGlobalUsageTask); | |
190 }; | |
191 | |
192 // A task class for getting the total amount of data used for a given host. | |
193 // This class is self-destructed. | |
194 class ClientUsageTracker::GatherHostUsageTask | |
195 : public GatherUsageTaskBase { | |
196 public: | |
197 GatherHostUsageTask( | |
198 UsageTracker* tracker, | |
199 QuotaClient* client, | |
200 const std::string& host) | |
201 : GatherUsageTaskBase(tracker, client), | |
202 client_(client), | |
203 host_(host), | |
204 weak_factory_(this) { | |
205 DCHECK(client_); | |
206 } | |
207 virtual ~GatherHostUsageTask() {} | |
208 | |
209 protected: | |
210 virtual void Run() OVERRIDE { | |
211 client_->GetOriginsForHost(tracker()->type(), host_, | |
212 base::Bind(&GatherUsageTaskBase::GetUsageForOrigins, | |
213 weak_factory_.GetWeakPtr())); | |
214 } | |
215 | |
216 virtual void Completed() OVERRIDE { | |
217 client_tracker()->GatherHostUsageComplete(host_, current_gathered_usage()); | |
218 } | |
219 | |
220 private: | |
221 QuotaClient* client_; | |
222 std::string host_; | |
223 base::WeakPtrFactory<GatherUsageTaskBase> weak_factory_; | |
224 | |
225 DISALLOW_COPY_AND_ASSIGN(GatherHostUsageTask); | |
226 }; | |
227 | |
228 // UsageTracker ---------------------------------------------------------- | 42 // UsageTracker ---------------------------------------------------------- |
229 | 43 |
230 UsageTracker::UsageTracker(const QuotaClientList& clients, | 44 UsageTracker::UsageTracker(const QuotaClientList& clients, |
231 StorageType type, | 45 StorageType type, |
232 SpecialStoragePolicy* special_storage_policy) | 46 SpecialStoragePolicy* special_storage_policy) |
233 : type_(type), | 47 : type_(type), |
234 weak_factory_(this) { | 48 weak_factory_(this) { |
235 for (QuotaClientList::const_iterator iter = clients.begin(); | 49 for (QuotaClientList::const_iterator iter = clients.begin(); |
236 iter != clients.end(); | 50 iter != clients.end(); |
237 ++iter) { | 51 ++iter) { |
(...skipping 10 matching lines...) Expand all Loading... |
248 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); | 62 ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); |
249 if (found != client_tracker_map_.end()) | 63 if (found != client_tracker_map_.end()) |
250 return found->second; | 64 return found->second; |
251 return NULL; | 65 return NULL; |
252 } | 66 } |
253 | 67 |
254 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | 68 void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { |
255 if (!global_usage_callbacks_.Add(callback)) | 69 if (!global_usage_callbacks_.Add(callback)) |
256 return; | 70 return; |
257 | 71 |
258 TrackingInfo* info = new TrackingInfo; | 72 AccumulateInfo* info = new AccumulateInfo; |
259 // Calling GetGlobalUsage(accumulator) may synchronously | 73 // Calling GetGlobalUsage(accumulator) may synchronously |
260 // return if the usage is cached, which may in turn dispatch | 74 // return if the usage is cached, which may in turn dispatch |
261 // the completion callback before we finish looping over | 75 // the completion callback before we finish looping over |
262 // all clients (because info->pending_clients may reach 0 | 76 // all clients (because info->pending_clients may reach 0 |
263 // during the loop). | 77 // during the loop). |
264 // To avoid this, we add one more pending client as a sentinel | 78 // To avoid this, we add one more pending client as a sentinel |
265 // and fire the sentinel callback at the end. | 79 // and fire the sentinel callback at the end. |
266 info->pending_clients = client_tracker_map_.size() + 1; | 80 info->pending_clients = client_tracker_map_.size() + 1; |
267 GlobalUsageCallback accumulator = base::Bind( | 81 GlobalUsageCallback accumulator = base::Bind( |
268 &UsageTracker::DidGetClientGlobalUsage, weak_factory_.GetWeakPtr(), | 82 &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(), |
269 base::Owned(info)); | 83 base::Owned(info)); |
270 | 84 |
271 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); | 85 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); |
272 iter != client_tracker_map_.end(); | 86 iter != client_tracker_map_.end(); |
273 ++iter) | 87 ++iter) |
274 iter->second->GetGlobalUsage(accumulator); | 88 iter->second->GetGlobalUsage(accumulator); |
275 | 89 |
276 // Fire the sentinel as we've now called GetGlobalUsage for all clients. | 90 // Fire the sentinel as we've now called GetGlobalUsage for all clients. |
277 accumulator.Run(0, 0); | 91 accumulator.Run(0, 0); |
278 } | 92 } |
279 | 93 |
280 void UsageTracker::GetHostUsage(const std::string& host, | 94 void UsageTracker::GetHostUsage(const std::string& host, |
281 const UsageCallback& callback) { | 95 const UsageCallback& callback) { |
282 if (!host_usage_callbacks_.Add(host, callback)) | 96 if (!host_usage_callbacks_.Add(host, callback)) |
283 return; | 97 return; |
284 | 98 |
285 TrackingInfo* info = new TrackingInfo; | 99 AccumulateInfo* info = new AccumulateInfo; |
286 // Calling GetHostUsage(accumulator) may synchronously | 100 // Calling GetHostUsage(accumulator) may synchronously |
287 // return if the usage is cached, which may in turn dispatch | 101 // return if the usage is cached, which may in turn dispatch |
288 // the completion callback before we finish looping over | 102 // the completion callback before we finish looping over |
289 // all clients (because info->pending_clients may reach 0 | 103 // all clients (because info->pending_clients may reach 0 |
290 // during the loop). | 104 // during the loop). |
291 // To avoid this, we add one more pending client as a sentinel | 105 // To avoid this, we add one more pending client as a sentinel |
292 // and fire the sentinel callback at the end. | 106 // and fire the sentinel callback at the end. |
293 info->pending_clients = client_tracker_map_.size() + 1; | 107 info->pending_clients = client_tracker_map_.size() + 1; |
294 UsageCallback accumulator = base::Bind( | 108 UsageCallback accumulator = base::Bind( |
295 &UsageTracker::DidGetClientHostUsage, weak_factory_.GetWeakPtr(), | 109 &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(), |
296 base::Owned(info), host); | 110 base::Owned(info), host); |
297 | 111 |
298 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); | 112 for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); |
299 iter != client_tracker_map_.end(); | 113 iter != client_tracker_map_.end(); |
300 ++iter) | 114 ++iter) |
301 iter->second->GetHostUsage(host, accumulator); | 115 iter->second->GetHostUsage(host, accumulator); |
302 | 116 |
303 // Fire the sentinel as we've now called GetHostUsage for all clients. | 117 // Fire the sentinel as we've now called GetHostUsage for all clients. |
304 accumulator.Run(0); | 118 accumulator.Run(0); |
305 } | 119 } |
(...skipping 26 matching lines...) Expand all Loading... |
332 | 146 |
333 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, | 147 void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, |
334 const GURL& origin, | 148 const GURL& origin, |
335 bool enabled) { | 149 bool enabled) { |
336 ClientUsageTracker* client_tracker = GetClientTracker(client_id); | 150 ClientUsageTracker* client_tracker = GetClientTracker(client_id); |
337 DCHECK(client_tracker); | 151 DCHECK(client_tracker); |
338 | 152 |
339 client_tracker->SetUsageCacheEnabled(origin, enabled); | 153 client_tracker->SetUsageCacheEnabled(origin, enabled); |
340 } | 154 } |
341 | 155 |
342 void UsageTracker::DidGetClientGlobalUsage(TrackingInfo* info, | 156 void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, |
343 int64 usage, | 157 int64 usage, |
344 int64 unlimited_usage) { | 158 int64 unlimited_usage) { |
345 info->usage += usage; | 159 info->usage += usage; |
346 info->unlimited_usage += unlimited_usage; | 160 info->unlimited_usage += unlimited_usage; |
347 | 161 |
348 if (--info->pending_clients) | 162 if (--info->pending_clients) |
349 return; | 163 return; |
350 | 164 |
351 // Defend against confusing inputs from clients. | 165 // Defend against confusing inputs from clients. |
352 if (info->usage < 0) | 166 if (info->usage < 0) |
353 info->usage = 0; | 167 info->usage = 0; |
354 | 168 |
355 // TODO(michaeln): The unlimited number is not trustworthy, it | 169 // TODO(michaeln): The unlimited number is not trustworthy, it |
356 // can get out of whack when apps are installed or uninstalled. | 170 // can get out of whack when apps are installed or uninstalled. |
357 if (info->unlimited_usage > info->usage) | 171 if (info->unlimited_usage > info->usage) |
358 info->unlimited_usage = info->usage; | 172 info->unlimited_usage = info->usage; |
359 else if (info->unlimited_usage < 0) | 173 else if (info->unlimited_usage < 0) |
360 info->unlimited_usage = 0; | 174 info->unlimited_usage = 0; |
361 | 175 |
362 // All the clients have returned their usage data. Dispatch the | 176 // All the clients have returned their usage data. Dispatch the |
363 // pending callbacks. | 177 // pending callbacks. |
364 global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage)); | 178 global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage)); |
365 } | 179 } |
366 | 180 |
367 void UsageTracker::DidGetClientHostUsage(TrackingInfo* info, | 181 void UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info, |
368 const std::string& host, | 182 const std::string& host, |
369 int64 usage) { | 183 int64 usage) { |
370 info->usage += usage; | 184 info->usage += usage; |
371 if (--info->pending_clients) | 185 if (--info->pending_clients) |
372 return; | 186 return; |
373 | 187 |
374 // Defend against confusing inputs from clients. | 188 // Defend against confusing inputs from clients. |
375 if (info->usage < 0) | 189 if (info->usage < 0) |
376 info->usage = 0; | 190 info->usage = 0; |
377 | 191 |
378 // All the clients have returned their usage data. Dispatch the | 192 // All the clients have returned their usage data. Dispatch the |
379 // pending callbacks. | 193 // pending callbacks. |
380 host_usage_callbacks_.Run(host, MakeTuple(info->usage)); | 194 host_usage_callbacks_.Run(host, MakeTuple(info->usage)); |
381 } | 195 } |
382 | 196 |
383 // ClientUsageTracker ---------------------------------------------------- | 197 // ClientUsageTracker ---------------------------------------------------- |
384 | 198 |
385 ClientUsageTracker::ClientUsageTracker( | 199 ClientUsageTracker::ClientUsageTracker( |
386 UsageTracker* tracker, QuotaClient* client, StorageType type, | 200 UsageTracker* tracker, QuotaClient* client, StorageType type, |
387 SpecialStoragePolicy* special_storage_policy) | 201 SpecialStoragePolicy* special_storage_policy) |
388 : tracker_(tracker), | 202 : tracker_(tracker), |
389 client_(client), | 203 client_(client), |
390 type_(type), | 204 type_(type), |
391 global_usage_(0), | 205 global_usage_(0), |
392 global_unlimited_usage_(0), | 206 global_unlimited_usage_(0), |
393 global_usage_retrieved_(false), | 207 global_usage_retrieved_(false), |
394 global_usage_task_(NULL), | |
395 special_storage_policy_(special_storage_policy) { | 208 special_storage_policy_(special_storage_policy) { |
396 DCHECK(tracker_); | 209 DCHECK(tracker_); |
397 DCHECK(client_); | 210 DCHECK(client_); |
398 if (special_storage_policy_) | 211 if (special_storage_policy_) |
399 special_storage_policy_->AddObserver(this); | 212 special_storage_policy_->AddObserver(this); |
400 } | 213 } |
401 | 214 |
402 ClientUsageTracker::~ClientUsageTracker() { | 215 ClientUsageTracker::~ClientUsageTracker() { |
403 if (special_storage_policy_) | 216 if (special_storage_policy_) |
404 special_storage_policy_->RemoveObserver(this); | 217 special_storage_policy_->RemoveObserver(this); |
405 } | 218 } |
406 | 219 |
407 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { | 220 void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { |
408 if (global_usage_retrieved_ && non_cached_origins_by_host_.empty()) { | 221 if (global_usage_retrieved_ && non_cached_origins_by_host_.empty()) { |
409 callback.Run(global_usage_, GetCachedGlobalUnlimitedUsage()); | 222 callback.Run(global_usage_, global_unlimited_usage_); |
410 return; | 223 return; |
411 } | 224 } |
412 DCHECK(!global_usage_callback_.HasCallbacks()); | 225 |
413 global_usage_callback_.Add(callback); | 226 client_->GetOriginsForType(type_, base::Bind( |
414 global_usage_task_ = new GatherGlobalUsageTask(tracker_, client_); | 227 &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), |
415 global_usage_task_->Start(); | 228 callback)); |
416 } | 229 } |
417 | 230 |
418 void ClientUsageTracker::GetHostUsage( | 231 void ClientUsageTracker::GetHostUsage( |
419 const std::string& host, const UsageCallback& callback) { | 232 const std::string& host, const UsageCallback& callback) { |
420 if (ContainsKey(cached_hosts_, host) && | 233 if (ContainsKey(cached_hosts_, host) && |
421 !ContainsKey(non_cached_origins_by_host_, host)) { | 234 !ContainsKey(non_cached_origins_by_host_, host)) { |
422 // TODO(kinuko): Drop host_usage_map_ cache periodically. | 235 // TODO(kinuko): Drop host_usage_map_ cache periodically. |
423 callback.Run(GetCachedHostUsage(host)); | 236 callback.Run(GetCachedHostUsage(host)); |
424 return; | 237 return; |
425 } | 238 } |
426 if (!host_usage_callbacks_.Add(host, callback) || global_usage_task_) | 239 |
| 240 if (!host_usage_accumulators_.Add(host, base::Bind( |
| 241 &DidGetHostUsage, callback))) |
427 return; | 242 return; |
428 GatherHostUsageTask* task = new GatherHostUsageTask(tracker_, client_, host); | 243 client_->GetOriginsForHost(type_, host, base::Bind( |
429 host_usage_tasks_[host] = task; | 244 &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); |
430 task->Start(); | |
431 } | 245 } |
432 | 246 |
433 void ClientUsageTracker::UpdateUsageCache( | 247 void ClientUsageTracker::UpdateUsageCache( |
434 const GURL& origin, int64 delta) { | 248 const GURL& origin, int64 delta) { |
435 std::string host = net::GetHostOrSpecFromURL(origin); | 249 std::string host = net::GetHostOrSpecFromURL(origin); |
436 if (cached_hosts_.find(host) != cached_hosts_.end()) { | 250 if (cached_hosts_.find(host) != cached_hosts_.end()) { |
437 if (!IsUsageCacheEnabledForOrigin(origin)) | 251 if (!IsUsageCacheEnabledForOrigin(origin)) |
438 return; | 252 return; |
439 | 253 |
440 cached_usage_by_host_[host][origin] += delta; | 254 cached_usage_by_host_[host][origin] += delta; |
441 global_usage_ += delta; | 255 global_usage_ += delta; |
442 if (IsStorageUnlimited(origin)) | 256 if (IsStorageUnlimited(origin)) |
443 global_unlimited_usage_ += delta; | 257 global_unlimited_usage_ += delta; |
444 DCHECK_GE(cached_usage_by_host_[host][origin], 0); | 258 DCHECK_GE(cached_usage_by_host_[host][origin], 0); |
445 DCHECK_GE(global_usage_, 0); | 259 DCHECK_GE(global_usage_, 0); |
446 return; | 260 return; |
447 } | 261 } |
448 | 262 |
449 // We don't know about this host yet, so populate our cache for it. | 263 // We don't know about this host yet, so populate our cache for it. |
450 GetHostUsage(host, | 264 GetHostUsage(host, base::Bind(&NoopHostUsageCallback)); |
451 base::Bind(&ClientUsageTracker::NoopHostUsageCallback, | |
452 base::Unretained(this))); | |
453 } | 265 } |
454 | 266 |
455 void ClientUsageTracker::GetCachedHostsUsage( | 267 void ClientUsageTracker::GetCachedHostsUsage( |
456 std::map<std::string, int64>* host_usage) const { | 268 std::map<std::string, int64>* host_usage) const { |
457 DCHECK(host_usage); | 269 DCHECK(host_usage); |
458 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); | 270 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); |
459 host_iter != cached_usage_by_host_.end(); host_iter++) { | 271 host_iter != cached_usage_by_host_.end(); host_iter++) { |
460 host_usage->operator[](host_iter->first) += | 272 const std::string& host = host_iter->first; |
461 GetCachedHostUsage(host_iter->first); | 273 (*host_usage)[host] += GetCachedHostUsage(host); |
462 } | 274 } |
463 } | 275 } |
464 | 276 |
465 void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { | 277 void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { |
466 DCHECK(origins); | 278 DCHECK(origins); |
467 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); | 279 for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); |
468 host_iter != cached_usage_by_host_.end(); host_iter++) { | 280 host_iter != cached_usage_by_host_.end(); host_iter++) { |
469 const UsageMap& origin_map = host_iter->second; | 281 const UsageMap& origin_map = host_iter->second; |
470 for (UsageMap::const_iterator origin_iter = origin_map.begin(); | 282 for (UsageMap::const_iterator origin_iter = origin_map.begin(); |
471 origin_iter != origin_map.end(); origin_iter++) { | 283 origin_iter != origin_map.end(); origin_iter++) { |
472 origins->insert(origin_iter->first); | 284 origins->insert(origin_iter->first); |
473 } | 285 } |
474 } | 286 } |
475 } | 287 } |
476 | 288 |
477 int64 ClientUsageTracker::GetCachedOriginsUsage( | |
478 const std::set<GURL>& origins, | |
479 std::vector<GURL>* origins_not_in_cache) { | |
480 DCHECK(origins_not_in_cache); | |
481 | |
482 int64 usage = 0; | |
483 for (std::set<GURL>::const_iterator itr = origins.begin(); | |
484 itr != origins.end(); ++itr) { | |
485 int64 origin_usage = 0; | |
486 if (GetCachedOriginUsage(*itr, &origin_usage)) | |
487 usage += origin_usage; | |
488 else | |
489 origins_not_in_cache->push_back(*itr); | |
490 } | |
491 return usage; | |
492 } | |
493 | |
494 void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, | 289 void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, |
495 bool enabled) { | 290 bool enabled) { |
496 std::string host = net::GetHostOrSpecFromURL(origin); | 291 std::string host = net::GetHostOrSpecFromURL(origin); |
497 if (!enabled) { | 292 if (!enabled) { |
498 // Erase |origin| from cache and subtract its usage. | 293 // Erase |origin| from cache and subtract its usage. |
499 HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); | 294 HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); |
500 if (found_host != cached_usage_by_host_.end()) { | 295 if (found_host != cached_usage_by_host_.end()) { |
501 UsageMap& cached_usage_for_host = found_host->second; | 296 UsageMap& cached_usage_for_host = found_host->second; |
502 | 297 |
503 UsageMap::iterator found = cached_usage_for_host.find(origin); | 298 UsageMap::iterator found = cached_usage_for_host.find(origin); |
(...skipping 18 matching lines...) Expand all Loading... |
522 | 317 |
523 found->second.erase(origin); | 318 found->second.erase(origin); |
524 if (found->second.empty()) { | 319 if (found->second.empty()) { |
525 non_cached_origins_by_host_.erase(found); | 320 non_cached_origins_by_host_.erase(found); |
526 cached_hosts_.erase(host); | 321 cached_hosts_.erase(host); |
527 global_usage_retrieved_ = false; | 322 global_usage_retrieved_ = false; |
528 } | 323 } |
529 } | 324 } |
530 } | 325 } |
531 | 326 |
| 327 void ClientUsageTracker::DidGetOriginsForGlobalUsage( |
| 328 const GlobalUsageCallback& callback, |
| 329 const std::set<GURL>& origins, StorageType type) { |
| 330 OriginSetByHost origins_by_host; |
| 331 for (std::set<GURL>::const_iterator itr = origins.begin(); |
| 332 itr != origins.end(); ++itr) |
| 333 origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr); |
| 334 |
| 335 AccumulateInfo* info = new AccumulateInfo; |
| 336 // Getting host usage may synchronously return the result if the usage is |
| 337 // cached, which may in turn dispatch the completion callback before we finish |
| 338 // looping over all hosts (because info->pending_jobs may reach 0 during the |
| 339 // loop). To avoid this, we add one more pending host as a sentinel and |
| 340 // fire the sentinel callback at the end. |
| 341 info->pending_jobs = origins_by_host.size() + 1; |
| 342 HostUsageAccumulator accumulator = |
| 343 base::Bind(&ClientUsageTracker::AccumulateHostUsage, AsWeakPtr(), |
| 344 base::Owned(info), callback); |
| 345 |
| 346 for (OriginSetByHost::iterator itr = origins_by_host.begin(); |
| 347 itr != origins_by_host.end(); ++itr) { |
| 348 if (host_usage_accumulators_.Add(itr->first, accumulator)) |
| 349 GetUsageForOrigins(itr->first, itr->second); |
| 350 } |
| 351 |
| 352 // Fire the sentinel as we've now called GetUsageForOrigins for all clients. |
| 353 accumulator.Run(0, 0); |
| 354 } |
| 355 |
| 356 void ClientUsageTracker::AccumulateHostUsage( |
| 357 AccumulateInfo* info, |
| 358 const GlobalUsageCallback& callback, |
| 359 int64 cached_usage, |
| 360 int64 non_cached_usage) { |
| 361 info->cached_usage += cached_usage; |
| 362 info->non_cached_usage += non_cached_usage; |
| 363 if (--info->pending_jobs) |
| 364 return; |
| 365 |
| 366 int64 total_usage = info->cached_usage + info->non_cached_usage; |
| 367 int64 unlimited_usage = global_unlimited_usage_ + info->non_cached_usage; |
| 368 |
| 369 DCHECK_GE(total_usage, 0); |
| 370 DCHECK_GE(unlimited_usage, 0); |
| 371 if (unlimited_usage > total_usage) |
| 372 unlimited_usage = total_usage; |
| 373 |
| 374 global_usage_retrieved_ = true; |
| 375 callback.Run(total_usage, unlimited_usage); |
| 376 } |
| 377 |
| 378 void ClientUsageTracker::DidGetOriginsForHostUsage( |
| 379 const std::string& host, |
| 380 const std::set<GURL>& origins, |
| 381 StorageType type) { |
| 382 GetUsageForOrigins(host, origins); |
| 383 } |
| 384 |
| 385 void ClientUsageTracker::GetUsageForOrigins( |
| 386 const std::string& host, |
| 387 const std::set<GURL>& origins) { |
| 388 AccumulateInfo* info = new AccumulateInfo; |
| 389 // Getting origin usage may synchronously return the result if the usage is |
| 390 // cached, which may in turn dispatch the completion callback before we finish |
| 391 // looping over all origins (because info->pending_jobs may reach 0 during the |
| 392 // loop). To avoid this, we add one more pending origin as a sentinel and |
| 393 // fire the sentinel callback at the end. |
| 394 info->pending_jobs = origins.size() + 1; |
| 395 OriginUsageAccumulator accumulator = |
| 396 base::Bind(&ClientUsageTracker::AccumulateOriginUsage, AsWeakPtr(), |
| 397 base::Owned(info), host); |
| 398 |
| 399 for (std::set<GURL>::const_iterator itr = origins.begin(); |
| 400 itr != origins.end(); ++itr) { |
| 401 DCHECK_EQ(host, net::GetHostOrSpecFromURL(*itr)); |
| 402 |
| 403 int64 origin_usage = 0; |
| 404 if (GetCachedOriginUsage(*itr, &origin_usage)) { |
| 405 accumulator.Run(*itr, origin_usage); |
| 406 } else { |
| 407 client_->GetOriginUsage(*itr, type_, base::Bind( |
| 408 &DidGetOriginUsage, accumulator, *itr)); |
| 409 } |
| 410 } |
| 411 |
| 412 // Fire the sentinel as we've now called GetOriginUsage for all clients. |
| 413 accumulator.Run(GURL(), 0); |
| 414 } |
| 415 |
| 416 void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, |
| 417 const std::string& host, |
| 418 const GURL& origin, |
| 419 int64 usage) { |
| 420 if (!origin.is_empty()) { |
| 421 if (usage < 0) |
| 422 usage = 0; |
| 423 |
| 424 if (IsUsageCacheEnabledForOrigin(origin)) { |
| 425 info->cached_usage += usage; |
| 426 AddCachedOrigin(origin, usage); |
| 427 } else { |
| 428 info->non_cached_usage += usage; |
| 429 } |
| 430 } |
| 431 if (--info->pending_jobs) |
| 432 return; |
| 433 |
| 434 AddCachedHost(host); |
| 435 host_usage_accumulators_.Run( |
| 436 host, MakeTuple(info->cached_usage, info->non_cached_usage)); |
| 437 } |
| 438 |
532 void ClientUsageTracker::AddCachedOrigin( | 439 void ClientUsageTracker::AddCachedOrigin( |
533 const GURL& origin, int64 usage) { | 440 const GURL& origin, int64 usage) { |
534 if (!IsUsageCacheEnabledForOrigin(origin)) | 441 if (!IsUsageCacheEnabledForOrigin(origin)) |
535 return; | 442 return; |
536 | 443 |
537 std::string host = net::GetHostOrSpecFromURL(origin); | 444 std::string host = net::GetHostOrSpecFromURL(origin); |
538 UsageMap::iterator iter = cached_usage_by_host_[host]. | 445 UsageMap::iterator iter = cached_usage_by_host_[host]. |
539 insert(UsageMap::value_type(origin, 0)).first; | 446 insert(UsageMap::value_type(origin, 0)).first; |
540 int64 old_usage = iter->second; | 447 int64 old_usage = iter->second; |
541 iter->second = usage; | 448 iter->second = usage; |
542 int64 delta = usage - old_usage; | 449 int64 delta = usage - old_usage; |
543 if (delta) { | 450 if (delta) { |
544 global_usage_ += delta; | 451 global_usage_ += delta; |
545 if (IsStorageUnlimited(origin)) | 452 if (IsStorageUnlimited(origin)) |
546 global_unlimited_usage_ += delta; | 453 global_unlimited_usage_ += delta; |
547 } | 454 } |
548 DCHECK_GE(iter->second, 0); | 455 DCHECK_GE(iter->second, 0); |
549 DCHECK_GE(global_usage_, 0); | 456 DCHECK_GE(global_usage_, 0); |
550 } | 457 } |
551 | 458 |
552 void ClientUsageTracker::AddCachedHost(const std::string& host) { | 459 void ClientUsageTracker::AddCachedHost(const std::string& host) { |
553 cached_hosts_.insert(host); | 460 cached_hosts_.insert(host); |
554 } | 461 } |
555 | 462 |
556 void ClientUsageTracker::GatherGlobalUsageComplete( | |
557 int64 global_usage, | |
558 int64 non_cached_global_usage, | |
559 const std::map<std::string, int64>& non_cached_host_usage) { | |
560 DCHECK(global_usage_task_ != NULL); | |
561 global_usage_task_ = NULL; | |
562 // TODO(kinuko): Record when it has retrieved the global usage. | |
563 global_usage_retrieved_ = true; | |
564 | |
565 DCHECK(global_usage_callback_.HasCallbacks()); | |
566 global_usage_callback_.Run( | |
567 MakeTuple(global_usage, | |
568 GetCachedGlobalUnlimitedUsage() + non_cached_global_usage)); | |
569 | |
570 for (HostUsageCallbackMap::iterator iter = host_usage_callbacks_.Begin(); | |
571 iter != host_usage_callbacks_.End(); ++iter) { | |
572 int64 host_usage = GetCachedHostUsage(iter->first); | |
573 std::map<std::string, int64>::const_iterator found = | |
574 non_cached_host_usage.find(iter->first); | |
575 if (found != non_cached_host_usage.end()) | |
576 host_usage += found->second; | |
577 iter->second.Run(MakeTuple(host_usage)); | |
578 } | |
579 host_usage_callbacks_.Clear(); | |
580 } | |
581 | |
582 void ClientUsageTracker::GatherHostUsageComplete(const std::string& host, | |
583 int64 usage) { | |
584 DCHECK(host_usage_tasks_.find(host) != host_usage_tasks_.end()); | |
585 host_usage_tasks_.erase(host); | |
586 host_usage_callbacks_.Run(host, MakeTuple(usage)); | |
587 } | |
588 | |
589 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { | 463 int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { |
590 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); | 464 HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); |
591 if (found == cached_usage_by_host_.end()) | 465 if (found == cached_usage_by_host_.end()) |
592 return 0; | 466 return 0; |
593 | 467 |
594 int64 usage = 0; | 468 int64 usage = 0; |
595 const UsageMap& map = found->second; | 469 const UsageMap& map = found->second; |
596 for (UsageMap::const_iterator iter = map.begin(); | 470 for (UsageMap::const_iterator iter = map.begin(); |
597 iter != map.end(); ++iter) { | 471 iter != map.end(); ++iter) { |
598 usage += iter->second; | 472 usage += iter->second; |
599 } | 473 } |
600 return usage; | 474 return usage; |
601 } | 475 } |
602 | 476 |
603 int64 ClientUsageTracker::GetCachedGlobalUnlimitedUsage() { | |
604 return global_unlimited_usage_; | |
605 } | |
606 | |
607 bool ClientUsageTracker::GetCachedOriginUsage( | 477 bool ClientUsageTracker::GetCachedOriginUsage( |
608 const GURL& origin, | 478 const GURL& origin, |
609 int64* usage) const { | 479 int64* usage) const { |
610 std::string host = net::GetHostOrSpecFromURL(origin); | 480 std::string host = net::GetHostOrSpecFromURL(origin); |
611 HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); | 481 HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); |
612 if (found_host == cached_usage_by_host_.end()) | 482 if (found_host == cached_usage_by_host_.end()) |
613 return false; | 483 return false; |
614 | 484 |
615 UsageMap::const_iterator found = found_host->second.find(origin); | 485 UsageMap::const_iterator found = found_host->second.find(origin); |
616 if (found == found_host->second.end()) | 486 if (found == found_host->second.end()) |
617 return false; | 487 return false; |
618 | 488 |
| 489 DCHECK(IsUsageCacheEnabledForOrigin(origin)); |
619 *usage = found->second; | 490 *usage = found->second; |
620 return true; | 491 return true; |
621 } | 492 } |
622 | 493 |
623 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( | 494 bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( |
624 const GURL& origin) const { | 495 const GURL& origin) const { |
625 std::string host = net::GetHostOrSpecFromURL(origin); | 496 std::string host = net::GetHostOrSpecFromURL(origin); |
626 OriginSetByHost::const_iterator found = | 497 OriginSetByHost::const_iterator found = |
627 non_cached_origins_by_host_.find(host); | 498 non_cached_origins_by_host_.find(host); |
628 return found == non_cached_origins_by_host_.end() || | 499 return found == non_cached_origins_by_host_.end() || |
(...skipping 18 matching lines...) Expand all Loading... |
647 if (GetCachedOriginUsage(origin, &usage)) | 518 if (GetCachedOriginUsage(origin, &usage)) |
648 global_unlimited_usage_ -= usage; | 519 global_unlimited_usage_ -= usage; |
649 } | 520 } |
650 } | 521 } |
651 | 522 |
652 void ClientUsageTracker::OnCleared() { | 523 void ClientUsageTracker::OnCleared() { |
653 DCHECK(CalledOnValidThread()); | 524 DCHECK(CalledOnValidThread()); |
654 global_unlimited_usage_ = 0; | 525 global_unlimited_usage_ = 0; |
655 } | 526 } |
656 | 527 |
657 void ClientUsageTracker::NoopHostUsageCallback(int64 usage) {} | |
658 | |
659 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { | 528 bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { |
660 if (type_ == kStorageTypeSyncable) | 529 if (type_ == kStorageTypeSyncable) |
661 return false; | 530 return false; |
662 return special_storage_policy_.get() && | 531 return special_storage_policy_.get() && |
663 special_storage_policy_->IsStorageUnlimited(origin); | 532 special_storage_policy_->IsStorageUnlimited(origin); |
664 } | 533 } |
665 | 534 |
666 } // namespace quota | 535 } // namespace quota |
OLD | NEW |