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"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "content/browser/appcache/appcache_service_impl.h"
15 using storage::QuotaClient
;
18 storage::QuotaStatusCode
NetErrorCodeToQuotaStatus(int code
) {
20 return storage::kQuotaStatusOk
;
21 else if (code
== net::ERR_ABORTED
)
22 return storage::kQuotaErrorAbort
;
24 return storage::kQuotaStatusUnknown
;
27 void RunFront(content::AppCacheQuotaClient::RequestQueue
* queue
) {
28 base::Closure request
= queue
->front();
36 AppCacheQuotaClient::AppCacheQuotaClient(AppCacheServiceImpl
* 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 {
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;
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_
);
75 if (!appcache_is_ready_
) {
76 pending_batch_requests_
.push_back(
77 base::Bind(&AppCacheQuotaClient::GetOriginUsage
,
78 base::Unretained(this), origin
, type
, callback
));
82 if (type
!= storage::kStorageTypeTemporary
) {
87 const AppCacheStorage::UsageMap
* map
= GetUsageMap();
88 AppCacheStorage::UsageMap::const_iterator found
= map
->find(origin
);
89 if (found
== map
->end()) {
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());
108 callback
.Run(std::set
<GURL
>());
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_
);
120 callback
.Run(storage::kQuotaErrorAbort
);
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
));
131 current_delete_request_callback_
= callback
;
132 if (type
!= storage::kStorageTypeTemporary
) {
133 DidDeleteAppCachesForOrigin(net::OK
);
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
) {
147 if (quota_manager_is_destroyed_
)
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())
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_
);
167 callback
.Run(std::set
<GURL
>());
171 if (!appcache_is_ready_
) {
172 pending_batch_requests_
.push_back(
173 base::Bind(&AppCacheQuotaClient::GetOriginsHelper
,
174 base::Unretained(this), type
, opt_host
, callback
));
178 if (type
!= storage::kStorageTypeTemporary
) {
179 callback
.Run(std::set
<GURL
>());
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() {
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() {
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_
)
251 } // namespace content