Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/disk_based_cert_cache.h" | 5 #include "net/http/disk_based_cert_cache.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/metrics/histogram.h" | |
| 12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 15 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 16 #include "net/disk_cache/disk_cache.h" | 17 #include "net/disk_cache/disk_cache.h" |
| 17 | 18 |
| 18 namespace net { | 19 namespace net { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // TODO(brandonsalmon): change this number to improve performance. | 23 // TODO(brandonsalmon): change this number to improve performance. |
| 23 const size_t kMemoryCacheMaxSize = 30; | 24 const size_t kMemoryCacheMaxSize = 30; |
| 24 | 25 |
| 25 // Used to obtain a unique cache key for a certificate in the form of | 26 // Used to obtain a unique cache key for a certificate in the form of |
| 26 // "cert:<hash>". | 27 // "cert:<hash>". |
| 27 std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) { | 28 std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) { |
| 28 SHA1HashValue fingerprint = | 29 SHA1HashValue fingerprint = |
| 29 X509Certificate::CalculateFingerprint(cert_handle); | 30 X509Certificate::CalculateFingerprint(cert_handle); |
| 30 | 31 |
| 31 return "cert:" + | 32 return "cert:" + |
| 32 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); | 33 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); |
| 33 } | 34 } |
| 34 | 35 |
| 36 void RecordMemCacheHits(bool hit) { | |
| 37 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.MemCacheHits", hit); | |
| 38 } | |
| 39 | |
| 40 void RecordDiskCacheHits(bool hit) { | |
| 41 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.DiskCacheHits", hit); | |
| 42 } | |
| 43 | |
| 35 } // namespace | 44 } // namespace |
| 36 | 45 |
| 37 // WriteWorkers represent pending Set jobs in the DiskBasedCertCache. Each | 46 // WriteWorkers represent pending Set jobs in the DiskBasedCertCache. Each |
| 38 // certificate requested to be cached is assigned a Writeworker on a one-to-one | 47 // certificate requested to be cached is assigned a Writeworker on a one-to-one |
| 39 // basis. The same certificate should not have multiple WriteWorkers at the same | 48 // basis. The same certificate should not have multiple WriteWorkers at the same |
| 40 // time; instead, add a user callback to the existing WriteWorker. | 49 // time; instead, add a user callback to the existing WriteWorker. |
| 41 class DiskBasedCertCache::WriteWorker { | 50 class DiskBasedCertCache::WriteWorker { |
| 42 public: | 51 public: |
| 43 // |backend| is the backend to store |certificate| in, using | 52 // |backend| is the backend to store |certificate| in, using |
| 44 // |key| as the key for the disk_cache::Entry. | 53 // |key| as the key for the disk_cache::Entry. |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 | 430 |
| 422 return rv; | 431 return rv; |
| 423 } | 432 } |
| 424 | 433 |
| 425 int DiskBasedCertCache::ReadWorker::DoOpen() { | 434 int DiskBasedCertCache::ReadWorker::DoOpen() { |
| 426 state_ = STATE_OPEN_COMPLETE; | 435 state_ = STATE_OPEN_COMPLETE; |
| 427 return backend_->OpenEntry(key_, &entry_, io_callback_); | 436 return backend_->OpenEntry(key_, &entry_, io_callback_); |
| 428 } | 437 } |
| 429 | 438 |
| 430 int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) { | 439 int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) { |
| 440 // Errors other than cache miss are not recorded as either a hit | |
| 441 // or a miss. | |
| 442 if (rv == ERR_CACHE_MISS) | |
| 443 RecordDiskCacheHits(false); | |
| 431 if (rv < 0) | 444 if (rv < 0) |
| 432 return rv; | 445 return rv; |
|
wtc
2014/07/09 14:55:36
Nit: I would structure this as follows:
if (rv
| |
| 446 RecordDiskCacheHits(true); | |
|
wtc
2014/07/09 14:55:36
This means a corrupted disk cache entry is still r
| |
| 433 | 447 |
| 434 state_ = STATE_READ; | 448 state_ = STATE_READ; |
| 435 return OK; | 449 return OK; |
| 436 } | 450 } |
| 437 | 451 |
| 438 int DiskBasedCertCache::ReadWorker::DoRead() { | 452 int DiskBasedCertCache::ReadWorker::DoRead() { |
| 439 state_ = STATE_READ_COMPLETE; | 453 state_ = STATE_READ_COMPLETE; |
| 440 io_buf_len_ = entry_->GetDataSize(0 /* index */); | 454 io_buf_len_ = entry_->GetDataSize(0 /* index */); |
| 441 buffer_ = new IOBuffer(io_buf_len_); | 455 buffer_ = new IOBuffer(io_buf_len_); |
| 442 return entry_->ReadData( | 456 return entry_->ReadData( |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 } | 513 } |
| 500 | 514 |
| 501 void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) { | 515 void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) { |
| 502 DCHECK(!key.empty()); | 516 DCHECK(!key.empty()); |
| 503 | 517 |
| 504 // If the handle is already in the MRU cache, just return that (via callback). | 518 // If the handle is already in the MRU cache, just return that (via callback). |
| 505 // Note, this will also bring the cert_handle to the front of the recency | 519 // Note, this will also bring the cert_handle to the front of the recency |
| 506 // list in the MRU cache. | 520 // list in the MRU cache. |
| 507 MRUCertCache::iterator mru_it = mru_cert_cache_.Get(key); | 521 MRUCertCache::iterator mru_it = mru_cert_cache_.Get(key); |
| 508 if (mru_it != mru_cert_cache_.end()) { | 522 if (mru_it != mru_cert_cache_.end()) { |
| 523 RecordMemCacheHits(true); | |
| 509 ++mem_cache_hits_; | 524 ++mem_cache_hits_; |
| 510 cb.Run(mru_it->second); | 525 cb.Run(mru_it->second); |
| 511 return; | 526 return; |
| 512 } | 527 } |
| 528 RecordMemCacheHits(false); | |
| 513 ++mem_cache_misses_; | 529 ++mem_cache_misses_; |
| 514 | 530 |
| 515 ReadWorkerMap::iterator it = read_worker_map_.find(key); | 531 ReadWorkerMap::iterator it = read_worker_map_.find(key); |
| 516 | 532 |
| 517 if (it == read_worker_map_.end()) { | 533 if (it == read_worker_map_.end()) { |
| 518 ReadWorker* worker = | 534 ReadWorker* worker = |
| 519 new ReadWorker(backend_, | 535 new ReadWorker(backend_, |
| 520 key, | 536 key, |
| 521 base::Bind(&DiskBasedCertCache::FinishedReadOperation, | 537 base::Bind(&DiskBasedCertCache::FinishedReadOperation, |
| 522 weak_factory_.GetWeakPtr(), | 538 weak_factory_.GetWeakPtr(), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 | 580 |
| 565 void DiskBasedCertCache::FinishedWriteOperation( | 581 void DiskBasedCertCache::FinishedWriteOperation( |
| 566 const std::string& key, | 582 const std::string& key, |
| 567 X509Certificate::OSCertHandle cert_handle) { | 583 X509Certificate::OSCertHandle cert_handle) { |
| 568 write_worker_map_.erase(key); | 584 write_worker_map_.erase(key); |
| 569 if (!key.empty()) | 585 if (!key.empty()) |
| 570 mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle)); | 586 mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle)); |
| 571 } | 587 } |
| 572 | 588 |
| 573 } // namespace net | 589 } // namespace net |
| OLD | NEW |