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

Side by Side Diff: webkit/quota/quota_manager.cc

Issue 7056006: QuotaManager::GetUsageAndQuota should not hung when the returned usage is negative (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 9 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/quota_manager.h" 5 #include "webkit/quota/quota_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 #include <set> 9 #include <set>
10 10
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 QuotaManager* manager, 113 QuotaManager* manager,
114 const std::string& host, 114 const std::string& host,
115 StorageType type) 115 StorageType type)
116 : QuotaTask(manager), 116 : QuotaTask(manager),
117 host_(host), 117 host_(host),
118 type_(type), 118 type_(type),
119 quota_(-1), 119 quota_(-1),
120 global_usage_(-1), 120 global_usage_(-1),
121 host_usage_(-1), 121 host_usage_(-1),
122 quota_status_(kQuotaStatusUnknown), 122 quota_status_(kQuotaStatusUnknown),
123 waiting_callbacks_(1),
123 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} 124 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
124 125
125 virtual ~UsageAndQuotaDispatcherTask() { 126 virtual ~UsageAndQuotaDispatcherTask() {
126 STLDeleteContainerPointers(callbacks_.begin(), callbacks_.end()); 127 STLDeleteContainerPointers(callbacks_.begin(), callbacks_.end());
127 } 128 }
128 129
129 virtual bool IsCompleted() const = 0; 130 // Subclasses must implement them.
131 virtual void RunBody() = 0;
132 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) = 0;
130 133
131 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) = 0; 134 virtual void Run() OVERRIDE {
135 RunBody();
136 // We initialize waiting_callbacks to 1 so that we won't run
137 // the completion callback until here even some of the callbacks
138 // are dispatched synchronously.
139 CheckCompleted();
140 }
132 141
133 virtual void Aborted() OVERRIDE { 142 virtual void Aborted() OVERRIDE {
134 for (CallbackList::iterator iter = callbacks_.begin(); 143 for (CallbackList::iterator iter = callbacks_.begin();
135 iter != callbacks_.end(); 144 iter != callbacks_.end();
136 ++iter) { 145 ++iter) {
137 (*iter)->Run(kQuotaErrorAbort, 0, 0); 146 (*iter)->Run(kQuotaErrorAbort, 0, 0);
138 delete *iter; 147 delete *iter;
139 } 148 }
140 callbacks_.clear(); 149 callbacks_.clear();
141 DeleteSoon(); 150 DeleteSoon();
142 } 151 }
143 152
144 virtual void Completed() OVERRIDE { 153 virtual void Completed() OVERRIDE {
145 DeleteSoon(); 154 DeleteSoon();
146 } 155 }
156
147 QuotaManager* manager() const { 157 QuotaManager* manager() const {
148 return static_cast<QuotaManager*>(observer()); 158 return static_cast<QuotaManager*>(observer());
149 } 159 }
150 160
151 std::string host() const { return host_; } 161 std::string host() const { return host_; }
152 StorageType type() const { return type_; } 162 StorageType type() const { return type_; }
153 int64 quota() const { return quota_; } 163 int64 quota() const { return quota_; }
154 int64 global_usage() const { return global_usage_; } 164 int64 global_usage() const { return global_usage_; }
155 int64 host_usage() const { return host_usage_; } 165 int64 host_usage() const { return host_usage_; }
156 QuotaStatusCode status() const { return quota_status_; } 166 QuotaStatusCode quota_status() const { return quota_status_; }
157 167
158 UsageCallback* NewGlobalUsageCallback() { 168 // Subclasses must call following methods to create a new 'waitable'
169 // callback, which decrements waiting_callbacks when it is called.
170 UsageCallback* NewWaitableGlobalUsageCallback() {
171 ++waiting_callbacks_;
159 return callback_factory_.NewCallback( 172 return callback_factory_.NewCallback(
160 &UsageAndQuotaDispatcherTask::DidGetGlobalUsage); 173 &UsageAndQuotaDispatcherTask::DidGetGlobalUsage);
161 } 174 }
162 175 HostUsageCallback* NewWaitableHostUsageCallback() {
163 HostUsageCallback* NewHostUsageCallback() { 176 ++waiting_callbacks_;
164 return callback_factory_.NewCallback( 177 return callback_factory_.NewCallback(
165 &UsageAndQuotaDispatcherTask::DidGetHostUsage); 178 &UsageAndQuotaDispatcherTask::DidGetHostUsage);
166 } 179 }
167 180 QuotaCallback* NewWaitableGlobalQuotaCallback() {
168 QuotaCallback* NewGlobalQuotaCallback() { 181 ++waiting_callbacks_;
169 return callback_factory_.NewCallback( 182 return callback_factory_.NewCallback(
170 &UsageAndQuotaDispatcherTask::DidGetGlobalQuota); 183 &UsageAndQuotaDispatcherTask::DidGetGlobalQuota);
171 } 184 }
172 185 HostQuotaCallback* NewWaitableHostQuotaCallback() {
173 HostQuotaCallback* NewHostQuotaCallback() { 186 ++waiting_callbacks_;
174 return callback_factory_.NewCallback( 187 return callback_factory_.NewCallback(
175 &UsageAndQuotaDispatcherTask::DidGetHostQuota); 188 &UsageAndQuotaDispatcherTask::DidGetHostQuota);
176 } 189 }
177 190
178 private: 191 private:
179 void CheckCompleted() { 192 void CheckCompleted() {
180 if (IsCompleted()) { 193 if (--waiting_callbacks_ <= 0) {
181 // Dispatches callbacks. 194 // Dispatches callbacks.
182 for (CallbackList::iterator iter = callbacks_.begin(); 195 for (CallbackList::iterator iter = callbacks_.begin();
183 iter != callbacks_.end(); 196 iter != callbacks_.end();
184 ++iter) { 197 ++iter) {
185 DispatchCallback(*iter); 198 DispatchCallback(*iter);
186 delete *iter; 199 delete *iter;
187 } 200 }
188 callbacks_.clear(); 201 callbacks_.clear();
189 UsageAndQuotaDispatcherTaskMap& dispatcher_map = 202 UsageAndQuotaDispatcherTaskMap& dispatcher_map =
190 manager()->usage_and_quota_dispatchers_; 203 manager()->usage_and_quota_dispatchers_;
191 DCHECK(dispatcher_map.find(std::make_pair(host_, type_)) != 204 DCHECK(dispatcher_map.find(std::make_pair(host_, type_)) !=
192 dispatcher_map.end()); 205 dispatcher_map.end());
193 dispatcher_map.erase(std::make_pair(host_, type_)); 206 dispatcher_map.erase(std::make_pair(host_, type_));
194 CallCompleted(); 207 CallCompleted();
195 } 208 }
196 } 209 }
197 210
198 const std::string host_; 211 const std::string host_;
199 const StorageType type_; 212 const StorageType type_;
200 int64 quota_; 213 int64 quota_;
201 int64 global_usage_; 214 int64 global_usage_;
202 int64 host_usage_; 215 int64 host_usage_;
203 QuotaStatusCode quota_status_; 216 QuotaStatusCode quota_status_;
204 CallbackList callbacks_; 217 CallbackList callbacks_;
218 int waiting_callbacks_;
205 ScopedCallbackFactory<UsageAndQuotaDispatcherTask> callback_factory_; 219 ScopedCallbackFactory<UsageAndQuotaDispatcherTask> callback_factory_;
206 220
207 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaDispatcherTask); 221 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaDispatcherTask);
208 }; 222 };
209 223
210 class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary 224 class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary
211 : public QuotaManager::UsageAndQuotaDispatcherTask { 225 : public QuotaManager::UsageAndQuotaDispatcherTask {
212 public: 226 public:
213 UsageAndQuotaDispatcherTaskForTemporary( 227 UsageAndQuotaDispatcherTaskForTemporary(
214 QuotaManager* manager, const std::string host) 228 QuotaManager* manager, const std::string host)
215 : UsageAndQuotaDispatcherTask(manager, host, kStorageTypeTemporary) {} 229 : UsageAndQuotaDispatcherTask(manager, host, kStorageTypeTemporary) {}
216 230
217 protected: 231 protected:
218 virtual void Run() OVERRIDE { 232 virtual void RunBody() OVERRIDE {
219 manager()->temporary_usage_tracker_->GetGlobalUsage( 233 manager()->temporary_usage_tracker_->GetGlobalUsage(
220 NewGlobalUsageCallback()); 234 NewWaitableGlobalUsageCallback());
221 manager()->temporary_usage_tracker_->GetHostUsage( 235 manager()->temporary_usage_tracker_->GetHostUsage(
222 host(), NewHostUsageCallback()); 236 host(), NewWaitableHostUsageCallback());
223 manager()->GetTemporaryGlobalQuota(NewGlobalQuotaCallback()); 237 manager()->GetTemporaryGlobalQuota(NewWaitableGlobalQuotaCallback());
224 }
225
226 virtual bool IsCompleted() const OVERRIDE {
227 return (quota() >= 0 && global_usage() >= 0 && host_usage() >= 0);
228 } 238 }
229 239
230 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) OVERRIDE { 240 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) OVERRIDE {
231 // TODO(kinuko): For now it returns pessimistic quota. Change this 241 // TODO(kinuko): For now it returns pessimistic quota. Change this
232 // to return {usage, quota - nonevictable_usage} once eviction is 242 // to return {usage, quota - nonevictable_usage} once eviction is
233 // supported. 243 // supported.
234 int64 other_usage = global_usage() - host_usage(); 244 int64 other_usage = global_usage() - host_usage();
235 callback->Run(status(), host_usage(), quota() - other_usage); 245 callback->Run(quota_status(), host_usage(), quota() - other_usage);
236 } 246 }
237 }; 247 };
238 248
239 class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent 249 class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent
240 : public QuotaManager::UsageAndQuotaDispatcherTask { 250 : public QuotaManager::UsageAndQuotaDispatcherTask {
241 public: 251 public:
242 UsageAndQuotaDispatcherTaskForPersistent( 252 UsageAndQuotaDispatcherTaskForPersistent(
243 QuotaManager* manager, const std::string host) 253 QuotaManager* manager, const std::string host)
244 : UsageAndQuotaDispatcherTask(manager, host, kStorageTypePersistent) {} 254 : UsageAndQuotaDispatcherTask(manager, host, kStorageTypePersistent) {}
245 255
246 protected: 256 protected:
247 virtual void Run() OVERRIDE { 257 virtual void RunBody() OVERRIDE {
248 manager()->persistent_usage_tracker_->GetHostUsage( 258 manager()->persistent_usage_tracker_->GetHostUsage(
249 host(), NewHostUsageCallback()); 259 host(), NewWaitableHostUsageCallback());
250 manager()->GetPersistentHostQuota( 260 manager()->GetPersistentHostQuota(
251 host(), NewHostQuotaCallback()); 261 host(), NewWaitableHostQuotaCallback());
252 }
253
254 virtual bool IsCompleted() const OVERRIDE {
255 return (quota() >= 0 && host_usage() >= 0);
256 } 262 }
257 263
258 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) OVERRIDE { 264 virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) OVERRIDE {
259 callback->Run(status(), host_usage(), quota()); 265 callback->Run(quota_status(), host_usage(), quota());
260 } 266 }
261 }; 267 };
262 268
263 // static 269 // static
264 QuotaManager::UsageAndQuotaDispatcherTask* 270 QuotaManager::UsageAndQuotaDispatcherTask*
265 QuotaManager::UsageAndQuotaDispatcherTask::Create( 271 QuotaManager::UsageAndQuotaDispatcherTask::Create(
266 QuotaManager* manager, const std::string& host, StorageType type) { 272 QuotaManager* manager, const std::string& host, StorageType type) {
267 switch (type) { 273 switch (type) {
268 case kStorageTypeTemporary: 274 case kStorageTypeTemporary:
269 return new UsageAndQuotaDispatcherTaskForTemporary( 275 return new UsageAndQuotaDispatcherTaskForTemporary(
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 1087
1082 QuotaManagerProxy::QuotaManagerProxy( 1088 QuotaManagerProxy::QuotaManagerProxy(
1083 QuotaManager* manager, base::MessageLoopProxy* io_thread) 1089 QuotaManager* manager, base::MessageLoopProxy* io_thread)
1084 : manager_(manager), io_thread_(io_thread) { 1090 : manager_(manager), io_thread_(io_thread) {
1085 } 1091 }
1086 1092
1087 QuotaManagerProxy::~QuotaManagerProxy() { 1093 QuotaManagerProxy::~QuotaManagerProxy() {
1088 } 1094 }
1089 1095
1090 } // namespace quota 1096 } // namespace quota
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698