Chromium Code Reviews| 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 |