| 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 |