OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "components/browsing_data/storage_partition_http_cache_data_remover.h" | |
6 | |
7 #include "base/location.h" | |
8 #include "base/single_thread_task_runner.h" | |
9 #include "base/threading/thread_task_runner_handle.h" | |
10 #include "components/browsing_data/conditional_cache_deletion_helper.h" | |
11 #include "content/public/browser/browser_thread.h" | |
12 #include "content/public/browser/storage_partition.h" | |
13 #include "net/base/sdch_manager.h" | |
14 #include "net/disk_cache/blockfile/backend_impl.h" | |
15 #include "net/disk_cache/disk_cache.h" | |
16 #include "net/disk_cache/memory/mem_backend_impl.h" | |
17 #include "net/disk_cache/simple/simple_backend_impl.h" | |
18 #include "net/http/http_cache.h" | |
19 #include "net/url_request/url_request_context.h" | |
20 #include "net/url_request/url_request_context_getter.h" | |
21 | |
22 using content::BrowserThread; | |
23 | |
24 namespace browsing_data { | |
25 | |
26 StoragePartitionHttpCacheDataRemover::StoragePartitionHttpCacheDataRemover( | |
27 base::Callback<bool(const GURL&)> url_predicate, | |
28 base::Time delete_begin, | |
29 base::Time delete_end, | |
30 net::URLRequestContextGetter* main_context_getter, | |
31 net::URLRequestContextGetter* media_context_getter) | |
32 : url_predicate_(url_predicate), | |
33 delete_begin_(delete_begin), | |
34 delete_end_(delete_end), | |
35 main_context_getter_(main_context_getter), | |
36 media_context_getter_(media_context_getter), | |
37 next_cache_state_(STATE_NONE), | |
38 cache_(nullptr), | |
39 calculation_result_(0) { | |
40 } | |
41 | |
42 StoragePartitionHttpCacheDataRemover::~StoragePartitionHttpCacheDataRemover() { | |
43 } | |
44 | |
45 // static. | |
46 StoragePartitionHttpCacheDataRemover* | |
47 StoragePartitionHttpCacheDataRemover::CreateForRange( | |
48 content::StoragePartition* storage_partition, | |
49 base::Time delete_begin, | |
50 base::Time delete_end) { | |
51 return new StoragePartitionHttpCacheDataRemover( | |
52 base::Callback<bool(const GURL&)>(), // Null callback. | |
53 delete_begin, delete_end, | |
54 storage_partition->GetURLRequestContext(), | |
55 storage_partition->GetMediaURLRequestContext()); | |
56 } | |
57 | |
58 // static. | |
59 StoragePartitionHttpCacheDataRemover* | |
60 StoragePartitionHttpCacheDataRemover::CreateForURLsAndRange( | |
61 content::StoragePartition* storage_partition, | |
62 const base::Callback<bool(const GURL&)>& url_predicate, | |
63 base::Time delete_begin, | |
64 base::Time delete_end) { | |
65 return new StoragePartitionHttpCacheDataRemover( | |
66 url_predicate, delete_begin, delete_end, | |
67 storage_partition->GetURLRequestContext(), | |
68 storage_partition->GetMediaURLRequestContext()); | |
69 } | |
70 | |
71 void StoragePartitionHttpCacheDataRemover::Remove( | |
72 const base::Closure& done_callback) { | |
73 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
74 DCHECK(!done_callback.is_null()); | |
75 done_callback_ = done_callback; | |
76 | |
77 BrowserThread::PostTask( | |
78 BrowserThread::IO, FROM_HERE, | |
79 base::Bind( | |
80 &StoragePartitionHttpCacheDataRemover::ClearHttpCacheOnIOThread, | |
81 base::Unretained(this))); | |
82 } | |
83 | |
84 void StoragePartitionHttpCacheDataRemover::Count( | |
85 const net::Int64CompletionCallback& result_callback) { | |
86 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
87 DCHECK(!result_callback.is_null()); | |
88 result_callback_ = result_callback; | |
89 calculation_result_ = 0; | |
90 | |
91 BrowserThread::PostTask( | |
92 BrowserThread::IO, FROM_HERE, | |
93 base::Bind( | |
94 &StoragePartitionHttpCacheDataRemover::CountHttpCacheOnIOThread, | |
95 base::Unretained(this))); | |
96 } | |
97 | |
98 void StoragePartitionHttpCacheDataRemover::ClearHttpCacheOnIOThread() { | |
99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
100 next_cache_state_ = STATE_NONE; | |
101 DCHECK_EQ(STATE_NONE, next_cache_state_); | |
102 DCHECK(main_context_getter_.get()); | |
103 DCHECK(media_context_getter_.get()); | |
104 | |
105 next_cache_state_ = STATE_CREATE_MAIN; | |
106 DoClearCache(net::OK); | |
107 } | |
108 | |
109 void StoragePartitionHttpCacheDataRemover::CountHttpCacheOnIOThread() { | |
110 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
111 next_cache_state_ = STATE_NONE; | |
112 DCHECK_EQ(STATE_NONE, next_cache_state_); | |
113 DCHECK(main_context_getter_.get()); | |
114 DCHECK(media_context_getter_.get()); | |
115 | |
116 next_cache_state_ = STATE_CREATE_MAIN; | |
117 DoCountCache(net::OK); | |
118 } | |
119 | |
120 void StoragePartitionHttpCacheDataRemover::ClearedHttpCache() { | |
121 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
122 done_callback_.Run(); | |
123 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | |
124 } | |
125 | |
126 void StoragePartitionHttpCacheDataRemover::CountedHttpCache() { | |
127 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
128 result_callback_.Run(calculation_result_); | |
129 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | |
130 } | |
131 | |
132 // The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> | |
133 // STATE_PROCESS_MAIN --> STATE_CREATE_MEDIA --> STATE_PROCESS_MEDIA --> | |
134 // STATE_DONE, and any errors are ignored. | |
135 void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) { | |
136 DCHECK_NE(STATE_NONE, next_cache_state_); | |
137 | |
138 while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { | |
139 switch (next_cache_state_) { | |
140 case STATE_CREATE_MAIN: | |
141 case STATE_CREATE_MEDIA: { | |
142 // Get a pointer to the cache. | |
143 net::URLRequestContextGetter* getter = | |
144 (next_cache_state_ == STATE_CREATE_MAIN) | |
145 ? main_context_getter_.get() | |
146 : media_context_getter_.get(); | |
147 net::HttpCache* http_cache = getter->GetURLRequestContext() | |
148 ->http_transaction_factory() | |
149 ->GetCache(); | |
150 | |
151 next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) | |
152 ? STATE_PROCESS_MAIN | |
153 : STATE_PROCESS_MEDIA; | |
154 | |
155 // Clear QUIC server information from memory and the disk cache. | |
156 http_cache->GetSession() | |
157 ->quic_stream_factory() | |
158 ->ClearCachedStatesInCryptoConfig(); | |
159 | |
160 // Clear SDCH dictionary state. | |
161 net::SdchManager* sdch_manager = | |
162 getter->GetURLRequestContext()->sdch_manager(); | |
163 // The test is probably overkill, since chrome should always have an | |
164 // SdchManager. But in general the URLRequestContext is *not* | |
165 // guaranteed to have an SdchManager, so checking is wise. | |
166 if (sdch_manager) | |
167 sdch_manager->ClearData(); | |
168 | |
169 rv = http_cache->GetBackend( | |
170 &cache_, | |
171 base::Bind(&StoragePartitionHttpCacheDataRemover::DoClearCache, | |
172 base::Unretained(this))); | |
173 break; | |
174 } | |
175 case STATE_PROCESS_MAIN: | |
176 case STATE_PROCESS_MEDIA: { | |
177 next_cache_state_ = (next_cache_state_ == STATE_PROCESS_MAIN) | |
178 ? STATE_CREATE_MEDIA | |
179 : STATE_DONE; | |
180 | |
181 // |cache_| can be null if it cannot be initialized. | |
182 if (cache_) { | |
183 if (!url_predicate_.is_null()) { | |
184 rv = (new ConditionalCacheDeletionHelper( | |
185 cache_, | |
186 ConditionalCacheDeletionHelper::CreateURLAndTimeCondition( | |
187 url_predicate_, | |
188 delete_begin_, | |
189 delete_end_)))->DeleteAndDestroySelfWhenFinished( | |
190 base::Bind( | |
191 &StoragePartitionHttpCacheDataRemover::DoClearCache, | |
192 base::Unretained(this))); | |
193 } else if (delete_begin_.is_null() && delete_end_.is_max()) { | |
194 rv = cache_->DoomAllEntries(base::Bind( | |
195 &StoragePartitionHttpCacheDataRemover::DoClearCache, | |
196 base::Unretained(this))); | |
197 } else { | |
198 rv = cache_->DoomEntriesBetween( | |
199 delete_begin_, delete_end_, | |
200 base::Bind( | |
201 &StoragePartitionHttpCacheDataRemover::DoClearCache, | |
202 base::Unretained(this))); | |
203 } | |
204 cache_ = NULL; | |
205 } | |
206 break; | |
207 } | |
208 case STATE_DONE: { | |
209 cache_ = NULL; | |
210 next_cache_state_ = STATE_NONE; | |
211 | |
212 // Notify the UI thread that we are done. | |
213 BrowserThread::PostTask( | |
214 BrowserThread::UI, FROM_HERE, | |
215 base::Bind(&StoragePartitionHttpCacheDataRemover::ClearedHttpCache, | |
216 base::Unretained(this))); | |
217 return; | |
218 } | |
219 default: { | |
220 NOTREACHED() << "bad state"; | |
221 next_cache_state_ = STATE_NONE; // Stop looping. | |
222 return; | |
223 } | |
224 } | |
225 } | |
226 } | |
227 | |
228 // The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> | |
229 // STATE_PROCESS_MAIN --> STATE_CREATE_MEDIA --> STATE_PROCESS_MEDIA --> | |
230 // STATE_DONE. On error, we jump directly to STATE_DONE. | |
231 void StoragePartitionHttpCacheDataRemover::DoCountCache(int rv) { | |
232 DCHECK_NE(STATE_NONE, next_cache_state_); | |
233 | |
234 while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { | |
235 // On error, finish and return the error code. A valid result value might | |
236 // be of two types - either net::OK from the CREATE states, or the result | |
237 // of calculation from the PROCESS states. Since net::OK == 0, it is valid | |
238 // to simply add the value to the final calculation result. | |
239 if (rv < 0) { | |
240 calculation_result_ = rv; | |
241 next_cache_state_ = STATE_DONE; | |
242 } else { | |
243 DCHECK_EQ(0, net::OK); | |
244 calculation_result_ += rv; | |
245 } | |
246 | |
247 switch (next_cache_state_) { | |
248 case STATE_CREATE_MAIN: | |
249 case STATE_CREATE_MEDIA: { | |
250 // Get a pointer to the cache. | |
251 net::URLRequestContextGetter* getter = | |
252 (next_cache_state_ == STATE_CREATE_MAIN) | |
253 ? main_context_getter_.get() | |
254 : media_context_getter_.get(); | |
255 net::HttpCache* http_cache = getter->GetURLRequestContext() | |
256 ->http_transaction_factory() | |
257 ->GetCache(); | |
258 | |
259 next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) | |
260 ? STATE_PROCESS_MAIN | |
261 : STATE_PROCESS_MEDIA; | |
262 | |
263 rv = http_cache->GetBackend( | |
264 &cache_, | |
265 base::Bind(&StoragePartitionHttpCacheDataRemover::DoCountCache, | |
266 base::Unretained(this))); | |
267 break; | |
268 } | |
269 case STATE_PROCESS_MAIN: | |
270 case STATE_PROCESS_MEDIA: { | |
271 next_cache_state_ = (next_cache_state_ == STATE_PROCESS_MAIN) | |
272 ? STATE_CREATE_MEDIA | |
273 : STATE_DONE; | |
274 | |
275 // |cache_| can be null if it cannot be initialized. | |
276 if (cache_) { | |
277 if (delete_begin_.is_null() && delete_end_.is_max()) { | |
278 rv = cache_->CalculateSizeOfAllEntries( | |
279 base::Bind( | |
280 &StoragePartitionHttpCacheDataRemover::DoCountCache, | |
281 base::Unretained(this))); | |
282 } else { | |
283 // TODO(msramek): Implement this when we need it. | |
284 DoCountCache(net::ERR_NOT_IMPLEMENTED); | |
285 } | |
286 cache_ = NULL; | |
287 } | |
288 break; | |
289 } | |
290 case STATE_DONE: { | |
291 cache_ = NULL; | |
292 next_cache_state_ = STATE_NONE; | |
293 | |
294 // Notify the UI thread that we are done. | |
295 BrowserThread::PostTask( | |
296 BrowserThread::UI, FROM_HERE, | |
297 base::Bind(&StoragePartitionHttpCacheDataRemover::CountedHttpCache, | |
298 base::Unretained(this))); | |
299 return; | |
300 } | |
301 default: { | |
302 NOTREACHED() << "bad state"; | |
303 next_cache_state_ = STATE_NONE; // Stop looping. | |
304 return; | |
305 } | |
306 } | |
307 } | |
308 } | |
309 | |
310 } // namespace browsing_data | |
OLD | NEW |