| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/appcache/appcache_quota_client.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <map> | |
| 9 #include <set> | |
| 10 | |
| 11 #include "base/bind.h" | |
| 12 #include "base/bind_helpers.h" | |
| 13 #include "webkit/browser/appcache/appcache_service_impl.h" | |
| 14 | |
| 15 using quota::QuotaClient; | |
| 16 | |
| 17 namespace { | |
| 18 quota::QuotaStatusCode NetErrorCodeToQuotaStatus(int code) { | |
| 19 if (code == net::OK) | |
| 20 return quota::kQuotaStatusOk; | |
| 21 else if (code == net::ERR_ABORTED) | |
| 22 return quota::kQuotaErrorAbort; | |
| 23 else | |
| 24 return quota::kQuotaStatusUnknown; | |
| 25 } | |
| 26 | |
| 27 void RunFront(appcache::AppCacheQuotaClient::RequestQueue* queue) { | |
| 28 base::Closure request = queue->front(); | |
| 29 queue->pop_front(); | |
| 30 request.Run(); | |
| 31 } | |
| 32 } // namespace | |
| 33 | |
| 34 namespace appcache { | |
| 35 | |
| 36 AppCacheQuotaClient::AppCacheQuotaClient(AppCacheServiceImpl* service) | |
| 37 : service_(service), | |
| 38 appcache_is_ready_(false), | |
| 39 quota_manager_is_destroyed_(false) { | |
| 40 } | |
| 41 | |
| 42 AppCacheQuotaClient::~AppCacheQuotaClient() { | |
| 43 DCHECK(pending_batch_requests_.empty()); | |
| 44 DCHECK(pending_serial_requests_.empty()); | |
| 45 DCHECK(current_delete_request_callback_.is_null()); | |
| 46 } | |
| 47 | |
| 48 QuotaClient::ID AppCacheQuotaClient::id() const { | |
| 49 return kAppcache; | |
| 50 } | |
| 51 | |
| 52 void AppCacheQuotaClient::OnQuotaManagerDestroyed() { | |
| 53 DeletePendingRequests(); | |
| 54 if (!current_delete_request_callback_.is_null()) { | |
| 55 current_delete_request_callback_.Reset(); | |
| 56 GetServiceDeleteCallback()->Cancel(); | |
| 57 } | |
| 58 | |
| 59 quota_manager_is_destroyed_ = true; | |
| 60 if (!service_) | |
| 61 delete this; | |
| 62 } | |
| 63 | |
| 64 void AppCacheQuotaClient::GetOriginUsage( | |
| 65 const GURL& origin, | |
| 66 quota::StorageType type, | |
| 67 const GetUsageCallback& callback) { | |
| 68 DCHECK(!callback.is_null()); | |
| 69 DCHECK(!quota_manager_is_destroyed_); | |
| 70 | |
| 71 if (!service_) { | |
| 72 callback.Run(0); | |
| 73 return; | |
| 74 } | |
| 75 | |
| 76 if (!appcache_is_ready_) { | |
| 77 pending_batch_requests_.push_back( | |
| 78 base::Bind(&AppCacheQuotaClient::GetOriginUsage, | |
| 79 base::Unretained(this), origin, type, callback)); | |
| 80 return; | |
| 81 } | |
| 82 | |
| 83 if (type != quota::kStorageTypeTemporary) { | |
| 84 callback.Run(0); | |
| 85 return; | |
| 86 } | |
| 87 | |
| 88 const AppCacheStorage::UsageMap* map = GetUsageMap(); | |
| 89 AppCacheStorage::UsageMap::const_iterator found = map->find(origin); | |
| 90 if (found == map->end()) { | |
| 91 callback.Run(0); | |
| 92 return; | |
| 93 } | |
| 94 callback.Run(found->second); | |
| 95 } | |
| 96 | |
| 97 void AppCacheQuotaClient::GetOriginsForType( | |
| 98 quota::StorageType type, | |
| 99 const GetOriginsCallback& callback) { | |
| 100 GetOriginsHelper(type, std::string(), callback); | |
| 101 } | |
| 102 | |
| 103 void AppCacheQuotaClient::GetOriginsForHost( | |
| 104 quota::StorageType type, | |
| 105 const std::string& host, | |
| 106 const GetOriginsCallback& callback) { | |
| 107 DCHECK(!callback.is_null()); | |
| 108 if (host.empty()) { | |
| 109 callback.Run(std::set<GURL>()); | |
| 110 return; | |
| 111 } | |
| 112 GetOriginsHelper(type, host, callback); | |
| 113 } | |
| 114 | |
| 115 void AppCacheQuotaClient::DeleteOriginData(const GURL& origin, | |
| 116 quota::StorageType type, | |
| 117 const DeletionCallback& callback) { | |
| 118 DCHECK(!quota_manager_is_destroyed_); | |
| 119 | |
| 120 if (!service_) { | |
| 121 callback.Run(quota::kQuotaErrorAbort); | |
| 122 return; | |
| 123 } | |
| 124 | |
| 125 if (!appcache_is_ready_ || !current_delete_request_callback_.is_null()) { | |
| 126 pending_serial_requests_.push_back( | |
| 127 base::Bind(&AppCacheQuotaClient::DeleteOriginData, | |
| 128 base::Unretained(this), origin, type, callback)); | |
| 129 return; | |
| 130 } | |
| 131 | |
| 132 current_delete_request_callback_ = callback; | |
| 133 if (type != quota::kStorageTypeTemporary) { | |
| 134 DidDeleteAppCachesForOrigin(net::OK); | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 service_->DeleteAppCachesForOrigin( | |
| 139 origin, GetServiceDeleteCallback()->callback()); | |
| 140 } | |
| 141 | |
| 142 bool AppCacheQuotaClient::DoesSupport(quota::StorageType type) const { | |
| 143 return type == quota::kStorageTypeTemporary; | |
| 144 } | |
| 145 | |
| 146 void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv) { | |
| 147 DCHECK(service_); | |
| 148 if (quota_manager_is_destroyed_) | |
| 149 return; | |
| 150 | |
| 151 // Finish the request by calling our callers callback. | |
| 152 current_delete_request_callback_.Run(NetErrorCodeToQuotaStatus(rv)); | |
| 153 current_delete_request_callback_.Reset(); | |
| 154 if (pending_serial_requests_.empty()) | |
| 155 return; | |
| 156 | |
| 157 // Start the next in the queue. | |
| 158 RunFront(&pending_serial_requests_); | |
| 159 } | |
| 160 | |
| 161 void AppCacheQuotaClient::GetOriginsHelper( | |
| 162 quota::StorageType type, | |
| 163 const std::string& opt_host, | |
| 164 const GetOriginsCallback& callback) { | |
| 165 DCHECK(!callback.is_null()); | |
| 166 DCHECK(!quota_manager_is_destroyed_); | |
| 167 | |
| 168 if (!service_) { | |
| 169 callback.Run(std::set<GURL>()); | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 if (!appcache_is_ready_) { | |
| 174 pending_batch_requests_.push_back( | |
| 175 base::Bind(&AppCacheQuotaClient::GetOriginsHelper, | |
| 176 base::Unretained(this), type, opt_host, callback)); | |
| 177 return; | |
| 178 } | |
| 179 | |
| 180 if (type != quota::kStorageTypeTemporary) { | |
| 181 callback.Run(std::set<GURL>()); | |
| 182 return; | |
| 183 } | |
| 184 | |
| 185 const AppCacheStorage::UsageMap* map = GetUsageMap(); | |
| 186 std::set<GURL> origins; | |
| 187 for (AppCacheStorage::UsageMap::const_iterator iter = map->begin(); | |
| 188 iter != map->end(); ++iter) { | |
| 189 if (opt_host.empty() || iter->first.host() == opt_host) | |
| 190 origins.insert(iter->first); | |
| 191 } | |
| 192 callback.Run(origins); | |
| 193 } | |
| 194 | |
| 195 void AppCacheQuotaClient::ProcessPendingRequests() { | |
| 196 DCHECK(appcache_is_ready_); | |
| 197 while (!pending_batch_requests_.empty()) | |
| 198 RunFront(&pending_batch_requests_); | |
| 199 | |
| 200 if (!pending_serial_requests_.empty()) | |
| 201 RunFront(&pending_serial_requests_); | |
| 202 } | |
| 203 | |
| 204 void AppCacheQuotaClient::DeletePendingRequests() { | |
| 205 pending_batch_requests_.clear(); | |
| 206 pending_serial_requests_.clear(); | |
| 207 } | |
| 208 | |
| 209 const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() { | |
| 210 DCHECK(service_); | |
| 211 return service_->storage()->usage_map(); | |
| 212 } | |
| 213 | |
| 214 net::CancelableCompletionCallback* | |
| 215 AppCacheQuotaClient::GetServiceDeleteCallback() { | |
| 216 // Lazily created due to CancelableCompletionCallback's threading | |
| 217 // restrictions, there is no way to detach from the thread created on. | |
| 218 if (!service_delete_callback_) { | |
| 219 service_delete_callback_.reset( | |
| 220 new net::CancelableCompletionCallback( | |
| 221 base::Bind(&AppCacheQuotaClient::DidDeleteAppCachesForOrigin, | |
| 222 base::Unretained(this)))); | |
| 223 } | |
| 224 return service_delete_callback_.get(); | |
| 225 } | |
| 226 | |
| 227 void AppCacheQuotaClient::NotifyAppCacheReady() { | |
| 228 // Can reoccur during reinitialization. | |
| 229 if (!appcache_is_ready_) { | |
| 230 appcache_is_ready_ = true; | |
| 231 ProcessPendingRequests(); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 void AppCacheQuotaClient::NotifyAppCacheDestroyed() { | |
| 236 service_ = NULL; | |
| 237 while (!pending_batch_requests_.empty()) | |
| 238 RunFront(&pending_batch_requests_); | |
| 239 | |
| 240 while (!pending_serial_requests_.empty()) | |
| 241 RunFront(&pending_serial_requests_); | |
| 242 | |
| 243 if (!current_delete_request_callback_.is_null()) { | |
| 244 current_delete_request_callback_.Run(quota::kQuotaErrorAbort); | |
| 245 current_delete_request_callback_.Reset(); | |
| 246 GetServiceDeleteCallback()->Cancel(); | |
| 247 } | |
| 248 | |
| 249 if (quota_manager_is_destroyed_) | |
| 250 delete this; | |
| 251 } | |
| 252 | |
| 253 } // namespace appcache | |
| OLD | NEW |