Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: webkit/browser/quota/storage_monitor.cc

Issue 218793002: Provide monitoring of usage for a storage type and origin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/browser/quota/storage_monitor.h"
6
7 #include <algorithm>
8
9 #include "base/stl_util.h"
10 #include "net/base/net_util.h"
11 #include "webkit/browser/quota/quota_manager.h"
12 #include "webkit/common/quota/quota_status_code.h"
13
14 namespace quota {
15
16 namespace {
17
18 // The minimum rate between event notifications.
19 const int kMinimumRateMSec = 50;
20
21 } // namespace
22
23 // StorageObserverList:
24
25 StorageObserverList::ObserverState::ObserverState()
26 : requires_update(false) {
27 }
28
29 StorageObserverList::StorageObserverList() {}
30
31 StorageObserverList::~StorageObserverList() {}
32
33 void StorageObserverList::AddObserver(
34 StorageObserver* observer, const StorageObserver::MonitorParams& params) {
35 ObserverState& observer_state = observers_[observer];
36 observer_state.origin = params.filter.origin;
37 observer_state.rate =
38 params.rate > 0 ? base::TimeDelta::FromSeconds(params.rate)
39 : base::TimeDelta::FromMilliseconds(kMinimumRateMSec);
40 }
41
42 void StorageObserverList::RemoveObserver(StorageObserver* observer) {
43 StorageObserverStateMap::iterator it = observers_.find(observer);
tzik 2014/03/31 06:54:16 just observers_.erase(observer); works.
44 if (it != observers_.end())
45 observers_.erase(it);
46 }
47
48 int StorageObserverList::ObserverCount() const {
49 return observers_.size();
50 }
51
52 void StorageObserverList::OnStorageChange(const StorageObserver::Event& event) {
53 for (StorageObserverStateMap::iterator it = observers_.begin();
54 it != observers_.end(); ++it) {
55 it->second.requires_update = true;
56 }
57
58 MaybeDispatchEvent(event);
59 }
60
61 const StorageObserver::Event* StorageObserverList::GetPendingEvent() const {
62 return notification_timer_.IsRunning() ? &pending_event_
63 : NULL;
64 }
65
66 int StorageObserverList::GetRequiredUpdatesCount() const {
67 int count = 0;
68 for (StorageObserverStateMap::const_iterator it = observers_.begin();
69 it != observers_.end(); ++it) {
70 if (it->second.requires_update)
71 ++count;
72 }
73
74 return count;
75 }
76
77 void StorageObserverList::MaybeDispatchEvent(
78 const StorageObserver::Event& event) {
79 notification_timer_.Stop();
80 base::TimeDelta min_delay = base::TimeDelta::Max();
81 bool all_observers_notified = true;
82
83 for (StorageObserverStateMap::iterator it = observers_.begin();
84 it != observers_.end(); ++it) {
85 if (!it->second.requires_update)
86 continue;
87
88 base::Time current_time = base::Time::Now();
89 base::TimeDelta delta = current_time - it->second.last_notification_time;
90 if (delta >= it->second.rate) {
91 it->second.requires_update = false;
92 it->second.last_notification_time = current_time;
93
94 if (it->second.origin == event.filter.origin) {
95 it->first->OnStorageEvent(event);
96 } else {
97 // When the quota and usage of an origin is requested, QuotaManager
98 // returns the quota and usage of the host. Multiple origins can map to
99 // to the same host, so ensure the |origin| field in the dispatched
100 // event matches the |origin| specified by the observer when it was
101 // registered.
102 StorageObserver::Event dispatch_event(event);
103 dispatch_event.filter.origin = it->second.origin;
104 it->first->OnStorageEvent(dispatch_event);
105 }
106 } else {
107 all_observers_notified = false;
108 base::TimeDelta delay = it->second.rate - delta;
109 if (delay < min_delay)
110 min_delay = delay;
111 }
112 }
113
114 // We need to respect the notification rate specified by observers. So if it
115 // is too soon to dispatch an event to an observer, save the event and
116 // dispatch it after a delay. If we simply drop the event, another one may
117 // not arrive anytime soon and the observer will miss the most recent event.
118 if (!all_observers_notified) {
119 pending_event_ = event;
120 notification_timer_.Start(
121 FROM_HERE,
122 min_delay,
123 this,
124 &StorageObserverList::DispatchPendingEvent);
125 }
126 }
127
128 void StorageObserverList::ScheduleUpdateForObserver(StorageObserver* observer) {
129 DCHECK(observers_.find(observer) != observers_.end());
tzik 2014/03/31 07:45:48 I think DCHECK(ContainsKey(observers_, observer));
130 observers_[observer].requires_update = true;
131 }
132
133 void StorageObserverList::DispatchPendingEvent() {
134 MaybeDispatchEvent(pending_event_);
135 }
136
137
138 // HostStorageObservers:
139
140 HostStorageObservers::HostStorageObservers(QuotaManager* quota_manager)
141 : quota_manager_(quota_manager),
142 weak_factory_(this),
143 initialized_(false),
144 initializing_(false),
145 event_occurred_before_init_(false),
146 cached_usage_(0),
147 cached_quota_(0) {
148 }
149
150 HostStorageObservers::~HostStorageObservers() {}
151
152 void HostStorageObservers::AddObserver(
153 StorageObserver* observer,
154 const StorageObserver::MonitorParams& params) {
155 StorageObserverList::AddObserver(observer, params);
156
157 if (!params.dispatch_initial_state)
158 return;
159
160 if (initialized_) {
161 StorageObserver::Event event(params.filter,
162 std::max<int64>(cached_usage_, 0),
163 std::max<int64>(cached_quota_, 0));
164 observer->OnStorageEvent(event);
165 return;
166 }
167
168 // Ensure the observer receives the initial storage state once initialization
169 // is complete.
170 ScheduleUpdateForObserver(observer);
171 StartInitialization(params.filter);
172 }
173
174 void HostStorageObservers::NotifyUsageChange(
175 const StorageObserver::Filter& filter, int64 delta) {
176 if (initialized_) {
177 cached_usage_ += delta;
178 DispatchEvent(filter, true);
179 return;
180 }
181
182 // If a storage change occurs before initialization, ensure all observers will
183 // receive an event once initialization is complete.
184 event_occurred_before_init_ = true;
185 StartInitialization(filter);
186 }
187
188 void HostStorageObservers::StartInitialization(
189 const StorageObserver::Filter& filter) {
190 if (initialized_ || initializing_)
191 return;
192
193 initializing_ = true;
194 quota_manager_->GetUsageAndQuotaForWebApps(
195 filter.origin,
196 filter.storage_type,
197 base::Bind(&HostStorageObservers::GotHostUsageAndQuota,
198 weak_factory_.GetWeakPtr(),
199 filter));
200 }
201
202 void HostStorageObservers::GotHostUsageAndQuota(
203 const StorageObserver::Filter& filter,
204 QuotaStatusCode status,
205 int64 usage,
206 int64 quota) {
207 initializing_ = false;
208 if (status != kQuotaStatusOk)
209 return;
210
211 initialized_ = true;
212 cached_quota_ = quota;
213 cached_usage_ = usage;
214 DispatchEvent(filter, event_occurred_before_init_);
215 }
216
217 void HostStorageObservers::DispatchEvent(
218 const StorageObserver::Filter& filter, bool is_update) {
219 StorageObserver::Event event(filter,
220 std::max<int64>(cached_usage_, 0),
221 std::max<int64>(cached_quota_, 0));
222 if (is_update)
223 OnStorageChange(event);
224 else
225 MaybeDispatchEvent(event);
226 }
227
228
229 // StorageTypeObservers:
230
231 StorageTypeObservers::StorageTypeObservers(QuotaManager* quota_manager)
232 : quota_manager_(quota_manager) {
233 }
234
235 StorageTypeObservers::~StorageTypeObservers() {
236 STLDeleteValues(&host_observers_map_);
237 }
238
239 void StorageTypeObservers::AddObserver(
240 StorageObserver* observer, const StorageObserver::MonitorParams& params) {
241 std::string host = net::GetHostOrSpecFromURL(params.filter.origin);
242 if (host.empty())
243 return;
244
245 HostStorageObservers* host_observers = NULL;
246 HostObserversMap::iterator it = host_observers_map_.find(host);
247 if (it == host_observers_map_.end()) {
248 host_observers = new HostStorageObservers(quota_manager_);
249 host_observers_map_[host] = host_observers;
250 } else {
251 host_observers = it->second;
252 }
253
254 host_observers->AddObserver(observer, params);
255 }
256
257 void StorageTypeObservers::RemoveObserver(StorageObserver* observer) {
258 for (HostObserversMap::iterator it = host_observers_map_.begin();
259 it != host_observers_map_.end(); ) {
260 it->second->RemoveObserver(observer);
261 if (it->second->ObserverCount() == 0) {
262 delete it->second;
263 host_observers_map_.erase(it++);
264 } else {
265 ++it;
266 }
267 }
268 }
269
270 void StorageTypeObservers::RemoveObserverForFilter(
271 StorageObserver* observer, const StorageObserver::Filter& filter) {
272 std::string host = net::GetHostOrSpecFromURL(filter.origin);
273 HostObserversMap::iterator it = host_observers_map_.find(host);
274 if (it == host_observers_map_.end())
275 return;
276
277 it->second->RemoveObserver(observer);
278 if (it->second->ObserverCount() == 0) {
279 delete it->second;
280 host_observers_map_.erase(it);
281 }
282 }
283
284 const HostStorageObservers* StorageTypeObservers::GetHostObservers(
285 const std::string& host) const {
286 HostObserversMap::const_iterator it = host_observers_map_.find(host);
287 if (it != host_observers_map_.end())
288 return it->second;
289
290 return NULL;
291 }
292
293 void StorageTypeObservers::NotifyUsageChange(
294 const StorageObserver::Filter& filter, int64 delta) {
295 std::string host = net::GetHostOrSpecFromURL(filter.origin);
296 HostObserversMap::iterator it = host_observers_map_.find(host);
297 if (it == host_observers_map_.end())
298 return;
299
300 it->second->NotifyUsageChange(filter, delta);
301 }
302
303
304 // StorageMonitor:
305
306 StorageMonitor::StorageMonitor(QuotaManager* quota_manager)
307 : quota_manager_(quota_manager) {
308 }
309
310 StorageMonitor::~StorageMonitor() {
311 STLDeleteValues(&storage_type_observers_map_);
312 }
313
314 void StorageMonitor::AddObserver(
315 StorageObserver* observer, const StorageObserver::MonitorParams& params) {
316 DCHECK(observer);
317
318 // Check preconditions.
319 if (params.filter.storage_type == kStorageTypeUnknown ||
320 params.filter.storage_type == kStorageTypeQuotaNotManaged ||
321 params.filter.origin.is_empty()) {
322 NOTREACHED();
323 return;
324 }
325
326 StorageTypeObservers* type_observers = NULL;
327 StorageTypeObserversMap::iterator it =
328 storage_type_observers_map_.find(params.filter.storage_type);
329 if (it == storage_type_observers_map_.end()) {
330 type_observers = new StorageTypeObservers(quota_manager_);
331 storage_type_observers_map_[params.filter.storage_type] = type_observers;
332 } else {
333 type_observers = it->second;
334 }
335
336 type_observers->AddObserver(observer, params);
337 }
338
339 void StorageMonitor::RemoveObserver(StorageObserver* observer) {
340 for (StorageTypeObserversMap::iterator it =
341 storage_type_observers_map_.begin();
342 it != storage_type_observers_map_.end(); ++it) {
343 it->second->RemoveObserver(observer);
344 }
345 }
346
347 void StorageMonitor::RemoveObserverForFilter(
348 StorageObserver* observer, const StorageObserver::Filter& filter) {
349 StorageTypeObserversMap::iterator it =
350 storage_type_observers_map_.find(filter.storage_type);
351 if (it == storage_type_observers_map_.end())
352 return;
353
354 it->second->RemoveObserverForFilter(observer, filter);
355 }
356
357 const StorageTypeObservers* StorageMonitor::GetStorageTypeObservers(
358 StorageType storage_type) const {
359 StorageTypeObserversMap::const_iterator it =
360 storage_type_observers_map_.find(storage_type);
361 if (it != storage_type_observers_map_.end())
362 return it->second;
363
364 return NULL;
365 }
366
367 void StorageMonitor::NotifyUsageChange(
368 const StorageObserver::Filter& filter, int64 delta) {
369 // Check preconditions.
370 if (filter.storage_type == kStorageTypeUnknown ||
371 filter.storage_type == kStorageTypeQuotaNotManaged ||
372 filter.origin.is_empty()) {
373 NOTREACHED();
374 return;
375 }
376
377 StorageTypeObserversMap::iterator it =
378 storage_type_observers_map_.find(filter.storage_type);
379 if (it == storage_type_observers_map_.end())
380 return;
381
382 it->second->NotifyUsageChange(filter, delta);
383 }
384
385 } // namespace quota
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698