Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / appcache / appcache_quota_client.cc
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 "content/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 "content/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(content::AppCacheQuotaClient::RequestQueue* queue) {
28   base::Closure request = queue->front();
29   queue->pop_front();
30   request.Run();
31 }
32 }  // namespace
33
34 namespace content {
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 content