OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2014 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 "net/http/disk_based_cert_cache.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/callback_helpers.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "net/base/io_buffer.h" | |
13 #include "net/base/net_errors.h" | |
14 | |
15 namespace net { | |
16 | |
17 //----------------------------------------------------------------------------- | |
Ryan Sleevi
2014/06/17 00:00:20
vertical whitespace comments apply
| |
18 | |
19 class DiskBasedCertCache::WriteWorker { | |
Ryan Sleevi
2014/06/17 00:00:20
Document
| |
20 public: | |
21 WriteWorker(disk_cache::Backend* backend, | |
22 std::string key, | |
23 const X509Certificate::OSCertHandle cert_handle, | |
24 base::Callback<void(const std::string&)> cleanup_callback, | |
25 SetCallback user_callback); | |
Ryan Sleevi
2014/06/17 00:00:20
const-refs
| |
26 | |
27 ~WriteWorker(); | |
28 | |
29 void Start(); | |
Ryan Sleevi
2014/06/17 00:00:20
Document
| |
30 | |
31 void AddCallback(SetCallback user_callback); | |
Ryan Sleevi
2014/06/17 00:00:19
const-ref
document
| |
32 | |
33 private: | |
34 // Types -------------------------------------------------------------------- | |
35 enum WriteState { | |
36 CREATE_OR_OPEN, | |
37 FINISH_CREATE_OR_OPEN, | |
38 START_WRITE, | |
39 FINISH_WRITE, | |
40 WRITE_NONE | |
41 }; | |
42 | |
43 // Methods ------------------------------------------------------------------ | |
44 | |
45 void OnIOComplete(int rv); | |
46 void DoLoop(int rv); | |
47 int DoCreateOrOpen(); | |
48 int DoFinishCreateOrOpen(int rv); | |
49 int DoStartWrite(); | |
50 int DoFinishWrite(int rv); | |
51 void CallCallbacks(const std::string& key); | |
52 | |
53 // Variables ---------------------------------------------------------------- | |
54 disk_cache::Backend* backend_; | |
55 const X509Certificate::OSCertHandle cert_handle_; | |
56 std::string key_; | |
57 | |
58 disk_cache::Entry* entry_; | |
59 WriteState state_; | |
60 bool create_failed_; | |
61 scoped_refptr<IOBuffer> buffer; | |
62 | |
63 base::Callback<void(const std::string&)> cleanup_callback_; | |
64 std::vector<SetCallback> user_callbacks_; | |
65 CompletionCallback io_callback_; | |
66 | |
67 base::WeakPtrFactory<WriteWorker> weak_factory_; | |
68 }; | |
69 | |
70 DiskBasedCertCache::WriteWorker::WriteWorker( | |
71 disk_cache::Backend* backend, | |
72 std::string key, | |
73 X509Certificate::OSCertHandle cert_handle, | |
74 base::Callback<void(const std::string&)> cleanup_callback, | |
75 SetCallback user_callback) | |
76 : backend_(backend), | |
77 cert_handle_(cert_handle), | |
78 key_(key), | |
79 entry_(NULL), | |
80 state_(CREATE_OR_OPEN), | |
81 create_failed_(false), | |
82 cleanup_callback_(cleanup_callback), | |
83 weak_factory_(this) { | |
84 io_callback_ = | |
85 base::Bind(&WriteWorker::OnIOComplete, weak_factory_.GetWeakPtr()); | |
86 AddCallback(user_callback); | |
87 } | |
88 | |
89 void DiskBasedCertCache::WriteWorker::Start() { | |
90 DoLoop(OK); | |
91 } | |
92 | |
93 void DiskBasedCertCache::WriteWorker::AddCallback(SetCallback user_callback) { | |
94 user_callbacks_.push_back(user_callback); | |
95 } | |
96 | |
97 void DiskBasedCertCache::WriteWorker::OnIOComplete(int rv) { | |
98 DoLoop(rv); | |
99 } | |
100 | |
101 void DiskBasedCertCache::WriteWorker::DoLoop(int rv) { | |
102 do { | |
103 switch (state_) { | |
104 case CREATE_OR_OPEN: | |
105 rv = DoCreateOrOpen(); | |
106 break; | |
107 case FINISH_CREATE_OR_OPEN: | |
108 rv = DoFinishCreateOrOpen(rv); | |
109 break; | |
110 case START_WRITE: | |
111 rv = DoStartWrite(); | |
112 break; | |
113 case FINISH_WRITE: | |
114 rv = DoFinishWrite(rv); | |
115 break; | |
116 case WRITE_NONE: | |
117 break; | |
118 } | |
119 } while (rv != ERR_IO_PENDING && state_ != WRITE_NONE); | |
120 | |
121 if (state_ == WRITE_NONE) { | |
Ryan Sleevi
2014/06/17 00:00:19
STYLE: We prefer error-handling/short circuiting a
| |
122 if (entry_) | |
123 entry_->Close(); | |
124 base::ResetAndReturn(&cleanup_callback_).Run(key_); | |
Ryan Sleevi
2014/06/17 00:00:20
DANGER: We almost always try to avoid calling call
| |
125 } | |
126 } | |
127 | |
128 int DiskBasedCertCache::WriteWorker::DoCreateOrOpen() { | |
129 DCHECK(entry_ == NULL); | |
Ryan Sleevi
2014/06/17 00:00:20
For == NULL dchecks, just do
DCHECK(entry_)
| |
130 | |
131 state_ = FINISH_CREATE_OR_OPEN; | |
132 | |
133 if (create_failed_) { | |
134 return backend_->OpenEntry(key_, &entry_, io_callback_); | |
135 } | |
Ryan Sleevi
2014/06/17 00:00:19
No braces on simple { }
| |
136 | |
137 return backend_->CreateEntry(key_, &entry_, io_callback_); | |
138 } | |
139 | |
140 int DiskBasedCertCache::WriteWorker::DoFinishCreateOrOpen(int rv) { | |
141 // ERR_FAILED implies create entry failed, and we should try opening instead. | |
142 //!create_failed is checked to make sure we only try to open once. | |
Ryan Sleevi
2014/06/17 00:00:19
When possible, it's better to avoid pronouns (like
| |
143 if (rv == ERR_FAILED && !create_failed_) { | |
144 create_failed_ = true; | |
145 state_ = CREATE_OR_OPEN; | |
146 return OK; | |
147 } else if (rv < 0) { | |
148 CallCallbacks(""); | |
149 state_ = WRITE_NONE; | |
150 return ERR_FAILED; | |
151 } | |
152 | |
153 state_ = START_WRITE; | |
154 return OK; | |
155 } | |
156 | |
157 int DiskBasedCertCache::WriteWorker::DoStartWrite() { | |
158 std::string write_data; | |
159 bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data); | |
160 | |
161 if (!encoded) { | |
162 CallCallbacks(NULL); | |
163 state_ = WRITE_NONE; | |
164 return ERR_FAILED; | |
165 } | |
166 | |
167 buffer = new IOBuffer(write_data.size()); | |
168 memcpy(buffer->data(), write_data.data(), write_data.size()); | |
169 | |
170 state_ = FINISH_WRITE; | |
171 | |
172 return entry_->WriteData(0 /* index */, | |
173 0 /* offset */, | |
174 buffer, | |
175 write_data.size(), | |
176 io_callback_, | |
177 true /* truncate */); | |
178 } | |
179 | |
180 int DiskBasedCertCache::WriteWorker::DoFinishWrite(int rv) { | |
181 if (rv < 0) { | |
182 CallCallbacks(""); | |
Ryan Sleevi
2014/06/17 00:00:20
use std::string() for empty strings, rather than "
| |
183 state_ = WRITE_NONE; | |
184 return ERR_FAILED; | |
185 } | |
186 | |
187 state_ = WRITE_NONE; | |
188 | |
189 CallCallbacks(key_); | |
190 return OK; | |
191 } | |
192 | |
193 void DiskBasedCertCache::WriteWorker::CallCallbacks(const std::string& key) { | |
194 for (std::vector<SetCallback>::iterator it = user_callbacks_.begin(); | |
195 it != user_callbacks_.end(); | |
196 it++) { | |
197 if (!it->is_null()) | |
198 base::ResetAndReturn(&(*it)).Run(key_); | |
Ryan Sleevi
2014/06/17 00:00:20
1) When would it->is_null be true? Seems like they
| |
199 } | |
200 } | |
201 | |
202 DiskBasedCertCache::WriteWorker::~WriteWorker() { | |
203 weak_factory_.InvalidateWeakPtrs(); | |
Ryan Sleevi
2014/06/17 00:00:19
You don't need to do this explicitly. WeakPtrFacto
| |
204 } | |
205 | |
206 //--------------------------------------------------------------------------- | |
207 | |
208 class DiskBasedCertCache::ReadWorker { | |
209 public: | |
210 ReadWorker(disk_cache::Backend* backend, | |
211 std::string key, | |
212 base::Callback<void(const std::string&)> cleanup_callback, | |
213 GetCallback user_callback); | |
214 | |
215 ~ReadWorker(); | |
216 | |
217 void Start(); | |
218 | |
219 void AddCallback(GetCallback user_callback); | |
Ryan Sleevi
2014/06/17 00:00:19
Same comments regarding const-refs, comments, etc
| |
220 | |
221 private: | |
222 // Types -------------------------------------------------------------------- | |
Ryan Sleevi
2014/06/17 00:00:20
Same comments regarding vertical whitespace (eg: d
| |
223 enum ReadState { OPEN, START_READ, FINISH_READ, READ_NONE }; | |
224 | |
225 // Methods ------------------------------------------------------------------ | |
226 void OnIOComplete(int rv); | |
227 void DoLoop(int rv); | |
228 int DoOpen(); | |
229 int DoStartRead(int rv); | |
230 int DoFinishRead(int rv); | |
231 | |
232 void CallCallbacks(X509Certificate::OSCertHandle cert_handle); | |
233 | |
234 // Variables ---------------------------------------------------------------- | |
235 disk_cache::Backend* backend_; | |
236 | |
237 std::string key_; | |
238 disk_cache::Entry* entry_; | |
239 ReadState state_; | |
240 int entry_size_; | |
241 scoped_refptr<IOBuffer> buffer; | |
242 | |
243 base::Callback<void(const std::string&)> cleanup_callback_; | |
244 std::vector<GetCallback> user_callbacks_; | |
245 CompletionCallback io_callback_; | |
246 base::WeakPtrFactory<ReadWorker> weak_factory_; | |
247 }; | |
248 | |
249 DiskBasedCertCache::ReadWorker::ReadWorker( | |
250 disk_cache::Backend* backend, | |
251 std::string key, | |
252 base::Callback<void(const std::string&)> cleanup_callback, | |
253 GetCallback user_callback) | |
254 : backend_(backend), | |
255 key_(key), | |
256 entry_(NULL), | |
257 state_(OPEN), | |
258 entry_size_(0), | |
259 cleanup_callback_(cleanup_callback), | |
260 weak_factory_(this) { | |
261 io_callback_ = | |
262 base::Bind(&ReadWorker::OnIOComplete, weak_factory_.GetWeakPtr()); | |
263 AddCallback(user_callback); | |
264 } | |
265 | |
266 void DiskBasedCertCache::ReadWorker::Start() { | |
267 DoLoop(OK); | |
268 } | |
269 | |
270 void DiskBasedCertCache::ReadWorker::AddCallback(GetCallback user_callback) { | |
271 user_callbacks_.push_back(user_callback); | |
272 } | |
273 | |
274 void DiskBasedCertCache::ReadWorker::OnIOComplete(int rv) { | |
275 DoLoop(rv); | |
276 } | |
277 | |
278 void DiskBasedCertCache::ReadWorker::DoLoop(int rv) { | |
279 do { | |
280 switch (state_) { | |
281 case OPEN: | |
282 rv = DoOpen(); | |
283 break; | |
284 case START_READ: | |
285 rv = DoStartRead(rv); | |
286 break; | |
287 case FINISH_READ: | |
288 rv = DoFinishRead(rv); | |
289 break; | |
290 case READ_NONE: | |
291 break; | |
292 } | |
293 } while (rv != ERR_IO_PENDING && state_ != READ_NONE); | |
294 | |
295 if (state_ == READ_NONE) { | |
296 if (entry_) | |
297 entry_->Close(); | |
298 base::ResetAndReturn(&cleanup_callback_).Run(key_); | |
Ryan Sleevi
2014/06/17 00:00:19
Same comments re: entry functions calling callback
| |
299 } | |
300 } | |
301 | |
302 int DiskBasedCertCache::ReadWorker::DoOpen() { | |
303 state_ = START_READ; | |
304 | |
305 return backend_->OpenEntry(key_, &entry_, io_callback_); | |
306 } | |
307 | |
308 int DiskBasedCertCache::ReadWorker::DoStartRead(int rv) { | |
309 if (rv < 0) { | |
310 CallCallbacks(NULL); | |
311 state_ = READ_NONE; | |
312 return ERR_FAILED; | |
313 } | |
314 | |
315 entry_size_ = entry_->GetDataSize(0 /* index */); | |
316 | |
317 state_ = FINISH_READ; | |
318 | |
319 buffer = new IOBuffer(entry_size_); | |
Ryan Sleevi
2014/06/17 00:00:20
Lots of unnecessary vertical whitespace here (and
| |
320 | |
321 return entry_->ReadData( | |
322 0 /* index */, 0 /* offset */, buffer, entry_size_, io_callback_); | |
323 } | |
324 | |
325 int DiskBasedCertCache::ReadWorker::DoFinishRead(int rv) { | |
326 if (rv < 0) { | |
327 CallCallbacks(NULL); | |
328 state_ = READ_NONE; | |
329 return ERR_FAILED; | |
330 } | |
331 | |
332 state_ = READ_NONE; | |
333 | |
334 X509Certificate::OSCertHandle retrieved_cert_handle = | |
335 X509Certificate::CreateOSCertHandleFromBytes(buffer->data(), entry_size_); | |
336 | |
337 CHECK(retrieved_cert_handle); | |
338 CallCallbacks(retrieved_cert_handle); | |
339 X509Certificate::FreeOSCertHandle(retrieved_cert_handle); | |
340 return OK; | |
341 } | |
342 | |
343 void DiskBasedCertCache::ReadWorker::CallCallbacks( | |
344 X509Certificate::OSCertHandle cert_handle) { | |
345 for (std::vector<GetCallback>::iterator it = user_callbacks_.begin(); | |
346 it != user_callbacks_.end(); | |
347 it++) { | |
348 if (!it->is_null()) | |
349 base::ResetAndReturn(&(*it)).Run(cert_handle); | |
350 } | |
351 } | |
352 | |
353 DiskBasedCertCache::ReadWorker::~ReadWorker() { | |
354 weak_factory_.InvalidateWeakPtrs(); | |
355 } | |
356 | |
357 //----------------------------------------------------------------------------- | |
358 | |
359 DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend) | |
360 : backend_(backend), weak_factory_(this) { | |
Ryan Sleevi
2014/06/17 00:00:19
Run git-cl format, and I believe it will restructu
| |
361 DCHECK(backend_); | |
362 write_io_callback_ = base::Bind(&DiskBasedCertCache::FinishedWriteOperation, | |
363 weak_factory_.GetWeakPtr()); | |
364 read_io_callback_ = base::Bind(&DiskBasedCertCache::FinishedReadOperation, | |
365 weak_factory_.GetWeakPtr()); | |
Ryan Sleevi
2014/06/17 00:00:20
You can create these two callbacks in the ctor ini
| |
366 } | |
367 | |
368 DiskBasedCertCache::~DiskBasedCertCache() { | |
369 weak_factory_.InvalidateWeakPtrs(); | |
370 for (WriteWorkerMap::iterator it = write_worker_map_.begin(); | |
371 it != write_worker_map_.end(); | |
372 it++) { | |
373 delete it->second; | |
374 } | |
Ryan Sleevi
2014/06/17 00:00:19
You can use base/stl_util.h
STLDeleteContainerPai
| |
375 for (ReadWorkerMap::iterator it = read_worker_map_.begin(); | |
376 it != read_worker_map_.end(); | |
377 it++) { | |
378 delete it->second; | |
379 } | |
380 } | |
381 | |
382 void DiskBasedCertCache::Get( | |
383 std::string& key, | |
384 base::Callback<void(X509Certificate::OSCertHandle cert_handle)> cb) { | |
385 CHECK(!key.empty()); | |
Ryan Sleevi
2014/06/17 00:00:19
Use DCHECK() when defining preconditions/post-cond
| |
386 | |
387 ReadWorkerMap::iterator it = read_worker_map_.find(key); | |
388 | |
389 if (it == read_worker_map_.end()) { | |
390 read_worker_map_[key] = | |
391 new ReadWorker(backend_, key, read_io_callback_, cb); | |
392 read_worker_map_[key]->Start(); | |
Ryan Sleevi
2014/06/17 00:00:19
Avoid duplicate accesses to [key], when possible.
| |
393 } else { | |
394 read_worker_map_[key]->AddCallback(cb); | |
Ryan Sleevi
2014/06/17 00:00:20
Here, you'd it->second->AddCallback(cb);
| |
395 } | |
396 } | |
397 | |
398 void DiskBasedCertCache::Set(const X509Certificate::OSCertHandle cert_handle, | |
399 base::Callback<void(const std::string&)> cb) { | |
400 CHECK(!cb.is_null()); | |
401 CHECK(cert_handle); | |
Ryan Sleevi
2014/06/17 00:00:20
ditto comments re: DCHECK
| |
402 std::string key = Key(cert_handle); | |
403 | |
404 WriteWorkerMap::iterator it = write_worker_map_.find(key); | |
405 | |
406 if (it == write_worker_map_.end()) { | |
407 write_worker_map_[key] = | |
408 new WriteWorker(backend_, key, cert_handle, write_io_callback_, cb); | |
409 write_worker_map_[key]->Start(); | |
410 } else { | |
411 write_worker_map_[key]->AddCallback(cb); | |
412 } | |
413 } | |
414 | |
415 std::string DiskBasedCertCache::Key( | |
416 const X509Certificate::OSCertHandle cert_handle) const { | |
417 SHA1HashValue fingerprint = | |
418 X509Certificate::CalculateFingerprint(cert_handle); | |
419 | |
420 return "cert:" + | |
421 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); | |
422 } | |
423 | |
424 void DiskBasedCertCache::FinishedWriteOperation(const std::string& key) { | |
425 WriteWorkerMap::iterator it = write_worker_map_.find(key); | |
426 WriteWorker* temp = it->second; | |
427 write_worker_map_.erase(it); | |
428 delete temp; | |
429 } | |
430 | |
431 void DiskBasedCertCache::FinishedReadOperation(const std::string& key) { | |
432 ReadWorkerMap::iterator it = read_worker_map_.find(key); | |
433 ReadWorker* temp = it->second; | |
434 read_worker_map_.erase(it); | |
435 delete temp; | |
436 } | |
437 | |
438 } // namespace net | |
OLD | NEW |