Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: net/http/http_cache_transaction.cc

Issue 356953003: Adding DiskBasedCertCache to HttpCache (+UMA). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@current
Patch Set: Added field trial. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/http_cache_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 14 matching lines...) Expand all
25 #include "base/time/time.h" 25 #include "base/time/time.h"
26 #include "net/base/completion_callback.h" 26 #include "net/base/completion_callback.h"
27 #include "net/base/io_buffer.h" 27 #include "net/base/io_buffer.h"
28 #include "net/base/load_flags.h" 28 #include "net/base/load_flags.h"
29 #include "net/base/load_timing_info.h" 29 #include "net/base/load_timing_info.h"
30 #include "net/base/net_errors.h" 30 #include "net/base/net_errors.h"
31 #include "net/base/net_log.h" 31 #include "net/base/net_log.h"
32 #include "net/base/upload_data_stream.h" 32 #include "net/base/upload_data_stream.h"
33 #include "net/cert/cert_status_flags.h" 33 #include "net/cert/cert_status_flags.h"
34 #include "net/disk_cache/disk_cache.h" 34 #include "net/disk_cache/disk_cache.h"
35 #include "net/http/disk_based_cert_cache.h"
35 #include "net/http/http_network_session.h" 36 #include "net/http/http_network_session.h"
36 #include "net/http/http_request_info.h" 37 #include "net/http/http_request_info.h"
37 #include "net/http/http_response_headers.h" 38 #include "net/http/http_response_headers.h"
38 #include "net/http/http_transaction.h" 39 #include "net/http/http_transaction.h"
39 #include "net/http/http_util.h" 40 #include "net/http/http_util.h"
40 #include "net/http/partial_data.h" 41 #include "net/http/partial_data.h"
41 #include "net/ssl/ssl_cert_request_info.h" 42 #include "net/ssl/ssl_cert_request_info.h"
42 #include "net/ssl/ssl_config_service.h" 43 #include "net/ssl/ssl_config_service.h"
43 44
44 using base::Time; 45 using base::Time;
45 using base::TimeDelta; 46 using base::TimeDelta;
46 using base::TimeTicks; 47 using base::TimeTicks;
47 48
48 namespace { 49 namespace {
49 50
51 // 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
52 // chains using DiskBasedCertCache. |num_pending_ops| is the number
53 // of certificates in the chain that have pending operations in the
54 // DiskBasedCertCache. |start_time| is the time that the read and write
55 // commands began being issued to the DiskBasedCertCache.
56 // TODO(brandonsalmon): Remove this when it is no longer necessary to
57 // collect data.
58 struct SharedCCData {
wtc 2014/07/08 00:14:04 Don't use the abbreviation "CC" in the name. See t
59 SharedCCData(int num, TimeTicks time)
wtc 2014/07/08 00:14:03 These two parameters are poorly named. You can try
60 : num_pending_ops(num), start_time(time) {}
61 int num_pending_ops;
62 TimeTicks start_time;
63 };
64
65 typedef base::RefCountedData<SharedCCData> RefCountedSharedCCData;
wtc 2014/07/08 00:14:04 This isn't how a ref-counted type is defined. Use
66
67 // Used to obtain a cache entry key for an OSCertHandle.
68 // TODO(brandonsalmon): Remove this when cache keys are stored
69 // and no longer have to be recomputed to retrieve the OSCertHandle
70 // from the disk.
71 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
72 const net::X509Certificate::OSCertHandle cert_handle) {
wtc 2014/07/08 00:14:03 This const is not necessary.
73 net::SHA1HashValue fingerprint =
74 net::X509Certificate::CalculateFingerprint(cert_handle);
75
76 return "cert:" +
77 base::HexEncode(fingerprint.data, arraysize(fingerprint.data));
78 }
79
80 // |dist_from_root| indicates the position of the read certificate in the
81 // 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
82 // whether or not the read certificate was the leaf of the chain.
83 // |shared_chain_data| contains data shared by each certificate in
84 // the chain.
85 void OnCertReadIOComplete(
86 int dist_from_root,
87 bool is_leaf,
88 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.
89 net::X509Certificate::OSCertHandle cert_handle) {
90 // If |num_pending_ops| is one, this was the last pending read operation
91 // 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 ?
92 // can be calculated by subtracting the starting time from Now().
93 (shared_chain_data->data).num_pending_ops--;
wtc 2014/07/08 00:14:03 Omit the parentheses.
94 if (!shared_chain_data->data.num_pending_ops) {
95 const TimeDelta read_chain_wait =
96 TimeTicks::Now() - shared_chain_data->data.start_time;
97 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
98 }
99
100 bool success = (cert_handle != NULL);
101 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessTotal", success);
102
103 if (is_leaf)
104 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessLeaf", success);
105
106 if (dist_from_root == 0)
107 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
108 else if (dist_from_root == 1)
109 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessInt1", success);
110 else if (dist_from_root == 2)
111 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessInt2", success);
wtc 2014/07/08 00:14:03 BUG: The Int1 and Int2 names imply these certifica
112 else
113 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.ReadSuccessIntN", success);
114 }
115
116 // |dist_from_root| indicates the position of the written certificate in the
117 // certificate chain, 0 indicating it is the leaf. |is_leaf| indicates
118 // whether or not the written certificate was the leaf of the chain.
119 // |shared_chain_data| contains data shared by each certificate in
120 // the chain.
121 void OnCertWriteIOComplete(
122 int dist_from_root,
123 bool is_leaf,
124 scoped_refptr<RefCountedSharedCCData> shared_chain_data,
Ryan Sleevi 2014/07/08 00:34:18 const-ref
125 const std::string& key) {
126 // If |num_pending_ops| is one, this was the last pending write operation
127 // for this chain of certificates. The total time to write the chain
128 // can be calculated by subtracting the starting time from Now().
129 shared_chain_data->data.num_pending_ops--;
130 if (!shared_chain_data->data.num_pending_ops) {
131 const TimeDelta write_chain_wait =
132 TimeTicks::Now() - shared_chain_data->data.start_time;
133 UMA_HISTOGRAM_TIMES("DiskBasedCertCache.ChainWriteTime", write_chain_wait);
134 }
135
136 bool success = (key != std::string());
wtc 2014/07/08 00:14:03 key != std::string() => !key.empty()
137 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessTotal", success);
138
139 if (is_leaf)
140 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessLeaf", success);
141
142 if (dist_from_root == 0)
143 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessRoot", success);
144 else if (dist_from_root == 1)
145 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessInt1", success);
146 else if (dist_from_root == 2)
147 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessInt2", success);
148 else
149 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.WriteSuccessIntN", success);
150 }
151
50 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 152 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
51 // a "non-error response" is one with a 2xx (Successful) or 3xx 153 // a "non-error response" is one with a 2xx (Successful) or 3xx
52 // (Redirection) status code. 154 // (Redirection) status code.
53 bool NonErrorResponse(int status_code) { 155 bool NonErrorResponse(int status_code) {
54 int status_code_range = status_code / 100; 156 int status_code_range = status_code / 100;
55 return status_code_range == 2 || status_code_range == 3; 157 return status_code_range == 2 || status_code_range == 3;
56 } 158 }
57 159
58 // Error codes that will be considered indicative of a page being offline/ 160 // Error codes that will be considered indicative of a page being offline/
59 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE. 161 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE.
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 } 1590 }
1489 1591
1490 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { 1592 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
1491 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1593 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1492 if (result != io_buf_len_ || 1594 if (result != io_buf_len_ ||
1493 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, 1595 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
1494 &response_, &truncated_)) { 1596 &response_, &truncated_)) {
1495 return OnCacheReadError(result, true); 1597 return OnCacheReadError(result, true);
1496 } 1598 }
1497 1599
1600 // CertCache() will be null if the CertCacheTrial field trial is disabled.
1601 if (cache_->CertCache() && response_.ssl_info.is_valid()) {
1602 std::string key =
1603 GetCacheKeyToCert(response_.ssl_info.cert->os_cert_handle());
1604 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
1605 response_.ssl_info.cert->GetIntermediateCertificates();
1606 int dist_from_root = intermediates.size();
1607
1608 SharedCCData temp(intermediates.size() + 1, TimeTicks::Now());
1609 scoped_refptr<RefCountedSharedCCData> shared_chain_data(
1610 new RefCountedSharedCCData(temp));
1611 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
1612 base::Bind(&OnCertReadIOComplete,
1613 dist_from_root,
1614 true /* is leaf */,
1615 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
1616
1617 for (X509Certificate::OSCertHandles::iterator it = intermediates.begin();
1618 it != intermediates.end();
1619 ++it) {
1620 --dist_from_root;
1621 key = GetCacheKeyToCert(*it);
1622 cache_->CertCache()->Get(key,
1623 base::Bind(&OnCertReadIOComplete,
1624 dist_from_root,
1625 false /* is not leaf */,
1626 shared_chain_data));
1627 }
1628 DCHECK_EQ(0, dist_from_root);
1629 }
1630
1498 // Some resources may have slipped in as truncated when they're not. 1631 // Some resources may have slipped in as truncated when they're not.
1499 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1632 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1500 if (response_.headers->GetContentLength() == current_size) 1633 if (response_.headers->GetContentLength() == current_size)
1501 truncated_ = false; 1634 truncated_ = false;
1502 1635
1503 // We now have access to the cache entry. 1636 // We now have access to the cache entry.
1504 // 1637 //
1505 // o if we are a reader for the transaction, then we can start reading the 1638 // o if we are a reader for the transaction, then we can start reading the
1506 // cache entry. 1639 // cache entry.
1507 // 1640 //
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
2320 // reverse-map the cert status to a net error and replay the net error. 2453 // reverse-map the cert status to a net error and replay the net error.
2321 if ((cache_->mode() != RECORD && 2454 if ((cache_->mode() != RECORD &&
2322 response_.headers->HasHeaderValue("cache-control", "no-store")) || 2455 response_.headers->HasHeaderValue("cache-control", "no-store")) ||
2323 net::IsCertStatusError(response_.ssl_info.cert_status)) { 2456 net::IsCertStatusError(response_.ssl_info.cert_status)) {
2324 DoneWritingToEntry(false); 2457 DoneWritingToEntry(false);
2325 if (net_log_.IsLogging()) 2458 if (net_log_.IsLogging())
2326 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2459 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
2327 return OK; 2460 return OK;
2328 } 2461 }
2329 2462
2463 // CertCache() will be null if the CertCacheTrial field trial is disabled.
2464 if (cache_->CertCache() && response_.ssl_info.is_valid()) {
2465 X509Certificate::OSCertHandles intermediates =
2466 response_.ssl_info.cert->GetIntermediateCertificates();
2467 int dist_from_root = intermediates.size();
2468 SharedCCData temp(intermediates.size() + 1, TimeTicks::Now());
2469 scoped_refptr<RefCountedSharedCCData> shared_chain_data(
2470 new RefCountedSharedCCData(temp));
2471 cache_->CertCache()->Set(response_.ssl_info.cert->os_cert_handle(),
2472 base::Bind(&OnCertWriteIOComplete,
2473 dist_from_root,
2474 true /* is leaf */,
2475 shared_chain_data));
2476 for (X509Certificate::OSCertHandles::iterator it = intermediates.begin();
2477 it != intermediates.end();
2478 ++it) {
2479 --dist_from_root;
2480 cache_->CertCache()->Set(*it,
2481 base::Bind(&OnCertWriteIOComplete,
2482 dist_from_root,
2483 false /* is not leaf */,
2484 shared_chain_data));
2485 }
2486 DCHECK_EQ(0, dist_from_root);
2487 }
2488
2330 // When writing headers, we normally only write the non-transient 2489 // When writing headers, we normally only write the non-transient
2331 // headers; when in record mode, record everything. 2490 // headers; when in record mode, record everything.
2332 bool skip_transient_headers = (cache_->mode() != RECORD); 2491 bool skip_transient_headers = (cache_->mode() != RECORD);
2333 2492
2334 if (truncated) 2493 if (truncated)
2335 DCHECK_EQ(200, response_.headers->response_code()); 2494 DCHECK_EQ(200, response_.headers->response_code());
2336 2495
2337 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2496 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2338 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2497 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2339 data->Done(); 2498 data->Done();
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
2576 default: 2735 default:
2577 NOTREACHED(); 2736 NOTREACHED();
2578 } 2737 }
2579 } 2738 }
2580 2739
2581 void HttpCache::Transaction::OnIOComplete(int result) { 2740 void HttpCache::Transaction::OnIOComplete(int result) {
2582 DoLoop(result); 2741 DoLoop(result);
2583 } 2742 }
2584 2743
2585 } // namespace net 2744 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698