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 <list> | |
|
Ryan Sleevi
2014/06/18 22:16:03
Curious: Was there a particular reason for choosin
brandonsalmon
2014/06/19 21:32:31
In this circumstance, I could not see any particul
| |
| 8 | |
| 9 #include "base/callback_helpers.h" | |
| 10 #include "base/memory/ref_counted.h" | |
| 11 #include "base/stl_util.h" | |
| 12 #include "base/strings/string_number_conversions.h" | |
| 13 #include "net/base/io_buffer.h" | |
| 14 #include "net/base/net_errors.h" | |
| 15 #include "net/disk_cache/disk_cache.h" | |
| 16 | |
| 17 namespace net { | |
| 18 | |
| 19 // WriteWorkers represent pending set jobs in the DiskBasedCertCache. Each | |
| 20 // certificate requested to be cached is assigned a Writeworker on a one-to-one | |
| 21 // basis. The same certificate should not have multiple WriteWorkers at the same | |
| 22 // time, instead, add a user_callback_ to the existing WriteWorker. | |
|
Ryan Sleevi
2014/06/18 22:16:04
comment nit:
// time, instead, add a user_callback
| |
| 23 class DiskBasedCertCache::WriteWorker { | |
| 24 public: | |
| 25 // |backend| is a pointer to the initialized disk_cache::backend stored in | |
| 26 // DiskBasedCertCache. |key| is the key corresponding to this certificate | |
| 27 // to be used in caching. |cert_handle| is the certificate to be stored. | |
| 28 // |cleanup_callback| is a callback to the function that will | |
| 29 // delete this worker. |user_callback| is a callback to the user | |
| 30 // to signify that the certificate has been correctly stored, or that the | |
| 31 // operation failed. | |
|
Ryan Sleevi
2014/06/18 22:16:04
comment style: we generally don't note types in pr
| |
| 32 WriteWorker(disk_cache::Backend* backend, | |
| 33 const std::string& key, | |
| 34 const X509Certificate::OSCertHandle cert_handle, | |
| 35 const base::Callback<void(void)>& cleanup_callback, | |
| 36 const SetCallback& user_callback); | |
|
Ryan Sleevi
2014/06/18 22:16:03
It seems like, for consistency, that the caller sh
| |
| 37 | |
| 38 ~WriteWorker(); | |
| 39 | |
| 40 // Begin the do-loop for this WriteWorker (will call all user_callbacks_ on | |
| 41 // completion). | |
|
Ryan Sleevi
2014/06/18 22:16:03
Comment rewording:
// Writes the given certificat
| |
| 42 void Start(); | |
| 43 | |
| 44 // Add a callback to this worker. Should be used when |cert_handle_| is | |
| 45 // requested to be stored in the cache multiple times within the lifetime | |
| 46 // of this worker. | |
|
Ryan Sleevi
2014/06/18 22:16:03
Comment rewording: We try to avoid descriptions of
| |
| 47 void AddCallback(const SetCallback& user_callback); | |
| 48 | |
| 49 private: | |
| 50 enum WriteState { | |
| 51 CREATE_OR_OPEN, | |
| 52 FINISH_CREATE_OR_OPEN, | |
| 53 START_WRITE, | |
| 54 FINISH_WRITE, | |
| 55 WRITE_NONE | |
| 56 }; | |
| 57 | |
| 58 void OnIOComplete(int rv); | |
| 59 void DoLoop(int rv); | |
| 60 int DoCreateOrOpen(); | |
| 61 int DoFinishCreateOrOpen(int rv); | |
| 62 int DoStartWrite(); | |
| 63 int DoFinishWrite(int rv); | |
| 64 | |
| 65 // CallCallbacks is used to call all user callbacks (i.e. callbacks that were | |
| 66 // given by the user to the DiskBasedCertCache when calling Set). | |
|
Ryan Sleevi
2014/06/18 22:16:03
// Invokes all of the |user_callbacks_|
| |
| 67 void CallCallbacks(const std::string& key); | |
|
Ryan Sleevi
2014/06/18 22:16:03
Why do you pass |key|, when you have |key_| as a m
brandonsalmon
2014/06/19 21:32:31
I did this so I could use CallCallbacks(std::strin
| |
| 68 | |
| 69 disk_cache::Backend* backend_; | |
| 70 const X509Certificate::OSCertHandle cert_handle_; | |
| 71 std::string key_; | |
| 72 | |
| 73 disk_cache::Entry* entry_; | |
| 74 WriteState state_; | |
| 75 bool create_failed_; | |
| 76 scoped_refptr<IOBuffer> buffer; | |
| 77 | |
| 78 base::Callback<void(void)> cleanup_callback_; | |
|
Ryan Sleevi
2014/06/18 22:16:03
the name for this is "base::Closure" - avoids the
| |
| 79 std::list<SetCallback> user_callbacks_; | |
| 80 CompletionCallback io_callback_; /* used to access the backend */ | |
|
Ryan Sleevi
2014/06/18 22:16:03
Delete this comment; Among other things, io_callba
| |
| 81 | |
| 82 base::WeakPtrFactory<WriteWorker> weak_factory_; | |
| 83 }; | |
| 84 | |
| 85 // ReadWorkers represent pending get jobs in the DiskBasedCertCache. Each | |
|
Ryan Sleevi
2014/06/18 22:16:03
s/get/Get/
| |
| 86 // certificate requested to be retrieved from the cache is assigned a ReadWorker | |
| 87 // on a one-to-one basis. The same |key| should not have multiple ReadWorkers | |
| 88 // at the same time, instead, call AddCallback to add a user_callback_ to | |
| 89 // the the existing ReadWorker. | |
|
Ryan Sleevi
2014/06/18 22:16:04
Similar comment cleanup as above.
| |
| 90 class DiskBasedCertCache::ReadWorker { | |
| 91 public: | |
| 92 // |backend| is a pointer to the initialized disk_cache::backend stored in | |
| 93 // DiskBasedCertCache. |key| is the key corresponding to this certificate | |
| 94 // to be used in caching. |cleanup_callback| is a callback to the function | |
| 95 // that will delete this worker. |user_callback| is a callback to the user | |
| 96 // to signify that the certificate has been correctly stored, or that the | |
| 97 // operation failed. | |
| 98 ReadWorker(disk_cache::Backend* backend, | |
|
Ryan Sleevi
2014/06/18 22:16:03
Same comment comments as above
| |
| 99 const std::string& key, | |
| 100 const base::Callback<void(void)>& cleanup_callback, | |
| 101 const GetCallback& user_callback); | |
|
Ryan Sleevi
2014/06/18 22:16:03
ditto AddCallback
| |
| 102 | |
| 103 ~ReadWorker(); | |
| 104 | |
| 105 // Begin the do-loop for this ReadWorker (will call all user_callbacks_ on | |
| 106 // completion). | |
| 107 void Start(); | |
| 108 | |
| 109 // Add a callback to this worker. Should be used when |key_| is | |
| 110 // requested to be retrieved from the cache multiple times within lifetime | |
| 111 // of this worker. | |
| 112 void AddCallback(const GetCallback& user_callback); | |
| 113 | |
| 114 private: | |
| 115 enum ReadState { OPEN, START_READ, FINISH_READ, READ_NONE }; | |
| 116 | |
| 117 void OnIOComplete(int rv); | |
| 118 void DoLoop(int rv); | |
| 119 int DoOpen(); | |
| 120 int DoStartRead(int rv); | |
| 121 int DoFinishRead(int rv); | |
| 122 | |
| 123 // CallCallbacks is used to call all user callbacks (i.e. callbacks that were | |
| 124 // given by the user to the DiskBasedCertCache when calling Get). | |
| 125 void CallCallbacks(X509Certificate::OSCertHandle cert_handle); | |
| 126 | |
| 127 disk_cache::Backend* backend_; | |
| 128 | |
| 129 std::string key_; | |
| 130 disk_cache::Entry* entry_; | |
| 131 ReadState state_; | |
| 132 int entry_size_; | |
| 133 scoped_refptr<IOBuffer> buffer; | |
| 134 | |
| 135 base::Callback<void(void)> cleanup_callback_; | |
| 136 std::list<GetCallback> user_callbacks_; | |
| 137 CompletionCallback io_callback_; | |
| 138 base::WeakPtrFactory<ReadWorker> weak_factory_; | |
| 139 }; | |
| 140 | |
| 141 std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) { | |
| 142 SHA1HashValue fingerprint = | |
| 143 X509Certificate::CalculateFingerprint(cert_handle); | |
| 144 | |
| 145 return "cert:" + | |
| 146 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); | |
| 147 } | |
|
Ryan Sleevi
2014/06/18 22:16:03
This function should be between lines 18/19 in an
| |
| 148 | |
| 149 DiskBasedCertCache::WriteWorker::WriteWorker( | |
| 150 disk_cache::Backend* backend, | |
| 151 const std::string& key, | |
| 152 X509Certificate::OSCertHandle cert_handle, | |
| 153 const base::Callback<void(void)>& cleanup_callback, | |
| 154 const SetCallback& user_callback) | |
| 155 : backend_(backend), | |
| 156 cert_handle_(cert_handle), | |
| 157 key_(key), | |
| 158 entry_(NULL), | |
| 159 state_(CREATE_OR_OPEN), | |
| 160 create_failed_(false), | |
| 161 cleanup_callback_(cleanup_callback), | |
| 162 weak_factory_(this) { | |
| 163 io_callback_ = | |
| 164 base::Bind(&WriteWorker::OnIOComplete, weak_factory_.GetWeakPtr()); | |
| 165 AddCallback(user_callback); | |
| 166 } | |
| 167 | |
| 168 void DiskBasedCertCache::WriteWorker::Start() { | |
| 169 DoLoop(OK); | |
| 170 | |
| 171 if (state_ == WRITE_NONE) { | |
|
Ryan Sleevi
2014/06/18 22:16:03
if (state_ != WRITE_NONE)
return;
if (entry_)
| |
| 172 if (entry_) | |
| 173 entry_->Close(); | |
| 174 base::ResetAndReturn(&cleanup_callback_).Run(); | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 void DiskBasedCertCache::WriteWorker::AddCallback( | |
| 179 const SetCallback& user_callback) { | |
| 180 user_callbacks_.push_back(user_callback); | |
| 181 } | |
| 182 | |
| 183 void DiskBasedCertCache::WriteWorker::OnIOComplete(int rv) { | |
| 184 DoLoop(rv); | |
| 185 | |
| 186 if (state_ == WRITE_NONE) { | |
| 187 if (entry_) | |
| 188 entry_->Close(); | |
| 189 base::ResetAndReturn(&cleanup_callback_).Run(); | |
| 190 } | |
|
Ryan Sleevi
2014/06/18 22:16:03
Ditto cleanup as above.
| |
| 191 } | |
| 192 | |
| 193 void DiskBasedCertCache::WriteWorker::DoLoop(int rv) { | |
| 194 do { | |
| 195 switch (state_) { | |
| 196 case CREATE_OR_OPEN: | |
| 197 rv = DoCreateOrOpen(); | |
| 198 break; | |
| 199 case FINISH_CREATE_OR_OPEN: | |
| 200 rv = DoFinishCreateOrOpen(rv); | |
| 201 break; | |
| 202 case START_WRITE: | |
| 203 rv = DoStartWrite(); | |
| 204 break; | |
| 205 case FINISH_WRITE: | |
| 206 rv = DoFinishWrite(rv); | |
| 207 break; | |
| 208 case WRITE_NONE: | |
| 209 break; | |
| 210 } | |
| 211 } while (rv != ERR_IO_PENDING && state_ != WRITE_NONE); | |
| 212 } | |
| 213 | |
| 214 int DiskBasedCertCache::WriteWorker::DoCreateOrOpen() { | |
| 215 state_ = FINISH_CREATE_OR_OPEN; | |
| 216 | |
| 217 if (create_failed_) | |
| 218 return backend_->OpenEntry(key_, &entry_, io_callback_); | |
| 219 | |
| 220 return backend_->CreateEntry(key_, &entry_, io_callback_); | |
| 221 } | |
| 222 | |
| 223 int DiskBasedCertCache::WriteWorker::DoFinishCreateOrOpen(int rv) { | |
| 224 // ERR_FAILED implies create entry failed. In order to avoid trying | |
| 225 // to open the entry multiple times, the flag create_failed_ is set and | |
| 226 // checked. | |
| 227 if (rv == ERR_FAILED && !create_failed_) { | |
|
Ryan Sleevi
2014/06/18 22:16:03
Why combine CREATE_OR_OPEN into one state?
It see
| |
| 228 create_failed_ = true; | |
| 229 state_ = CREATE_OR_OPEN; | |
| 230 return OK; | |
| 231 } else if (rv < 0) { | |
| 232 CallCallbacks(std::string()); | |
|
Ryan Sleevi
2014/06/18 22:16:03
DANGER!
So the same comments I made on the previo
| |
| 233 state_ = WRITE_NONE; | |
| 234 return ERR_FAILED; | |
| 235 } | |
| 236 | |
| 237 state_ = START_WRITE; | |
| 238 return OK; | |
| 239 } | |
| 240 | |
| 241 int DiskBasedCertCache::WriteWorker::DoStartWrite() { | |
| 242 std::string write_data; | |
| 243 bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data); | |
| 244 | |
| 245 if (!encoded) { | |
| 246 CallCallbacks(std::string()); | |
| 247 state_ = WRITE_NONE; | |
| 248 return ERR_FAILED; | |
| 249 } | |
|
Ryan Sleevi
2014/06/18 22:16:04
Let's chat in person how to structure these 'failu
| |
| 250 | |
| 251 buffer = new IOBuffer(write_data.size()); | |
| 252 memcpy(buffer->data(), write_data.data(), write_data.size()); | |
| 253 | |
| 254 state_ = FINISH_WRITE; | |
| 255 | |
| 256 return entry_->WriteData(0 /* index */, | |
| 257 0 /* offset */, | |
| 258 buffer, | |
| 259 write_data.size(), | |
| 260 io_callback_, | |
| 261 true /* truncate */); | |
| 262 } | |
| 263 | |
| 264 int DiskBasedCertCache::WriteWorker::DoFinishWrite(int rv) { | |
| 265 if (rv < 0) { | |
| 266 CallCallbacks(std::string()); | |
| 267 state_ = WRITE_NONE; | |
| 268 return ERR_FAILED; | |
| 269 } | |
| 270 | |
| 271 state_ = WRITE_NONE; | |
| 272 | |
| 273 CallCallbacks(key_); | |
| 274 return OK; | |
| 275 } | |
| 276 | |
| 277 void DiskBasedCertCache::WriteWorker::CallCallbacks(const std::string& key) { | |
| 278 for (std::list<SetCallback>::iterator it = user_callbacks_.begin(); | |
| 279 it != user_callbacks_.end(); | |
| 280 it++) { | |
| 281 base::ResetAndReturn(&(*it)).Run(key_); | |
|
Ryan Sleevi
2014/06/18 22:16:03
Same danger regarding the risk of the following:
| |
| 282 } | |
| 283 } | |
| 284 | |
| 285 DiskBasedCertCache::WriteWorker::~WriteWorker() { | |
| 286 } | |
| 287 | |
| 288 DiskBasedCertCache::ReadWorker::ReadWorker( | |
| 289 disk_cache::Backend* backend, | |
| 290 const std::string& key, | |
| 291 const base::Callback<void(void)>& cleanup_callback, | |
| 292 const GetCallback& user_callback) | |
| 293 : backend_(backend), | |
| 294 key_(key), | |
| 295 entry_(NULL), | |
| 296 state_(OPEN), | |
| 297 entry_size_(0), | |
| 298 cleanup_callback_(cleanup_callback), | |
| 299 weak_factory_(this) { | |
| 300 io_callback_ = | |
| 301 base::Bind(&ReadWorker::OnIOComplete, weak_factory_.GetWeakPtr()); | |
| 302 AddCallback(user_callback); | |
| 303 } | |
| 304 | |
| 305 void DiskBasedCertCache::ReadWorker::Start() { | |
| 306 DoLoop(OK); | |
| 307 | |
| 308 if (state_ == READ_NONE) { | |
| 309 if (entry_) | |
| 310 entry_->Close(); | |
| 311 base::ResetAndReturn(&cleanup_callback_).Run(); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 void DiskBasedCertCache::ReadWorker::AddCallback( | |
| 316 const GetCallback& user_callback) { | |
| 317 user_callbacks_.push_back(user_callback); | |
| 318 } | |
| 319 | |
| 320 void DiskBasedCertCache::ReadWorker::OnIOComplete(int rv) { | |
| 321 DoLoop(rv); | |
| 322 | |
| 323 if (state_ == READ_NONE) { | |
| 324 if (entry_) | |
| 325 entry_->Close(); | |
| 326 base::ResetAndReturn(&cleanup_callback_).Run(); | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 void DiskBasedCertCache::ReadWorker::DoLoop(int rv) { | |
| 331 do { | |
| 332 switch (state_) { | |
| 333 case OPEN: | |
| 334 rv = DoOpen(); | |
| 335 break; | |
| 336 case START_READ: | |
| 337 rv = DoStartRead(rv); | |
| 338 break; | |
| 339 case FINISH_READ: | |
| 340 rv = DoFinishRead(rv); | |
| 341 break; | |
| 342 case READ_NONE: | |
| 343 break; | |
| 344 } | |
| 345 } while (rv != ERR_IO_PENDING && state_ != READ_NONE); | |
| 346 } | |
| 347 | |
| 348 int DiskBasedCertCache::ReadWorker::DoOpen() { | |
| 349 state_ = START_READ; | |
| 350 return backend_->OpenEntry(key_, &entry_, io_callback_); | |
| 351 } | |
| 352 | |
| 353 int DiskBasedCertCache::ReadWorker::DoStartRead(int rv) { | |
| 354 if (rv < 0) { | |
| 355 CallCallbacks(NULL); | |
| 356 state_ = READ_NONE; | |
| 357 return ERR_FAILED; | |
| 358 } | |
| 359 | |
| 360 entry_size_ = entry_->GetDataSize(0 /* index */); | |
| 361 state_ = FINISH_READ; | |
| 362 buffer = new IOBuffer(entry_size_); | |
| 363 return entry_->ReadData( | |
| 364 0 /* index */, 0 /* offset */, buffer, entry_size_, io_callback_); | |
| 365 } | |
| 366 | |
| 367 int DiskBasedCertCache::ReadWorker::DoFinishRead(int rv) { | |
| 368 if (rv < 0) { | |
| 369 CallCallbacks(NULL); | |
| 370 state_ = READ_NONE; | |
| 371 return ERR_FAILED; | |
| 372 } | |
| 373 | |
| 374 state_ = READ_NONE; | |
| 375 | |
| 376 X509Certificate::OSCertHandle retrieved_cert_handle = | |
| 377 X509Certificate::CreateOSCertHandleFromBytes(buffer->data(), entry_size_); | |
| 378 | |
| 379 DCHECK(retrieved_cert_handle); | |
| 380 | |
| 381 CallCallbacks(retrieved_cert_handle); | |
| 382 X509Certificate::FreeOSCertHandle(retrieved_cert_handle); | |
| 383 return OK; | |
| 384 } | |
| 385 | |
| 386 void DiskBasedCertCache::ReadWorker::CallCallbacks( | |
| 387 X509Certificate::OSCertHandle cert_handle) { | |
| 388 for (std::list<GetCallback>::iterator it = user_callbacks_.begin(); | |
| 389 it != user_callbacks_.end(); | |
| 390 it++) { | |
| 391 base::ResetAndReturn(&(*it)).Run(cert_handle); | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 DiskBasedCertCache::ReadWorker::~ReadWorker() { | |
| 396 } | |
| 397 | |
| 398 DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend) | |
| 399 : backend_(backend), weak_factory_(this) { | |
| 400 DCHECK(backend_); | |
| 401 } | |
| 402 | |
| 403 DiskBasedCertCache::~DiskBasedCertCache() { | |
| 404 STLDeleteContainerPairSecondPointers(read_worker_map_.begin(), | |
| 405 read_worker_map_.end()); | |
| 406 STLDeleteContainerPairSecondPointers(write_worker_map_.begin(), | |
| 407 write_worker_map_.end()); | |
| 408 } | |
| 409 | |
| 410 void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) { | |
| 411 DCHECK(!key.empty()); | |
| 412 | |
| 413 ReadWorkerMap::iterator it = read_worker_map_.find(key); | |
| 414 | |
| 415 if (it == read_worker_map_.end()) { | |
| 416 std::pair<ReadWorkerMap::iterator, bool> entry = read_worker_map_.insert( | |
| 417 make_pair(key, | |
| 418 new ReadWorker( | |
| 419 backend_, | |
| 420 key, | |
| 421 base::Bind(&DiskBasedCertCache::FinishedReadOperation, | |
| 422 weak_factory_.GetWeakPtr(), | |
| 423 key), | |
| 424 cb))); | |
| 425 DCHECK(entry.second); | |
| 426 entry.first->second->Start(); | |
| 427 } else { | |
| 428 it->second->AddCallback(cb); | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 void DiskBasedCertCache::Set(const X509Certificate::OSCertHandle cert_handle, | |
| 433 const SetCallback& cb) { | |
| 434 DCHECK(!cb.is_null()); | |
| 435 DCHECK(cert_handle); | |
| 436 std::string key = GetCacheKeyToCert(cert_handle); | |
| 437 | |
| 438 WriteWorkerMap::iterator it = write_worker_map_.find(key); | |
| 439 | |
| 440 if (it == write_worker_map_.end()) { | |
| 441 std::pair<WriteWorkerMap::iterator, bool> entry = write_worker_map_.insert( | |
| 442 make_pair(key, | |
| 443 new WriteWorker( | |
| 444 backend_, | |
| 445 key, | |
| 446 cert_handle, | |
| 447 base::Bind(&DiskBasedCertCache::FinishedWriteOperation, | |
| 448 weak_factory_.GetWeakPtr(), | |
| 449 key), | |
| 450 cb))); | |
| 451 DCHECK(entry.second); | |
| 452 entry.first->second->Start(); | |
| 453 } else { | |
| 454 it->second->AddCallback(cb); | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 void DiskBasedCertCache::FinishedWriteOperation(const std::string& key) { | |
| 459 WriteWorkerMap::iterator it = write_worker_map_.find(key); | |
| 460 delete it->second; | |
| 461 write_worker_map_.erase(it); | |
| 462 } | |
| 463 | |
| 464 void DiskBasedCertCache::FinishedReadOperation(const std::string& key) { | |
| 465 ReadWorkerMap::iterator it = read_worker_map_.find(key); | |
| 466 delete it->second; | |
| 467 read_worker_map_.erase(it); | |
| 468 } | |
| 469 | |
| 470 } // namespace net | |
| OLD | NEW |