OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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/content/conditional_cache_counting_helper.h" |
| 6 |
| 7 #include "base/callback.h" |
| 8 #include "base/single_thread_task_runner.h" |
| 9 #include "base/threading/thread_task_runner_handle.h" |
| 10 #include "content/public/browser/browser_thread.h" |
| 11 #include "content/public/browser/storage_partition.h" |
| 12 #include "net/disk_cache/disk_cache.h" |
| 13 #include "net/http/http_cache.h" |
| 14 #include "net/url_request/url_request_context.h" |
| 15 #include "net/url_request/url_request_context_getter.h" |
| 16 |
| 17 using content::BrowserThread; |
| 18 |
| 19 namespace browsing_data { |
| 20 |
| 21 // static. |
| 22 ConditionalCacheCountingHelper* ConditionalCacheCountingHelper::CreateForRange( |
| 23 content::StoragePartition* storage_partition, |
| 24 base::Time begin_time, |
| 25 base::Time end_time) { |
| 26 return new ConditionalCacheCountingHelper( |
| 27 begin_time, end_time, storage_partition->GetURLRequestContext(), |
| 28 storage_partition->GetMediaURLRequestContext()); |
| 29 } |
| 30 |
| 31 ConditionalCacheCountingHelper::ConditionalCacheCountingHelper( |
| 32 base::Time begin_time, |
| 33 base::Time end_time, |
| 34 net::URLRequestContextGetter* main_context_getter, |
| 35 net::URLRequestContextGetter* media_context_getter) |
| 36 : calculation_result_(0), |
| 37 begin_time_(begin_time), |
| 38 end_time_(end_time), |
| 39 is_finished_(false), |
| 40 main_context_getter_(main_context_getter), |
| 41 media_context_getter_(media_context_getter), |
| 42 next_cache_state_(CacheState::NONE), |
| 43 cache_(nullptr), |
| 44 iterator_(nullptr), |
| 45 weak_ptr_factory_(this) { |
| 46 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 47 } |
| 48 |
| 49 ConditionalCacheCountingHelper::~ConditionalCacheCountingHelper() { |
| 50 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 51 } |
| 52 |
| 53 base::WeakPtr<ConditionalCacheCountingHelper> |
| 54 ConditionalCacheCountingHelper::CountAndDestroySelfWhenFinished( |
| 55 const CacheCountCallback& result_callback) { |
| 56 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 57 DCHECK(!result_callback.is_null()); |
| 58 result_callback_ = result_callback; |
| 59 calculation_result_ = 0; |
| 60 |
| 61 BrowserThread::PostTask( |
| 62 BrowserThread::IO, FROM_HERE, |
| 63 base::Bind(&ConditionalCacheCountingHelper::CountHttpCacheOnIOThread, |
| 64 base::Unretained(this))); |
| 65 return weak_ptr_factory_.GetWeakPtr(); |
| 66 } |
| 67 |
| 68 bool ConditionalCacheCountingHelper::IsFinished() { |
| 69 return is_finished_; |
| 70 } |
| 71 |
| 72 void ConditionalCacheCountingHelper::Finished() { |
| 73 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 74 DCHECK(!is_finished_); |
| 75 is_finished_ = true; |
| 76 result_callback_.Run(calculation_result_); |
| 77 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
| 78 } |
| 79 |
| 80 void ConditionalCacheCountingHelper::CountHttpCacheOnIOThread() { |
| 81 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 82 next_cache_state_ = CacheState::NONE; |
| 83 DCHECK_EQ(CacheState::NONE, next_cache_state_); |
| 84 DCHECK(main_context_getter_.get()); |
| 85 DCHECK(media_context_getter_.get()); |
| 86 |
| 87 next_cache_state_ = CacheState::CREATE_MAIN; |
| 88 DoCountCache(net::OK); |
| 89 } |
| 90 |
| 91 // The expected state sequence is CacheState::NONE --> CacheState::CREATE_MAIN |
| 92 // --> CacheState::PROCESS_MAIN --> CacheState::CREATE_MEDIA --> |
| 93 // CacheState::PROCESS_MEDIA --> CacheState::DONE. |
| 94 // On error, we jump directly to CacheState::DONE. |
| 95 void ConditionalCacheCountingHelper::DoCountCache(int rv) { |
| 96 DCHECK_NE(CacheState::NONE, next_cache_state_); |
| 97 while (rv != net::ERR_IO_PENDING && next_cache_state_ != CacheState::NONE) { |
| 98 // On error, finish and return the error code. A valid result value might |
| 99 // be of two types - either net::OK from the CREATE states, or the result |
| 100 // of calculation from the PROCESS states. Since net::OK == 0, it is valid |
| 101 // to simply add the value to the final calculation result. |
| 102 if (rv < 0) { |
| 103 calculation_result_ = rv; |
| 104 next_cache_state_ = CacheState::DONE; |
| 105 } else { |
| 106 DCHECK_EQ(0, net::OK); |
| 107 calculation_result_ += rv; |
| 108 } |
| 109 |
| 110 switch (next_cache_state_) { |
| 111 case CacheState::CREATE_MAIN: |
| 112 case CacheState::CREATE_MEDIA: { |
| 113 // Get a pointer to the cache. |
| 114 net::URLRequestContextGetter* getter = |
| 115 (next_cache_state_ == CacheState::CREATE_MAIN) |
| 116 ? main_context_getter_.get() |
| 117 : media_context_getter_.get(); |
| 118 net::HttpCache* http_cache = getter->GetURLRequestContext() |
| 119 ->http_transaction_factory() |
| 120 ->GetCache(); |
| 121 |
| 122 next_cache_state_ = (next_cache_state_ == CacheState::CREATE_MAIN) |
| 123 ? CacheState::COUNT_MAIN |
| 124 : CacheState::COUNT_MEDIA; |
| 125 |
| 126 rv = http_cache->GetBackend( |
| 127 &cache_, base::Bind(&ConditionalCacheCountingHelper::DoCountCache, |
| 128 base::Unretained(this))); |
| 129 break; |
| 130 } |
| 131 case CacheState::COUNT_MAIN: |
| 132 case CacheState::COUNT_MEDIA: { |
| 133 next_cache_state_ = (next_cache_state_ == CacheState::COUNT_MAIN) |
| 134 ? CacheState::CREATE_MEDIA |
| 135 : CacheState::DONE; |
| 136 |
| 137 // |cache_| can be null if it cannot be initialized. |
| 138 if (cache_) { |
| 139 if (begin_time_.is_null() && end_time_.is_max()) { |
| 140 rv = cache_->CalculateSizeOfAllEntries( |
| 141 base::Bind(&ConditionalCacheCountingHelper::DoCountCache, |
| 142 base::Unretained(this))); |
| 143 } else { |
| 144 // TODO(dullweber): Readd code for counting with timeout. |
| 145 // TODO(dullweber): Implement faster counting for SimpleBackendImpl. |
| 146 rv = cache_->CalculateSizeOfAllEntries( |
| 147 base::Bind(&ConditionalCacheCountingHelper::DoCountCache, |
| 148 base::Unretained(this))); |
| 149 } |
| 150 cache_ = NULL; |
| 151 } |
| 152 break; |
| 153 } |
| 154 case CacheState::DONE: { |
| 155 cache_ = NULL; |
| 156 next_cache_state_ = CacheState::NONE; |
| 157 // Notify the UI thread that we are done. |
| 158 BrowserThread::PostTask( |
| 159 BrowserThread::UI, FROM_HERE, |
| 160 base::Bind(&ConditionalCacheCountingHelper::Finished, |
| 161 base::Unretained(this))); |
| 162 return; |
| 163 } |
| 164 case CacheState::NONE: { |
| 165 NOTREACHED() << "bad state"; |
| 166 return; |
| 167 } |
| 168 } |
| 169 } |
| 170 } |
| 171 |
| 172 } // namespace browsing_data |
OLD | NEW |