Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / appcache / appcache_quota_client.cc
blobcff864026744cae1355f708754ab65c5d111414e
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.
5 #include "content/browser/appcache/appcache_quota_client.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "content/browser/appcache/appcache_service_impl.h"
15 using storage::QuotaClient;
17 namespace {
18 storage::QuotaStatusCode NetErrorCodeToQuotaStatus(int code) {
19 if (code == net::OK)
20 return storage::kQuotaStatusOk;
21 else if (code == net::ERR_ABORTED)
22 return storage::kQuotaErrorAbort;
23 else
24 return storage::kQuotaStatusUnknown;
27 void RunFront(content::AppCacheQuotaClient::RequestQueue* queue) {
28 base::Closure request = queue->front();
29 queue->pop_front();
30 request.Run();
32 } // namespace
34 namespace content {
36 AppCacheQuotaClient::AppCacheQuotaClient(AppCacheServiceImpl* service)
37 : service_(service),
38 appcache_is_ready_(false),
39 quota_manager_is_destroyed_(false) {
42 AppCacheQuotaClient::~AppCacheQuotaClient() {
43 DCHECK(pending_batch_requests_.empty());
44 DCHECK(pending_serial_requests_.empty());
45 DCHECK(current_delete_request_callback_.is_null());
48 QuotaClient::ID AppCacheQuotaClient::id() const {
49 return kAppcache;
52 void AppCacheQuotaClient::OnQuotaManagerDestroyed() {
53 DeletePendingRequests();
54 if (!current_delete_request_callback_.is_null()) {
55 current_delete_request_callback_.Reset();
56 GetServiceDeleteCallback()->Cancel();
59 quota_manager_is_destroyed_ = true;
60 if (!service_)
61 delete this;
64 void AppCacheQuotaClient::GetOriginUsage(const GURL& origin,
65 storage::StorageType type,
66 const GetUsageCallback& callback) {
67 DCHECK(!callback.is_null());
68 DCHECK(!quota_manager_is_destroyed_);
70 if (!service_) {
71 callback.Run(0);
72 return;
75 if (!appcache_is_ready_) {
76 pending_batch_requests_.push_back(
77 base::Bind(&AppCacheQuotaClient::GetOriginUsage,
78 base::Unretained(this), origin, type, callback));
79 return;
82 if (type != storage::kStorageTypeTemporary) {
83 callback.Run(0);
84 return;
87 const AppCacheStorage::UsageMap* map = GetUsageMap();
88 AppCacheStorage::UsageMap::const_iterator found = map->find(origin);
89 if (found == map->end()) {
90 callback.Run(0);
91 return;
93 callback.Run(found->second);
96 void AppCacheQuotaClient::GetOriginsForType(
97 storage::StorageType type,
98 const GetOriginsCallback& callback) {
99 GetOriginsHelper(type, std::string(), callback);
102 void AppCacheQuotaClient::GetOriginsForHost(
103 storage::StorageType type,
104 const std::string& host,
105 const GetOriginsCallback& callback) {
106 DCHECK(!callback.is_null());
107 if (host.empty()) {
108 callback.Run(std::set<GURL>());
109 return;
111 GetOriginsHelper(type, host, callback);
114 void AppCacheQuotaClient::DeleteOriginData(const GURL& origin,
115 storage::StorageType type,
116 const DeletionCallback& callback) {
117 DCHECK(!quota_manager_is_destroyed_);
119 if (!service_) {
120 callback.Run(storage::kQuotaErrorAbort);
121 return;
124 if (!appcache_is_ready_ || !current_delete_request_callback_.is_null()) {
125 pending_serial_requests_.push_back(
126 base::Bind(&AppCacheQuotaClient::DeleteOriginData,
127 base::Unretained(this), origin, type, callback));
128 return;
131 current_delete_request_callback_ = callback;
132 if (type != storage::kStorageTypeTemporary) {
133 DidDeleteAppCachesForOrigin(net::OK);
134 return;
137 service_->DeleteAppCachesForOrigin(
138 origin, GetServiceDeleteCallback()->callback());
141 bool AppCacheQuotaClient::DoesSupport(storage::StorageType type) const {
142 return type == storage::kStorageTypeTemporary;
145 void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv) {
146 DCHECK(service_);
147 if (quota_manager_is_destroyed_)
148 return;
150 // Finish the request by calling our callers callback.
151 current_delete_request_callback_.Run(NetErrorCodeToQuotaStatus(rv));
152 current_delete_request_callback_.Reset();
153 if (pending_serial_requests_.empty())
154 return;
156 // Start the next in the queue.
157 RunFront(&pending_serial_requests_);
160 void AppCacheQuotaClient::GetOriginsHelper(storage::StorageType type,
161 const std::string& opt_host,
162 const GetOriginsCallback& callback) {
163 DCHECK(!callback.is_null());
164 DCHECK(!quota_manager_is_destroyed_);
166 if (!service_) {
167 callback.Run(std::set<GURL>());
168 return;
171 if (!appcache_is_ready_) {
172 pending_batch_requests_.push_back(
173 base::Bind(&AppCacheQuotaClient::GetOriginsHelper,
174 base::Unretained(this), type, opt_host, callback));
175 return;
178 if (type != storage::kStorageTypeTemporary) {
179 callback.Run(std::set<GURL>());
180 return;
183 const AppCacheStorage::UsageMap* map = GetUsageMap();
184 std::set<GURL> origins;
185 for (AppCacheStorage::UsageMap::const_iterator iter = map->begin();
186 iter != map->end(); ++iter) {
187 if (opt_host.empty() || iter->first.host() == opt_host)
188 origins.insert(iter->first);
190 callback.Run(origins);
193 void AppCacheQuotaClient::ProcessPendingRequests() {
194 DCHECK(appcache_is_ready_);
195 while (!pending_batch_requests_.empty())
196 RunFront(&pending_batch_requests_);
198 if (!pending_serial_requests_.empty())
199 RunFront(&pending_serial_requests_);
202 void AppCacheQuotaClient::DeletePendingRequests() {
203 pending_batch_requests_.clear();
204 pending_serial_requests_.clear();
207 const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() {
208 DCHECK(service_);
209 return service_->storage()->usage_map();
212 net::CancelableCompletionCallback*
213 AppCacheQuotaClient::GetServiceDeleteCallback() {
214 // Lazily created due to CancelableCompletionCallback's threading
215 // restrictions, there is no way to detach from the thread created on.
216 if (!service_delete_callback_) {
217 service_delete_callback_.reset(
218 new net::CancelableCompletionCallback(
219 base::Bind(&AppCacheQuotaClient::DidDeleteAppCachesForOrigin,
220 base::Unretained(this))));
222 return service_delete_callback_.get();
225 void AppCacheQuotaClient::NotifyAppCacheReady() {
226 // Can reoccur during reinitialization.
227 if (!appcache_is_ready_) {
228 appcache_is_ready_ = true;
229 ProcessPendingRequests();
233 void AppCacheQuotaClient::NotifyAppCacheDestroyed() {
234 service_ = NULL;
235 while (!pending_batch_requests_.empty())
236 RunFront(&pending_batch_requests_);
238 while (!pending_serial_requests_.empty())
239 RunFront(&pending_serial_requests_);
241 if (!current_delete_request_callback_.is_null()) {
242 current_delete_request_callback_.Run(storage::kQuotaErrorAbort);
243 current_delete_request_callback_.Reset();
244 GetServiceDeleteCallback()->Cancel();
247 if (quota_manager_is_destroyed_)
248 delete this;
251 } // namespace content