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