OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "webkit/appcache/appcache_quota_client.h" |
| 6 |
| 7 #include <algorithm> |
| 8 #include <map> |
| 9 |
| 10 #include "webkit/appcache/appcache_service.h" |
| 11 |
| 12 using quota::QuotaClient; |
| 13 |
| 14 namespace { |
| 15 |
| 16 quota::QuotaStatusCode NetErrorCodeToQuotaStatus(int code) { |
| 17 if (code == net::OK) |
| 18 return quota::kQuotaStatusOk; |
| 19 else if (code == net::ERR_ABORTED) |
| 20 return quota::kQuotaErrorAbort; |
| 21 else |
| 22 return quota::kQuotaStatusUnknown; |
| 23 } |
| 24 |
| 25 template <class RequestType> |
| 26 void DeleteCallbackHelper(const RequestType& request) { |
| 27 delete request.callback; |
| 28 } |
| 29 |
| 30 } |
| 31 |
| 32 namespace appcache { |
| 33 |
| 34 AppCacheQuotaClient::AppCacheQuotaClient(AppCacheService* service) |
| 35 : ALLOW_THIS_IN_INITIALIZER_LIST(service_delete_callback_( |
| 36 new net::CancelableCompletionCallback<AppCacheQuotaClient>( |
| 37 this, &AppCacheQuotaClient::DidDeleteAppCachesForOrigin))), |
| 38 service_(service), appcache_is_ready_(false), |
| 39 quota_manager_is_destroyed_(false) { |
| 40 } |
| 41 |
| 42 AppCacheQuotaClient::~AppCacheQuotaClient() { |
| 43 DCHECK(pending_usage_requests_.empty()); |
| 44 DCHECK(pending_origins_requests_.empty()); |
| 45 DCHECK(pending_delete_requests_.empty()); |
| 46 DCHECK(!current_delete_request_callback_.get()); |
| 47 } |
| 48 |
| 49 QuotaClient::ID AppCacheQuotaClient::id() const { |
| 50 return kAppcache; |
| 51 } |
| 52 |
| 53 void AppCacheQuotaClient::OnQuotaManagerDestroyed() { |
| 54 DeletePendingRequests(); |
| 55 if (current_delete_request_callback_.get()) { |
| 56 current_delete_request_callback_.reset(); |
| 57 service_delete_callback_.release()->Cancel(); |
| 58 } else { |
| 59 service_delete_callback_ = NULL; |
| 60 } |
| 61 quota_manager_is_destroyed_ = true; |
| 62 if (!service_) |
| 63 delete this; |
| 64 } |
| 65 |
| 66 void AppCacheQuotaClient::GetOriginUsage( |
| 67 const GURL& origin, |
| 68 quota::StorageType type, |
| 69 GetUsageCallback* callback_ptr) { |
| 70 DCHECK(callback_ptr); |
| 71 DCHECK(!quota_manager_is_destroyed_); |
| 72 |
| 73 scoped_ptr<GetUsageCallback> callback(callback_ptr); |
| 74 if (!service_) { |
| 75 callback->Run(0); |
| 76 return; |
| 77 } |
| 78 |
| 79 if (!appcache_is_ready_) { |
| 80 pending_usage_requests_.push_back(UsageRequest()); |
| 81 pending_usage_requests_.back().origin = origin; |
| 82 pending_usage_requests_.back().type = type; |
| 83 pending_usage_requests_.back().callback = callback.release(); |
| 84 return; |
| 85 } |
| 86 |
| 87 if (type == quota::kStorageTypePersistent) { |
| 88 callback->Run(0); |
| 89 return; |
| 90 } |
| 91 |
| 92 const AppCacheStorage::UsageMap* map = GetUsageMap(); |
| 93 AppCacheStorage::UsageMap::const_iterator found = map->find(origin); |
| 94 if (found == map->end()) { |
| 95 callback->Run(0); |
| 96 return; |
| 97 } |
| 98 callback->Run(found->second); |
| 99 } |
| 100 |
| 101 void AppCacheQuotaClient::GetOriginsForType( |
| 102 quota::StorageType type, |
| 103 GetOriginsCallback* callback_ptr) { |
| 104 GetOriginsHelper(type, std::string(), callback_ptr); |
| 105 } |
| 106 |
| 107 void AppCacheQuotaClient::GetOriginsForHost( |
| 108 quota::StorageType type, |
| 109 const std::string& host, |
| 110 GetOriginsCallback* callback_ptr) { |
| 111 DCHECK(!host.empty()); |
| 112 GetOriginsHelper(type, host, callback_ptr); |
| 113 } |
| 114 |
| 115 void AppCacheQuotaClient::DeleteOriginData(const GURL& origin, |
| 116 quota::StorageType type, |
| 117 DeletionCallback* callback_ptr) { |
| 118 DCHECK(callback_ptr); |
| 119 DCHECK(!quota_manager_is_destroyed_); |
| 120 |
| 121 scoped_ptr<DeletionCallback> callback(callback_ptr); |
| 122 if (!service_) { |
| 123 callback->Run(quota::kQuotaErrorAbort); |
| 124 return; |
| 125 } |
| 126 |
| 127 if (!appcache_is_ready_ || current_delete_request_callback_.get()) { |
| 128 pending_delete_requests_.push_back(DeleteRequest()); |
| 129 pending_delete_requests_.back().origin = origin; |
| 130 pending_delete_requests_.back().type = type; |
| 131 pending_delete_requests_.back().callback = callback.release(); |
| 132 return; |
| 133 } |
| 134 |
| 135 current_delete_request_callback_.swap(callback); |
| 136 if (type == quota::kStorageTypePersistent) { |
| 137 DidDeleteAppCachesForOrigin(net::OK); |
| 138 return; |
| 139 } |
| 140 service_->DeleteAppCachesForOrigin(origin, service_delete_callback_); |
| 141 } |
| 142 |
| 143 void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv) { |
| 144 if (quota_manager_is_destroyed_) |
| 145 return; |
| 146 |
| 147 // Finish the request by calling our callers callback. |
| 148 current_delete_request_callback_->Run(NetErrorCodeToQuotaStatus(rv)); |
| 149 current_delete_request_callback_.reset(); |
| 150 if (pending_delete_requests_.empty()) |
| 151 return; |
| 152 |
| 153 // Start the next in the queue. |
| 154 DeleteRequest& next_request = pending_delete_requests_.front(); |
| 155 current_delete_request_callback_.reset(next_request.callback); |
| 156 service_->DeleteAppCachesForOrigin(next_request.origin, |
| 157 service_delete_callback_); |
| 158 pending_delete_requests_.pop_front(); |
| 159 } |
| 160 |
| 161 void AppCacheQuotaClient::GetOriginsHelper( |
| 162 quota::StorageType type, |
| 163 const std::string& opt_host, |
| 164 GetOriginsCallback* callback_ptr) { |
| 165 DCHECK(callback_ptr); |
| 166 DCHECK(!quota_manager_is_destroyed_); |
| 167 |
| 168 scoped_ptr<GetOriginsCallback> callback(callback_ptr); |
| 169 if (!service_) { |
| 170 callback->Run(std::set<GURL>()); |
| 171 return; |
| 172 } |
| 173 |
| 174 if (!appcache_is_ready_) { |
| 175 pending_origins_requests_.push_back(OriginsRequest()); |
| 176 pending_origins_requests_.back().opt_host = opt_host; |
| 177 pending_origins_requests_.back().type = type; |
| 178 pending_origins_requests_.back().callback = callback.release(); |
| 179 return; |
| 180 } |
| 181 |
| 182 if (type == quota::kStorageTypePersistent) { |
| 183 callback->Run(std::set<GURL>()); |
| 184 return; |
| 185 } |
| 186 |
| 187 const AppCacheStorage::UsageMap* map = GetUsageMap(); |
| 188 std::set<GURL> origins; |
| 189 for (AppCacheStorage::UsageMap::const_iterator iter = map->begin(); |
| 190 iter != map->end(); ++iter) { |
| 191 if (opt_host.empty() || iter->first.host() == opt_host) |
| 192 origins.insert(iter->first); |
| 193 } |
| 194 callback->Run(origins); |
| 195 } |
| 196 |
| 197 void AppCacheQuotaClient::ProcessPendingRequests() { |
| 198 DCHECK(appcache_is_ready_); |
| 199 while (!pending_usage_requests_.empty()) { |
| 200 UsageRequest& request = pending_usage_requests_.front(); |
| 201 GetOriginUsage(request.origin, request.type, request.callback); |
| 202 pending_usage_requests_.pop_front(); |
| 203 } |
| 204 |
| 205 while (!pending_origins_requests_.empty()) { |
| 206 OriginsRequest& request = pending_origins_requests_.front(); |
| 207 GetOriginsHelper(request.type, request.opt_host, request.callback); |
| 208 pending_origins_requests_.pop_front(); |
| 209 } |
| 210 |
| 211 if (!pending_delete_requests_.empty()) { |
| 212 // Just start the first delete, others will follow upon completion. |
| 213 DeleteRequest& request = pending_delete_requests_.front(); |
| 214 DeleteOriginData(request.origin, request.type, request.callback); |
| 215 pending_delete_requests_.pop_front(); |
| 216 } |
| 217 } |
| 218 |
| 219 void AppCacheQuotaClient::AbortPendingRequests() { |
| 220 while (!pending_usage_requests_.empty()) { |
| 221 AbortUsageRequest(pending_usage_requests_.front()); |
| 222 pending_usage_requests_.pop_front(); |
| 223 } |
| 224 while (!pending_origins_requests_.empty()) { |
| 225 AbortOriginsRequest(pending_origins_requests_.front()); |
| 226 pending_origins_requests_.pop_front(); |
| 227 } |
| 228 while (!pending_delete_requests_.empty()) { |
| 229 AbortDeleteRequest(pending_delete_requests_.front()); |
| 230 pending_delete_requests_.pop_front(); |
| 231 } |
| 232 } |
| 233 |
| 234 void AppCacheQuotaClient::DeletePendingRequests() { |
| 235 while (!pending_usage_requests_.empty()) { |
| 236 DeleteCallbackHelper(pending_usage_requests_.front()); |
| 237 pending_usage_requests_.pop_front(); |
| 238 } |
| 239 while (!pending_origins_requests_.empty()) { |
| 240 DeleteCallbackHelper(pending_origins_requests_.front()); |
| 241 pending_origins_requests_.pop_front(); |
| 242 } |
| 243 while (!pending_delete_requests_.empty()) { |
| 244 DeleteCallbackHelper(pending_delete_requests_.front()); |
| 245 pending_delete_requests_.pop_front(); |
| 246 } |
| 247 } |
| 248 |
| 249 const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() { |
| 250 DCHECK(service_); |
| 251 return service_->storage()->usage_map(); |
| 252 } |
| 253 |
| 254 void AppCacheQuotaClient::NotifyAppCacheReady() { |
| 255 appcache_is_ready_ = true; |
| 256 ProcessPendingRequests(); |
| 257 } |
| 258 |
| 259 void AppCacheQuotaClient::NotifyAppCacheDestroyed() { |
| 260 service_ = NULL; |
| 261 AbortPendingRequests(); |
| 262 if (current_delete_request_callback_.get()) { |
| 263 current_delete_request_callback_->Run(quota::kQuotaErrorAbort); |
| 264 current_delete_request_callback_.reset(); |
| 265 service_delete_callback_.release()->Cancel(); |
| 266 } else { |
| 267 service_delete_callback_ = NULL; |
| 268 } |
| 269 if (quota_manager_is_destroyed_) |
| 270 delete this; |
| 271 } |
| 272 |
| 273 // static |
| 274 void AppCacheQuotaClient::AbortUsageRequest(const UsageRequest& request) { |
| 275 request.callback->Run(0); |
| 276 delete request.callback; |
| 277 } |
| 278 |
| 279 // static |
| 280 void AppCacheQuotaClient::AbortOriginsRequest(const OriginsRequest& request) { |
| 281 request.callback->Run(std::set<GURL>()); |
| 282 delete request.callback; |
| 283 } |
| 284 |
| 285 // static |
| 286 void AppCacheQuotaClient::AbortDeleteRequest(const DeleteRequest& request) { |
| 287 request.callback->Run(quota::kQuotaErrorAbort); |
| 288 delete request.callback; |
| 289 } |
| 290 |
| 291 } // namespace appcache |
OLD | NEW |