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_(CacheState::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_ = CacheState::NONE; | |
91 DCHECK_EQ(CacheState::NONE, next_cache_state_); | |
92 DCHECK(main_context_getter_.get()); | |
93 DCHECK(media_context_getter_.get()); | |
94 | |
95 next_cache_state_ = CacheState::CREATE_MAIN; | |
96 DoCountCache(net::OK); | |
97 } | |
98 | |
99 // The expected state sequence is CacheState::NONE --> CacheState::CREATE_MAIN | |
100 // --> | |
msramek
2016/12/20 01:03:00
nit: Why the line break?
dullweber
2016/12/21 10:29:19
Oh, I guess changing to an enum class made the lin
| |
101 // CacheState::PROCESS_MAIN --> CacheState::CREATE_MEDIA --> | |
102 // CacheState::PROCESS_MEDIA --> | |
103 // CacheState::DONE. On error, we jump directly to CacheState::DONE. | |
104 void ConditionalCacheCountingHelper::DoCountCache(int rv) { | |
105 DCHECK_NE(CacheState::NONE, next_cache_state_); | |
106 while (rv != net::ERR_IO_PENDING && next_cache_state_ != CacheState::NONE) { | |
107 // On error, finish and return the error code. A valid result value might | |
108 // be of two types - either net::OK from the CREATE states, or the result | |
109 // of calculation from the PROCESS states. Since net::OK == 0, it is valid | |
110 // to simply add the value to the final calculation result. | |
111 if (rv < 0) { | |
112 calculation_result_ = rv; | |
113 next_cache_state_ = CacheState::DONE; | |
114 } else { | |
115 DCHECK_EQ(0, net::OK); | |
116 calculation_result_ += rv; | |
117 } | |
118 | |
119 switch (next_cache_state_) { | |
120 case CacheState::CREATE_MAIN: | |
121 case CacheState::CREATE_MEDIA: { | |
122 // Get a pointer to the cache. | |
123 net::URLRequestContextGetter* getter = | |
124 (next_cache_state_ == CacheState::CREATE_MAIN) | |
125 ? main_context_getter_.get() | |
126 : media_context_getter_.get(); | |
127 net::HttpCache* http_cache = getter->GetURLRequestContext() | |
128 ->http_transaction_factory() | |
129 ->GetCache(); | |
130 | |
131 next_cache_state_ = (next_cache_state_ == CacheState::CREATE_MAIN) | |
132 ? CacheState::COUNT_MAIN | |
133 : CacheState::COUNT_MEDIA; | |
134 | |
135 rv = http_cache->GetBackend( | |
136 &cache_, base::Bind(&ConditionalCacheCountingHelper::DoCountCache, | |
137 base::Unretained(this))); | |
138 break; | |
139 } | |
140 case CacheState::COUNT_MAIN: | |
141 case CacheState::COUNT_MEDIA: { | |
142 next_cache_state_ = (next_cache_state_ == CacheState::COUNT_MAIN) | |
143 ? CacheState::CREATE_MEDIA | |
144 : CacheState::DONE; | |
145 | |
146 // |cache_| can be null if it cannot be initialized. | |
147 if (cache_) { | |
148 if (begin_time_.is_null() && end_time_.is_max()) { | |
149 rv = cache_->CalculateSizeOfAllEntries( | |
150 base::Bind(&ConditionalCacheCountingHelper::DoCountCache, | |
151 base::Unretained(this))); | |
152 } else { | |
153 // TODO(dullweber): Implement faster counting for SimpleBackendImpl. | |
154 rv = CountEntries(cache_); | |
155 } | |
156 cache_ = NULL; | |
157 } | |
158 break; | |
159 } | |
160 case CacheState::DONE: { | |
161 cache_ = NULL; | |
162 next_cache_state_ = CacheState::NONE; | |
163 // Notify the UI thread that we are done. | |
164 BrowserThread::PostTask( | |
165 BrowserThread::UI, FROM_HERE, | |
166 base::Bind(&ConditionalCacheCountingHelper::Finished, | |
167 base::Unretained(this))); | |
168 return; | |
169 } | |
170 case CacheState::NONE: { | |
171 NOTREACHED() << "bad state"; | |
172 return; | |
173 } | |
174 } | |
175 } | |
176 } | |
177 | |
178 int ConditionalCacheCountingHelper::CountEntries(disk_cache::Backend* backend) { | |
179 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
180 iterator_ = backend->CreateIterator(); | |
181 current_entry_ = nullptr; | |
182 IterateOverEntries(net::OK); | |
183 return net::ERR_IO_PENDING; | |
184 } | |
185 | |
186 void ConditionalCacheCountingHelper::IterateOverEntries(int error) { | |
187 while (error != net::ERR_IO_PENDING) { | |
188 if (is_cancelled_) { | |
189 if (current_entry_) | |
190 current_entry_->Close(); | |
191 iterator_.reset(); | |
192 DoCountCache(net::ERR_ABORTED); | |
193 return; | |
194 } | |
195 if (error == net::ERR_FAILED) { | |
196 // The iteration finished successfully or we can no longer iterate | |
197 // (e.g. the cache was destroyed). We cannot distinguish between the two, | |
198 // but we know that there is nothing more that we can do, so we return to | |
199 // the main calculation loop. | |
200 iterator_.reset(); | |
201 DoCountCache(net::OK); | |
202 return; | |
203 } | |
204 | |
205 if (current_entry_) { | |
206 if (current_entry_->GetLastUsed() >= begin_time_ && | |
207 current_entry_->GetLastUsed() < end_time_) { | |
208 calculation_result_ += current_entry_->GetEntrySize(); | |
209 } | |
210 current_entry_->Close(); | |
211 } | |
212 | |
213 error = iterator_->OpenNextEntry( | |
214 ¤t_entry_, | |
215 base::Bind(&ConditionalCacheCountingHelper::IterateOverEntries, | |
216 base::Unretained(this))); | |
217 } | |
218 } | |
219 | |
220 } // namespace browsing_data | |
OLD | NEW |