Chromium Code Reviews| Index: net/http/http_cache_transaction.cc |
| diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
| index bf791118be88b704966c7d3a886d5fcc4c924f63..a2e48432fbb866e5e3ecd3d384ee14c2ef079415 100644 |
| --- a/net/http/http_cache_transaction.cc |
| +++ b/net/http/http_cache_transaction.cc |
| @@ -32,6 +32,7 @@ |
| #include "net/base/upload_data_stream.h" |
| #include "net/cert/cert_status_flags.h" |
| #include "net/disk_cache/disk_cache.h" |
| +#include "net/http/disk_based_cert_cache.h" |
| #include "net/http/http_network_session.h" |
| #include "net/http/http_request_info.h" |
| #include "net/http/http_response_headers.h" |
| @@ -47,6 +48,107 @@ using base::TimeTicks; |
| namespace { |
| +// Stores data relevant to the statistics of writing entire certificate |
|
wtc
2014/07/08 00:14:03
Nit: you also use this struct for reading certific
|
| +// chains using DiskBasedCertCache. |num_pending_ops| is the number |
| +// of certificates in the chain that have pending operations in the |
| +// DiskBasedCertCache. |start_time| is the time that the read and write |
| +// commands began being issued to the DiskBasedCertCache. |
| +// TODO(brandonsalmon): Remove this when it is no longer necessary to |
| +// collect data. |
| +struct SharedCCData { |
|
wtc
2014/07/08 00:14:04
Don't use the abbreviation "CC" in the name. See t
|
| + SharedCCData(int num, TimeTicks time) |
|
wtc
2014/07/08 00:14:03
These two parameters are poorly named. You can try
|
| + : num_pending_ops(num), start_time(time) {} |
| + int num_pending_ops; |
| + TimeTicks start_time; |
| +}; |
| + |
| +typedef base::RefCountedData<SharedCCData> RefCountedSharedCCData; |
|
wtc
2014/07/08 00:14:04
This isn't how a ref-counted type is defined. Use
|
| + |
| +// Used to obtain a cache entry key for an OSCertHandle. |
| +// TODO(brandonsalmon): Remove this when cache keys are stored |
| +// and no longer have to be recomputed to retrieve the OSCertHandle |
| +// from the disk. |
| +std::string GetCacheKeyToCert( |
|
wtc
2014/07/08 00:14:03
Nit: GetCacheKeyToCert => GetCacheKeyForCert
To g
Ryan Sleevi
2014/07/08 00:34:18
I recommended Brandon not do this, precisely becau
|
| + const net::X509Certificate::OSCertHandle cert_handle) { |
|
wtc
2014/07/08 00:14:03
This const is not necessary.
|
| + net::SHA1HashValue fingerprint = |
| + net::X509Certificate::CalculateFingerprint(cert_handle); |
| + |
| + return "cert:" + |
| + base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); |
| +} |
| + |
| +// |dist_from_root| indicates the position of the read certificate in the |
| +// certificate chain, 0 indicating it is the leaf. |is_leaf| indicates |
|
wtc
2014/07/08 00:14:03
Typo: 0 indicating it is the leaf => 0 indicating
|
| +// whether or not the read certificate was the leaf of the chain. |
| +// |shared_chain_data| contains data shared by each certificate in |
| +// the chain. |
| +void OnCertReadIOComplete( |
| + int dist_from_root, |
| + bool is_leaf, |
| + scoped_refptr<RefCountedSharedCCData> shared_chain_data, |
|
wtc
2014/07/08 00:14:04
I think you can declare this as
Ryan Sleevi
2014/07/08 00:34:18
Incomplete?
passing "const scoped_refptr<RefCount
wtc
2014/07/08 01:54:42
Yes, this comment is incomplete. Please ignore it.
|
| + net::X509Certificate::OSCertHandle cert_handle) { |
| + // If |num_pending_ops| is one, this was the last pending read operation |
| + // for this chain of certificates. The total time to write the chain |
|
wtc
2014/07/08 00:14:03
write the chain => read the chain ?
|
| + // can be calculated by subtracting the starting time from Now(). |
| + (shared_chain_data->data).num_pending_ops--; |
|
wtc
2014/07/08 00:14:03
Omit the parentheses.
|
| + if (!shared_chain_data->data.num_pending_ops) { |
| + const TimeDelta read_chain_wait = |
| + TimeTicks::Now() - shared_chain_data->data.start_time; |
| + UMA_HISTOGRAM_TIMES("DiskBasedCertCache.ChainReadTime", read_chain_wait); |
|
wtc
2014/07/08 00:14:03
IMPORTANT: use a local histogram (HISTOGRAM_TIMES)
Ryan Sleevi
2014/07/08 00:34:18
wtc: Why do you suggest this? Part of the field tr
wtc
2014/07/08 01:54:42
I didn't know you suggested the field trial.
This
|
| + } |
| + |
| + bool success = (cert_handle != NULL); |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessTotal", success); |
| + |
| + if (is_leaf) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessLeaf", success); |
| + |
| + if (dist_from_root == 0) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessRoot", success); |
|
wtc
2014/07/08 00:14:03
We should not need to cache the root certificate b
Ryan Sleevi
2014/07/08 00:34:18
We do cache the root certs today, precisely becaus
|
| + else if (dist_from_root == 1) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessInt1", success); |
| + else if (dist_from_root == 2) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessInt2", success); |
|
wtc
2014/07/08 00:14:03
BUG: The Int1 and Int2 names imply these certifica
|
| + else |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessIntN", success); |
| +} |
| + |
| +// |dist_from_root| indicates the position of the written certificate in the |
| +// certificate chain, 0 indicating it is the leaf. |is_leaf| indicates |
| +// whether or not the written certificate was the leaf of the chain. |
| +// |shared_chain_data| contains data shared by each certificate in |
| +// the chain. |
| +void OnCertWriteIOComplete( |
| + int dist_from_root, |
| + bool is_leaf, |
| + scoped_refptr<RefCountedSharedCCData> shared_chain_data, |
|
Ryan Sleevi
2014/07/08 00:34:18
const-ref
|
| + const std::string& key) { |
| + // If |num_pending_ops| is one, this was the last pending write operation |
| + // for this chain of certificates. The total time to write the chain |
| + // can be calculated by subtracting the starting time from Now(). |
| + shared_chain_data->data.num_pending_ops--; |
| + if (!shared_chain_data->data.num_pending_ops) { |
| + const TimeDelta write_chain_wait = |
| + TimeTicks::Now() - shared_chain_data->data.start_time; |
| + UMA_HISTOGRAM_TIMES("DiskBasedCertCache.ChainWriteTime", write_chain_wait); |
| + } |
| + |
| + bool success = (key != std::string()); |
|
wtc
2014/07/08 00:14:03
key != std::string() => !key.empty()
|
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessTotal", success); |
| + |
| + if (is_leaf) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessLeaf", success); |
| + |
| + if (dist_from_root == 0) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessRoot", success); |
| + else if (dist_from_root == 1) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessInt1", success); |
| + else if (dist_from_root == 2) |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessInt2", success); |
| + else |
| + UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessIntN", success); |
| +} |
| + |
| // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 |
| // a "non-error response" is one with a 2xx (Successful) or 3xx |
| // (Redirection) status code. |
| @@ -1495,6 +1597,37 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { |
| return OnCacheReadError(result, true); |
| } |
| + // CertCache() will be null if the CertCacheTrial field trial is disabled. |
| + if (cache_->CertCache() && response_.ssl_info.is_valid()) { |
| + std::string key = |
| + GetCacheKeyToCert(response_.ssl_info.cert->os_cert_handle()); |
| + X509Certificate::OSCertHandles intermediates = |
|
wtc
2014/07/08 00:14:03
Declare this as const X509Certificate::OSCertHandl
Ryan Sleevi
2014/07/08 00:34:18
Correct.
So it's unambiguous: const-ref OSCertHan
|
| + response_.ssl_info.cert->GetIntermediateCertificates(); |
| + int dist_from_root = intermediates.size(); |
| + |
| + SharedCCData temp(intermediates.size() + 1, TimeTicks::Now()); |
| + scoped_refptr<RefCountedSharedCCData> shared_chain_data( |
| + new RefCountedSharedCCData(temp)); |
| + cache_->CertCache()->Get(key, |
|
wtc
2014/07/08 00:14:04
IMPORTANT: Add new states to wait for the completi
Ryan Sleevi
2014/07/08 00:34:18
wtc: I recommended this path to Brandon. Could you
wtc
2014/07/08 01:54:42
Eventually we will need to wait for the completion
|
| + base::Bind(&OnCertReadIOComplete, |
| + dist_from_root, |
| + true /* is leaf */, |
| + shared_chain_data)); |
|
wtc
2014/07/08 00:14:03
IMPORTANT: rather than using a heap-allocated Shar
Ryan Sleevi
2014/07/08 00:34:18
It's unclear to me what you're trying to solve.
T
wtc
2014/07/08 01:54:42
Eventually this class will need to wait for the co
|
| + |
| + for (X509Certificate::OSCertHandles::iterator it = intermediates.begin(); |
| + it != intermediates.end(); |
| + ++it) { |
| + --dist_from_root; |
| + key = GetCacheKeyToCert(*it); |
| + cache_->CertCache()->Get(key, |
| + base::Bind(&OnCertReadIOComplete, |
| + dist_from_root, |
| + false /* is not leaf */, |
| + shared_chain_data)); |
| + } |
| + DCHECK_EQ(0, dist_from_root); |
| + } |
| + |
| // Some resources may have slipped in as truncated when they're not. |
| int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); |
| if (response_.headers->GetContentLength() == current_size) |
| @@ -2327,6 +2460,32 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { |
| return OK; |
| } |
| + // CertCache() will be null if the CertCacheTrial field trial is disabled. |
| + if (cache_->CertCache() && response_.ssl_info.is_valid()) { |
| + X509Certificate::OSCertHandles intermediates = |
| + response_.ssl_info.cert->GetIntermediateCertificates(); |
| + int dist_from_root = intermediates.size(); |
| + SharedCCData temp(intermediates.size() + 1, TimeTicks::Now()); |
| + scoped_refptr<RefCountedSharedCCData> shared_chain_data( |
| + new RefCountedSharedCCData(temp)); |
| + cache_->CertCache()->Set(response_.ssl_info.cert->os_cert_handle(), |
| + base::Bind(&OnCertWriteIOComplete, |
| + dist_from_root, |
| + true /* is leaf */, |
| + shared_chain_data)); |
| + for (X509Certificate::OSCertHandles::iterator it = intermediates.begin(); |
| + it != intermediates.end(); |
| + ++it) { |
| + --dist_from_root; |
| + cache_->CertCache()->Set(*it, |
| + base::Bind(&OnCertWriteIOComplete, |
| + dist_from_root, |
| + false /* is not leaf */, |
| + shared_chain_data)); |
| + } |
| + DCHECK_EQ(0, dist_from_root); |
| + } |
| + |
| // When writing headers, we normally only write the non-transient |
| // headers; when in record mode, record everything. |
| bool skip_transient_headers = (cache_->mode() != RECORD); |