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 |