Chromium Code Reviews| 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_cancelled_(false), | |
| 40 is_finished_(false), | |
| 41 main_context_getter_(main_context_getter), | |
| 42 media_context_getter_(media_context_getter), | |
| 43 next_cache_state_(STATE_NONE), | |
| 44 cache_(nullptr), | |
| 45 iterator_(nullptr), | |
| 46 current_entry_(nullptr), | |
| 47 weak_ptr_factory_(this) { | |
| 48 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 49 } | |
| 50 | |
| 51 ConditionalCacheCountingHelper::~ConditionalCacheCountingHelper() { | |
| 52 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 53 } | |
| 54 | |
| 55 base::WeakPtr<ConditionalCacheCountingHelper> | |
| 56 ConditionalCacheCountingHelper::CountAndDestroySelfWhenFinished( | |
| 57 const CacheCountCallback& result_callback) { | |
| 58 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 59 DCHECK(!result_callback.is_null()); | |
| 60 result_callback_ = result_callback; | |
| 61 calculation_result_ = 0; | |
| 62 | |
| 63 BrowserThread::PostTask( | |
| 64 BrowserThread::IO, FROM_HERE, | |
| 65 base::Bind(&ConditionalCacheCountingHelper::CountHttpCacheOnIOThread, | |
| 66 base::Unretained(this))); | |
| 67 return weak_ptr_factory_.GetWeakPtr(); | |
| 68 } | |
| 69 | |
| 70 void ConditionalCacheCountingHelper::CancelCounting() { | |
| 71 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 72 DCHECK(!is_finished_); | |
| 73 is_cancelled_ = true; | |
| 74 } | |
| 75 | |
| 76 bool ConditionalCacheCountingHelper::IsFinished() { | |
| 77 return is_finished_; | |
| 78 } | |
| 79 | |
| 80 void ConditionalCacheCountingHelper::Finished() { | |
| 81 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 82 DCHECK(!is_finished_); | |
| 83 is_finished_ = true; | |
| 84 result_callback_.Run(calculation_result_); | |
| 85 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | |
| 86 } | |
| 87 | |
| 88 void ConditionalCacheCountingHelper::CountHttpCacheOnIOThread() { | |
| 89 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 90 next_cache_state_ = STATE_NONE; | |
| 91 DCHECK_EQ(STATE_NONE, next_cache_state_); | |
| 92 DCHECK(main_context_getter_.get()); | |
| 93 DCHECK(media_context_getter_.get()); | |
| 94 | |
| 95 next_cache_state_ = STATE_CREATE_MAIN; | |
| 96 DoCountCache(net::OK); | |
| 97 } | |
| 98 | |
| 99 // The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> | |
| 100 // STATE_PROCESS_MAIN --> STATE_CREATE_MEDIA --> STATE_PROCESS_MEDIA --> | |
| 101 // STATE_DONE. On error, we jump directly to STATE_DONE. | |
| 102 void ConditionalCacheCountingHelper::DoCountCache(int rv) { | |
| 103 DCHECK_NE(STATE_NONE, next_cache_state_); | |
| 104 while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { | |
| 105 // On error, finish and return the error code. A valid result value might | |
| 106 // be of two types - either net::OK from the CREATE states, or the result | |
| 107 // of calculation from the PROCESS states. Since net::OK == 0, it is valid | |
| 108 // to simply add the value to the final calculation result. | |
| 109 if (rv < 0) { | |
| 110 calculation_result_ = rv; | |
| 111 next_cache_state_ = STATE_DONE; | |
| 112 } else { | |
| 113 DCHECK_EQ(0, net::OK); | |
| 114 calculation_result_ += rv; | |
| 115 } | |
| 116 | |
| 117 switch (next_cache_state_) { | |
| 118 case STATE_CREATE_MAIN: | |
| 119 case STATE_CREATE_MEDIA: { | |
| 120 // Get a pointer to the cache. | |
| 121 net::URLRequestContextGetter* getter = | |
| 122 (next_cache_state_ == STATE_CREATE_MAIN) | |
| 123 ? main_context_getter_.get() | |
| 124 : media_context_getter_.get(); | |
| 125 net::HttpCache* http_cache = getter->GetURLRequestContext() | |
| 126 ->http_transaction_factory() | |
| 127 ->GetCache(); | |
| 128 | |
| 129 next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) | |
| 130 ? STATE_PROCESS_MAIN | |
| 131 : STATE_PROCESS_MEDIA; | |
| 132 | |
| 133 rv = http_cache->GetBackend( | |
| 134 &cache_, base::Bind(&ConditionalCacheCountingHelper::DoCountCache, | |
| 135 base::Unretained(this))); | |
| 136 break; | |
| 137 } | |
| 138 case STATE_PROCESS_MAIN: | |
| 139 case STATE_PROCESS_MEDIA: { | |
| 140 next_cache_state_ = (next_cache_state_ == STATE_PROCESS_MAIN) | |
| 141 ? STATE_CREATE_MEDIA | |
| 142 : STATE_DONE; | |
| 143 | |
| 144 // |cache_| can be null if it cannot be initialized. | |
| 145 if (cache_) { | |
| 146 if (begin_time_.is_null() && end_time_.is_max()) { | |
| 147 rv = cache_->CalculateSizeOfAllEntries( | |
| 148 base::Bind(&ConditionalCacheCountingHelper::DoCountCache, | |
| 149 base::Unretained(this))); | |
| 150 } else { | |
| 151 // TODO(dullweber): Implement faster counting for SimpleBackendImpl. | |
|
msramek
2016/12/15 15:58:51
You already implemented it in this CL, just didn't
dullweber
2016/12/16 16:41:11
I added the code to get the size of a single entry
msramek
2016/12/20 01:02:59
You seem not to have finished that sentence; howev
dullweber
2016/12/21 10:29:19
I created a separate cl and moved the GetEntrySize
| |
| 152 rv = CountEntries(cache_); | |
| 153 } | |
| 154 cache_ = NULL; | |
| 155 } | |
| 156 break; | |
| 157 } | |
| 158 case STATE_DONE: { | |
| 159 cache_ = NULL; | |
| 160 next_cache_state_ = STATE_NONE; | |
| 161 // Notify the UI thread that we are done. | |
| 162 BrowserThread::PostTask( | |
| 163 BrowserThread::UI, FROM_HERE, | |
| 164 base::Bind(&ConditionalCacheCountingHelper::Finished, | |
| 165 base::Unretained(this))); | |
| 166 return; | |
| 167 } | |
| 168 default: { | |
|
msramek
2016/12/15 15:58:51
Instead of default: NOTREACHED(), we could just re
dullweber
2016/12/16 16:41:11
Done.
| |
| 169 NOTREACHED() << "bad state"; | |
| 170 next_cache_state_ = STATE_NONE; // Stop looping. | |
| 171 return; | |
| 172 } | |
| 173 } | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 int ConditionalCacheCountingHelper::CountEntries(disk_cache::Backend* backend) { | |
| 178 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
| 179 iterator_ = backend->CreateIterator(); | |
| 180 current_entry_ = nullptr; | |
| 181 IterateOverEntries(net::OK); | |
| 182 return net::ERR_IO_PENDING; | |
| 183 } | |
| 184 | |
| 185 void ConditionalCacheCountingHelper::IterateOverEntries(int error) { | |
| 186 while (error != net::ERR_IO_PENDING) { | |
| 187 if (is_cancelled_) { | |
| 188 if (current_entry_) | |
| 189 current_entry_->Close(); | |
| 190 iterator_.reset(nullptr); | |
|
msramek
2016/12/15 15:58:50
nit: reset()
dullweber
2016/12/16 16:41:11
Done.
| |
| 191 DoCountCache(net::ERR_ABORTED); | |
| 192 return; | |
| 193 } | |
| 194 if (error == net::ERR_FAILED) { | |
| 195 // The iteration finished successfully or we can no longer iterate | |
| 196 // (e.g. the cache was destroyed). We cannot distinguish between the two, | |
| 197 // but we know that there is nothing more that we can do, so we return to | |
| 198 // the main calculation loop. | |
| 199 iterator_.reset(nullptr); | |
| 200 DoCountCache(net::OK); | |
| 201 return; | |
| 202 } | |
| 203 | |
| 204 if (current_entry_) { | |
| 205 if (current_entry_->GetLastUsed() >= begin_time_ && | |
| 206 current_entry_->GetLastUsed() < end_time_) { | |
| 207 calculation_result_ += current_entry_->GetEntrySize(); | |
| 208 } | |
| 209 current_entry_->Close(); | |
| 210 } | |
| 211 | |
| 212 error = iterator_->OpenNextEntry( | |
| 213 ¤t_entry_, | |
| 214 base::Bind(&ConditionalCacheCountingHelper::IterateOverEntries, | |
| 215 base::Unretained(this))); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 } // namespace browsing_data | |
| OLD | NEW |