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); |