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 "webkit/browser/appcache/appcache_quota_client.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "webkit/browser/appcache/appcache_service.h"
15 using quota::QuotaClient
;
18 quota::QuotaStatusCode
NetErrorCodeToQuotaStatus(int code
) {
20 return quota::kQuotaStatusOk
;
21 else if (code
== net::ERR_ABORTED
)
22 return quota::kQuotaErrorAbort
;
24 return quota::kQuotaStatusUnknown
;
27 void RunFront(appcache::AppCacheQuotaClient::RequestQueue
* queue
) {
28 base::Closure request
= queue
->front();
36 AppCacheQuotaClient::AppCacheQuotaClient(AppCacheService
* 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(
66 quota::StorageType type
,
67 const GetUsageCallback
& callback
) {
68 DCHECK(!callback
.is_null());
69 DCHECK(!quota_manager_is_destroyed_
);
76 if (!appcache_is_ready_
) {
77 pending_batch_requests_
.push_back(
78 base::Bind(&AppCacheQuotaClient::GetOriginUsage
,
79 base::Unretained(this), origin
, type
, callback
));
83 if (type
!= quota::kStorageTypeTemporary
) {
88 const AppCacheStorage::UsageMap
* map
= GetUsageMap();
89 AppCacheStorage::UsageMap::const_iterator found
= map
->find(origin
);
90 if (found
== map
->end()) {
94 callback
.Run(found
->second
);
97 void AppCacheQuotaClient::GetOriginsForType(
98 quota::StorageType type
,
99 const GetOriginsCallback
& callback
) {
100 GetOriginsHelper(type
, std::string(), callback
);
103 void AppCacheQuotaClient::GetOriginsForHost(
104 quota::StorageType type
,
105 const std::string
& host
,
106 const GetOriginsCallback
& callback
) {
107 DCHECK(!callback
.is_null());
109 callback
.Run(std::set
<GURL
>());
112 GetOriginsHelper(type
, host
, callback
);
115 void AppCacheQuotaClient::DeleteOriginData(const GURL
& origin
,
116 quota::StorageType type
,
117 const DeletionCallback
& callback
) {
118 DCHECK(!quota_manager_is_destroyed_
);
121 callback
.Run(quota::kQuotaErrorAbort
);
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
));
132 current_delete_request_callback_
= callback
;
133 if (type
!= quota::kStorageTypeTemporary
) {
134 DidDeleteAppCachesForOrigin(net::OK
);
138 service_
->DeleteAppCachesForOrigin(
139 origin
, GetServiceDeleteCallback()->callback());
142 void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv
) {
144 if (quota_manager_is_destroyed_
)
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_serial_requests_
.empty())
153 // Start the next in the queue.
154 RunFront(&pending_serial_requests_
);
157 void AppCacheQuotaClient::GetOriginsHelper(
158 quota::StorageType type
,
159 const std::string
& opt_host
,
160 const GetOriginsCallback
& callback
) {
161 DCHECK(!callback
.is_null());
162 DCHECK(!quota_manager_is_destroyed_
);
165 callback
.Run(std::set
<GURL
>());
169 if (!appcache_is_ready_
) {
170 pending_batch_requests_
.push_back(
171 base::Bind(&AppCacheQuotaClient::GetOriginsHelper
,
172 base::Unretained(this), type
, opt_host
, callback
));
176 if (type
!= quota::kStorageTypeTemporary
) {
177 callback
.Run(std::set
<GURL
>());
181 const AppCacheStorage::UsageMap
* map
= GetUsageMap();
182 std::set
<GURL
> origins
;
183 for (AppCacheStorage::UsageMap::const_iterator iter
= map
->begin();
184 iter
!= map
->end(); ++iter
) {
185 if (opt_host
.empty() || iter
->first
.host() == opt_host
)
186 origins
.insert(iter
->first
);
188 callback
.Run(origins
);
191 void AppCacheQuotaClient::ProcessPendingRequests() {
192 DCHECK(appcache_is_ready_
);
193 while (!pending_batch_requests_
.empty())
194 RunFront(&pending_batch_requests_
);
196 if (!pending_serial_requests_
.empty())
197 RunFront(&pending_serial_requests_
);
200 void AppCacheQuotaClient::DeletePendingRequests() {
201 pending_batch_requests_
.clear();
202 pending_serial_requests_
.clear();
205 const AppCacheStorage::UsageMap
* AppCacheQuotaClient::GetUsageMap() {
207 return service_
->storage()->usage_map();
210 net::CancelableCompletionCallback
*
211 AppCacheQuotaClient::GetServiceDeleteCallback() {
212 // Lazily created due to CancelableCompletionCallback's threading
213 // restrictions, there is no way to detach from the thread created on.
214 if (!service_delete_callback_
) {
215 service_delete_callback_
.reset(
216 new net::CancelableCompletionCallback(
217 base::Bind(&AppCacheQuotaClient::DidDeleteAppCachesForOrigin
,
218 base::Unretained(this))));
220 return service_delete_callback_
.get();
223 void AppCacheQuotaClient::NotifyAppCacheReady() {
224 appcache_is_ready_
= true;
225 ProcessPendingRequests();
228 void AppCacheQuotaClient::NotifyAppCacheDestroyed() {
230 while (!pending_batch_requests_
.empty())
231 RunFront(&pending_batch_requests_
);
233 while (!pending_serial_requests_
.empty())
234 RunFront(&pending_serial_requests_
);
236 if (!current_delete_request_callback_
.is_null()) {
237 current_delete_request_callback_
.Run(quota::kQuotaErrorAbort
);
238 current_delete_request_callback_
.Reset();
239 GetServiceDeleteCallback()->Cancel();
242 if (quota_manager_is_destroyed_
)
246 } // namespace appcache