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

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

Powered by Google App Engine
This is Rietveld 408576698