summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2013-08-08 10:24:53 +0100
committerBen Murdoch <benm@google.com>2013-08-08 10:24:53 +0100
commitbb1529ce867d8845a77ec7cdf3e3003ef1771a40 (patch)
treef78d0de03cc8aed1a934d921636a0beb8d164378 /net
parentc95505573d864f17cabf515e32f5b8e0831ae237 (diff)
downloadchromium_org-bb1529ce867d8845a77ec7cdf3e3003ef1771a40.tar.gz
Merge from Chromium at DEPS revision r216370
This commit was generated by merge_to_master.py. Change-Id: I739228187a6f1df6c28c5761160e593a49891113
Diffstat (limited to 'net')
-rw-r--r--net/cert/cert_verify_proc_nss.cc29
-rw-r--r--net/cert/jwk_serializer.h30
-rw-r--r--net/cert/jwk_serializer_nss.cc118
-rw-r--r--net/cert/jwk_serializer_openssl.cc22
-rw-r--r--net/cert/jwk_serializer_unittest.cc148
-rw-r--r--net/disk_cache/simple/simple_entry_impl.cc242
-rw-r--r--net/disk_cache/simple/simple_entry_impl.h43
-rw-r--r--net/disk_cache/simple/simple_entry_operation.cc184
-rw-r--r--net/disk_cache/simple/simple_entry_operation.h125
-rw-r--r--net/dns/mdns_client_impl.cc3
-rw-r--r--net/net.gyp11
-rw-r--r--net/net.target.darwin-arm.mk2
-rw-r--r--net/net.target.darwin-mips.mk2
-rw-r--r--net/net.target.darwin-x86.mk2
-rw-r--r--net/net.target.linux-arm.mk2
-rw-r--r--net/net.target.linux-mips.mk2
-rw-r--r--net/net.target.linux-x86.mk2
-rw-r--r--net/quic/crypto/crypto_server_config.h6
-rw-r--r--net/quic/quic_connection.cc4
-rw-r--r--net/quic/quic_packet_creator.cc25
-rw-r--r--net/quic/quic_received_packet_manager.cc2
-rw-r--r--net/quic/quic_utils.h4
-rw-r--r--net/socket/ssl_client_socket_nss.cc59
-rw-r--r--net/spdy/spdy_credential_builder.cc4
-rw-r--r--net/spdy/spdy_credential_builder.h2
-rw-r--r--net/spdy/spdy_credential_builder_unittest.cc44
-rw-r--r--net/spdy/spdy_http_stream_unittest.cc9
-rw-r--r--net/spdy/spdy_session.cc3
-rw-r--r--net/spdy/spdy_session.h2
-rw-r--r--net/spdy/spdy_stream.cc15
-rw-r--r--net/spdy/spdy_stream.h1
-rw-r--r--net/ssl/default_server_bound_cert_store.cc36
-rw-r--r--net/ssl/default_server_bound_cert_store.h5
-rw-r--r--net/ssl/default_server_bound_cert_store_unittest.cc157
-rw-r--r--net/ssl/server_bound_cert_service.cc229
-rw-r--r--net/ssl/server_bound_cert_service.h24
-rw-r--r--net/ssl/server_bound_cert_service_unittest.cc295
-rw-r--r--net/ssl/server_bound_cert_store.cc7
-rw-r--r--net/ssl/server_bound_cert_store.h21
-rw-r--r--net/third_party/nss/README.chromium4
-rw-r--r--net/third_party/nss/patches/aes256keylength.patch15
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh2
-rw-r--r--net/third_party/nss/ssl.gyp1
-rw-r--r--net/third_party/nss/ssl/bodge/secure_memcmp.c59
-rw-r--r--net/third_party/nss/ssl/sslsnce.c5
-rw-r--r--net/tools/quic/quic_server.cc25
-rw-r--r--net/tools/quic/quic_server.h8
-rw-r--r--net/tools/quic/quic_server_test.cc74
-rw-r--r--net/tools/quic/test_tools/mock_quic_dispatcher.cc21
-rw-r--r--net/tools/quic/test_tools/mock_quic_dispatcher.h38
50 files changed, 1299 insertions, 874 deletions
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc
index 120f091d7b..f63297e83c 100644
--- a/net/cert/cert_verify_proc_nss.cc
+++ b/net/cert/cert_verify_proc_nss.cc
@@ -162,10 +162,6 @@ CertStatus MapCertErrorToCertStatus(int err) {
void GetCertChainInfo(CERTCertList* cert_list,
CERTCertificate* root_cert,
CertVerifyResult* verify_result) {
- // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the
- // NSS version currently in use:
- // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*)
- // 2. use ident libnss3.so* for the library's version
DCHECK(cert_list);
CERTCertificate* verified_cert = NULL;
@@ -367,31 +363,6 @@ SECStatus PKIXVerifyCert(CERTCertificate* cert_handle,
bool use_crl = check_revocation;
bool use_ocsp = check_revocation;
- // These CAs have multiple keys, which trigger two bugs in NSS's CRL code.
- // 1. NSS may use one key to verify a CRL signed with another key,
- // incorrectly concluding that the CRL's signature is invalid.
- // Hopefully this bug will be fixed in NSS 3.12.9.
- // 2. NSS considers all certificates issued by the CA as revoked when it
- // receives a CRL with an invalid signature. This overly strict policy
- // has been relaxed in NSS 3.12.7. See
- // https://bugzilla.mozilla.org/show_bug.cgi?id=562542.
- // So we have to turn off CRL checking for these CAs. See
- // http://crbug.com/55695.
- static const char* const kMultipleKeyCA[] = {
- "CN=Microsoft Secure Server Authority,"
- "DC=redmond,DC=corp,DC=microsoft,DC=com",
- "CN=Microsoft Secure Server Authority",
- };
-
- if (!NSS_VersionCheck("3.12.7")) {
- for (size_t i = 0; i < arraysize(kMultipleKeyCA); ++i) {
- if (strcmp(cert_handle->issuerName, kMultipleKeyCA[i]) == 0) {
- use_crl = false;
- break;
- }
- }
- }
-
PRUint64 revocation_method_flags =
CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD |
CERT_REV_M_ALLOW_NETWORK_FETCHING |
diff --git a/net/cert/jwk_serializer.h b/net/cert/jwk_serializer.h
new file mode 100644
index 0000000000..7a12a36624
--- /dev/null
+++ b/net/cert/jwk_serializer.h
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_JWK_SERIALIZER_H_
+#define NET_CERT_JWK_SERIALIZER_H_
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace net {
+
+namespace JwkSerializer {
+
+// Converts a subject public key info from DER to JWK.
+// See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-13 for
+// the output format.
+NET_EXPORT_PRIVATE bool ConvertSpkiFromDerToJwk(
+ const base::StringPiece& spki_der,
+ base::DictionaryValue* public_key_jwk);
+
+} // namespace JwkSerializer
+
+} // namespace net
+
+#endif // NET_CERT_JWK_SERIALIZER_H_
diff --git a/net/cert/jwk_serializer_nss.cc b/net/cert/jwk_serializer_nss.cc
new file mode 100644
index 0000000000..0259c5c515
--- /dev/null
+++ b/net/cert/jwk_serializer_nss.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/jwk_serializer.h"
+
+#include <cert.h>
+#include <keyhi.h>
+#include <nss.h>
+
+#include "base/base64.h"
+#include "base/values.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace net {
+
+namespace JwkSerializer {
+
+namespace {
+
+bool ConvertEcPrime256v1PublicKeyInfoToJwk(
+ CERTSubjectPublicKeyInfo* spki,
+ base::DictionaryValue* public_key_jwk) {
+ static const int kPrime256v1EncodingType = 4;
+ static const int kPrime256v1PublicKeyLength = 64;
+ // The public key value is encoded as 0x04 + 64 bytes of public key.
+ // NSS gives the length as the bit length.
+ if (spki->subjectPublicKey.len != (kPrime256v1PublicKeyLength + 1) * 8 ||
+ spki->subjectPublicKey.data[0] != kPrime256v1EncodingType)
+ return false;
+
+ public_key_jwk->SetString("alg", "EC");
+ public_key_jwk->SetString("crv", "P-256");
+
+ base::StringPiece x(
+ reinterpret_cast<char*>(spki->subjectPublicKey.data + 1),
+ kPrime256v1PublicKeyLength / 2);
+ std::string x_b64;
+ base::Base64Encode(x, &x_b64);
+ public_key_jwk->SetString("x", x_b64);
+
+ base::StringPiece y(
+ reinterpret_cast<char*>(spki->subjectPublicKey.data + 1 +
+ kPrime256v1PublicKeyLength / 2),
+ kPrime256v1PublicKeyLength / 2);
+ std::string y_b64;
+ base::Base64Encode(y, &y_b64);
+ public_key_jwk->SetString("y", y_b64);
+ return true;
+}
+
+bool ConvertEcPublicKeyInfoToJwk(
+ CERTSubjectPublicKeyInfo* spki,
+ base::DictionaryValue* public_key_jwk) {
+ // 1.2.840.10045.3.1.7
+ // (iso.member-body.us.ansi-x9-62.ellipticCurve.primeCurve.prime256v1)
+ // (This includes the DER-encoded type (OID) and length: parameters can be
+ // anything, so the DER type isn't implied, and NSS includes it.)
+ static const unsigned char kPrime256v1[] = {
+ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
+ };
+ if (spki->algorithm.parameters.len == sizeof(kPrime256v1) &&
+ !memcmp(spki->algorithm.parameters.data, kPrime256v1,
+ sizeof(kPrime256v1))) {
+ return ConvertEcPrime256v1PublicKeyInfoToJwk(spki, public_key_jwk);
+ }
+ // TODO(juanlang): other curves
+ return false;
+}
+
+typedef scoped_ptr_malloc<
+ CERTSubjectPublicKeyInfo,
+ crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
+ SECKEY_DestroySubjectPublicKeyInfo> >
+ ScopedCERTSubjectPublicKeyInfo;
+
+} // namespace
+
+bool ConvertSpkiFromDerToJwk(
+ const base::StringPiece& spki_der,
+ base::DictionaryValue* public_key_jwk) {
+ public_key_jwk->Clear();
+
+ crypto::EnsureNSSInit();
+
+ if (!NSS_IsInitialized())
+ return false;
+
+ SECItem sec_item;
+ sec_item.data = const_cast<unsigned char*>(
+ reinterpret_cast<const unsigned char*>(spki_der.data()));
+ sec_item.len = spki_der.size();
+ ScopedCERTSubjectPublicKeyInfo spki(
+ SECKEY_DecodeDERSubjectPublicKeyInfo(&sec_item));
+ if (!spki)
+ return false;
+
+ // 1.2.840.10045.2
+ // (iso.member-body.us.ansi-x9-62.id-ecPublicKey)
+ // (This omits the ASN.1 encoding of the type (OID) and length: the fact that
+ // this is an OID is already clear, and NSS omits it here.)
+ static const unsigned char kIdEcPublicKey[] = {
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01
+ };
+ bool rv = false;
+ if (spki->algorithm.algorithm.len == sizeof(kIdEcPublicKey) &&
+ !memcmp(spki->algorithm.algorithm.data, kIdEcPublicKey,
+ sizeof(kIdEcPublicKey))) {
+ rv = ConvertEcPublicKeyInfoToJwk(spki.get(), public_key_jwk);
+ }
+ // TODO(juanlang): other algorithms
+ return rv;
+}
+
+} // namespace JwkSerializer
+
+} // namespace net
diff --git a/net/cert/jwk_serializer_openssl.cc b/net/cert/jwk_serializer_openssl.cc
new file mode 100644
index 0000000000..ef15b4bcfa
--- /dev/null
+++ b/net/cert/jwk_serializer_openssl.cc
@@ -0,0 +1,22 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "net/cert/jwk_serializer.h"
+
+namespace net {
+
+namespace JwkSerializer {
+
+bool ConvertSpkiFromDerToJwk(
+ const base::StringPiece& spki_der,
+ base::DictionaryValue* public_key_jwk) {
+ // TODO(juanlang): implement
+ NOTIMPLEMENTED();
+ return false;
+}
+
+} // namespace JwkSerializer
+
+} // namespace net
diff --git a/net/cert/jwk_serializer_unittest.cc b/net/cert/jwk_serializer_unittest.cc
new file mode 100644
index 0000000000..37b8002951
--- /dev/null
+++ b/net/cert/jwk_serializer_unittest.cc
@@ -0,0 +1,148 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/jwk_serializer.h"
+
+#include "base/base64.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+// This is the ASN.1 prefix for a P-256 public key. Specifically it's:
+// SEQUENCE
+// SEQUENCE
+// OID id-ecPublicKey
+// OID prime256v1
+// BIT STRING, length 66, 0 trailing bits: 0x04
+//
+// The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62
+// public key. Following that are the two field elements as 32-byte,
+// big-endian numbers, as required by the Channel ID.
+static const unsigned char kP256SpkiPrefix[] = {
+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+ 0x42, 0x00, 0x04
+};
+static const unsigned int kEcPointSize = 32U;
+
+// This is a valid P-256 public key.
+static const unsigned char kSpkiEc[] = {
+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+ 0x42, 0x00, 0x04,
+ 0x29, 0x5d, 0x6e, 0xfe, 0x33, 0x77, 0x26, 0xea,
+ 0x5b, 0xa4, 0xe6, 0x1b, 0x34, 0x6e, 0x7b, 0xa0,
+ 0xa3, 0x8f, 0x33, 0x49, 0xa0, 0x9c, 0xae, 0x98,
+ 0xbd, 0x46, 0x0d, 0xf6, 0xd4, 0x5a, 0xdc, 0x8a,
+ 0x1f, 0x8a, 0xb2, 0x20, 0x51, 0xb7, 0xd2, 0x87,
+ 0x0d, 0x53, 0x7e, 0x5d, 0x94, 0xa3, 0xe0, 0x34,
+ 0x16, 0xa1, 0xcc, 0x10, 0x48, 0xcd, 0x70, 0x9c,
+ 0x05, 0xd3, 0xd2, 0xca, 0xdf, 0x44, 0x2f, 0xf4
+};
+
+// This is a P-256 public key with 0 X and Y values.
+static const unsigned char kSpkiEcWithZeroXY[] = {
+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+ 0x42, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#if !defined(USE_OPENSSL)
+
+TEST(JwkSerializerNSSTest, ConvertSpkiFromDerToJwkEc) {
+ base::StringPiece spki;
+ base::DictionaryValue public_key_jwk;
+
+ EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
+ EXPECT_TRUE(public_key_jwk.empty());
+
+ // Test the result of a "normal" point on this curve.
+ spki.set(reinterpret_cast<const char*>(kSpkiEc), sizeof(kSpkiEc));
+ EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
+
+ std::string string_value;
+ EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value));
+ EXPECT_STREQ("EC", string_value.c_str());
+ EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
+ EXPECT_STREQ("P-256", string_value.c_str());
+
+ EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
+ std::string decoded_coordinate;
+ EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
+ EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(0,
+ memcmp(decoded_coordinate.data(),
+ kSpkiEc + sizeof(kP256SpkiPrefix),
+ kEcPointSize));
+
+ EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
+ EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
+ EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(0,
+ memcmp(decoded_coordinate.data(),
+ kSpkiEc + sizeof(kP256SpkiPrefix) + kEcPointSize,
+ kEcPointSize));
+
+ // Test the result of a corner case: leading 0s in the x, y coordinates are
+ // not trimmed, but the point is fixed-length encoded.
+ spki.set(reinterpret_cast<const char*>(kSpkiEcWithZeroXY),
+ sizeof(kSpkiEcWithZeroXY));
+ EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
+
+ EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value));
+ EXPECT_STREQ("EC", string_value.c_str());
+ EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
+ EXPECT_STREQ("P-256", string_value.c_str());
+
+ EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
+ EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
+ EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(0,
+ memcmp(decoded_coordinate.data(),
+ kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix),
+ kEcPointSize));
+
+ EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
+ EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
+ EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(0,
+ memcmp(decoded_coordinate.data(),
+ kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcPointSize,
+ kEcPointSize));
+}
+
+#else
+
+// For OpenSSL, JwkSerializer::ConvertSpkiFromDerToJwk() is not yet implemented
+// and should return false. This unit test ensures that a stub implementation
+// is present.
+TEST(JwkSerializerOpenSSLTest, ConvertSpkiFromDerToJwkNotImplemented) {
+ base::StringPiece spki;
+ base::DictionaryValue public_key_jwk;
+
+ // The empty SPKI is trivially non-convertible...
+ EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
+ EXPECT_TRUE(public_key_jwk.empty());
+ // but even a valid SPKI is non-convertible via the stub OpenSSL
+ // implementation.
+ spki.set(reinterpret_cast<const char*>(kSpkiEc), sizeof(kSpkiEc));
+ EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
+ EXPECT_TRUE(public_key_jwk.empty());
+}
+
+#endif // !defined(USE_OPENSSL)
+
+} // namespace net
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 7bef5f0aea..3c3ec7daff 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -125,14 +125,6 @@ void AdjustOpenEntryCountBy(int offset) {
g_open_entry_count);
}
-bool OperationsConflict(int index1, int offset1, int length1, bool truncate1,
- int index2, int offset2, int length2, bool truncate2) {
- int end1 = truncate1 ? INT_MAX : offset1 + length1;
- int end2 = truncate2 ? INT_MAX : offset2 + length2;
- bool ranges_intersect = (offset1 < end2 && offset2 < end1);
- return (index1 == index2 && ranges_intersect);
-}
-
} // namespace
namespace disk_cache {
@@ -220,11 +212,8 @@ int SimpleEntryImpl::OpenEntry(Entry** out_entry,
return net::ERR_FAILED;
}
- EnqueueOperation(base::Bind(&SimpleEntryImpl::OpenEntryInternal,
- this,
- have_index,
- callback,
- out_entry));
+ pending_operations_.push(SimpleEntryOperation::OpenOperation(
+ this, have_index, callback, out_entry));
RunNextOperationIfNeeded();
return net::ERR_IO_PENDING;
}
@@ -243,18 +232,12 @@ int SimpleEntryImpl::CreateEntry(Entry** out_entry,
net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_CREATE_OPTIMISTIC);
ReturnEntryToCaller(out_entry);
- EnqueueOperation(base::Bind(&SimpleEntryImpl::CreateEntryInternal,
- this,
- have_index,
- CompletionCallback(),
- static_cast<Entry**>(NULL)));
+ pending_operations_.push(SimpleEntryOperation::CreateOperation(
+ this, have_index, CompletionCallback(), static_cast<Entry**>(NULL)));
ret_value = net::OK;
} else {
- EnqueueOperation(base::Bind(&SimpleEntryImpl::CreateEntryInternal,
- this,
- have_index,
- callback,
- out_entry));
+ pending_operations_.push(SimpleEntryOperation::CreateOperation(
+ this, have_index, callback, out_entry));
ret_value = net::ERR_IO_PENDING;
}
@@ -305,7 +288,7 @@ void SimpleEntryImpl::Close() {
return;
}
- EnqueueOperation(base::Bind(&SimpleEntryImpl::CloseInternal, this));
+ pending_operations_.push(SimpleEntryOperation::CloseOperation(this));
DCHECK(!HasOneRef());
Release(); // Balanced in ReturnEntryToCaller().
RunNextOperationIfNeeded();
@@ -368,16 +351,10 @@ int SimpleEntryImpl::ReadData(int stream_index,
// TODO(felipeg): Optimization: Add support for truly parallel read
// operations.
- EnqueueReadOperation(base::Bind(&SimpleEntryImpl::ReadDataInternal,
- this,
- stream_index,
- offset,
- make_scoped_refptr(buf),
- buf_len,
- callback),
- stream_index,
- offset,
- buf_len);
+ bool alone_in_queue =
+ pending_operations_.size() == 0 && state_ == STATE_READY;
+ pending_operations_.push(SimpleEntryOperation::ReadOperation(
+ this, stream_index, offset, buf_len, buf, callback, alone_in_queue));
RunNextOperationIfNeeded();
return net::ERR_IO_PENDING;
}
@@ -462,13 +439,14 @@ int SimpleEntryImpl::WriteData(int stream_index,
}
}
- EnqueueWriteOperation(optimistic,
- stream_index,
- offset,
- op_buf.get(),
- buf_len,
- truncate,
- op_callback);
+ pending_operations_.push(SimpleEntryOperation::WriteOperation(this,
+ stream_index,
+ offset,
+ buf_len,
+ op_buf.get(),
+ truncate,
+ optimistic,
+ op_callback));
return ret_value;
}
@@ -521,9 +499,6 @@ int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
return net::ERR_FAILED;
}
-SimpleEntryImpl::LastQueuedOpInfo::LastQueuedOpInfo()
- : is_optimistic_write(false), is_write(false), is_read(false) {}
-
SimpleEntryImpl::~SimpleEntryImpl() {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_EQ(0U, pending_operations_.size());
@@ -570,96 +545,49 @@ void SimpleEntryImpl::RunNextOperationIfNeeded() {
UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.EntryOperationsPending",
pending_operations_.size(), 0, 100, 20);
if (!pending_operations_.empty() && state_ != STATE_IO_PENDING) {
- base::Closure operation = pending_operations_.front();
+ scoped_ptr<SimpleEntryOperation> operation(
+ new SimpleEntryOperation(pending_operations_.front()));
pending_operations_.pop();
- operation.Run();
- // |this| may have been deleted.
- }
-}
-
-void SimpleEntryImpl::EnqueueOperation(const base::Closure& operation) {
- last_op_info_.is_read = false;
- last_op_info_.is_write = false;
- last_op_info_.is_optimistic_write = false;
- pending_operations_.push(operation);
-}
-
-void SimpleEntryImpl::EnqueueReadOperation(const base::Closure& operation,
- int index,
- int offset,
- int length) {
- bool parallelizable_read = last_op_info_.is_read &&
- (!pending_operations_.empty() || state_ == STATE_IO_PENDING);
- UMA_HISTOGRAM_BOOLEAN("SimpleCache.ReadIsParallelizable",
- parallelizable_read);
- last_op_info_.is_read = true;
- last_op_info_.is_write = false;
- last_op_info_.is_optimistic_write = false;
- last_op_info_.io_index = index;
- last_op_info_.io_offset = offset;
- last_op_info_.io_length = length;
- pending_operations_.push(operation);
-}
-
-void SimpleEntryImpl::EnqueueWriteOperation(
- bool optimistic,
- int index,
- int offset,
- net::IOBuffer* buf,
- int length,
- bool truncate,
- const CompletionCallback& callback) {
- // Used in histograms, please only add entries at the end.
- enum WriteDependencyType {
- WRITE_OPTIMISTIC = 0,
- WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC = 1,
- WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC = 2,
- WRITE_FOLLOWS_CONFLICTING_WRITE = 3,
- WRITE_FOLLOWS_NON_CONFLICTING_WRITE = 4,
- WRITE_FOLLOWS_CONFLICTING_READ = 5,
- WRITE_FOLLOWS_NON_CONFLICTING_READ = 6,
- WRITE_FOLLOWS_OTHER = 7,
- WRITE_DEPENDENCY_TYPE_MAX = 8,
- };
-
- WriteDependencyType type = WRITE_FOLLOWS_OTHER;
- if (optimistic) {
- type = WRITE_OPTIMISTIC;
- } else if (last_op_info_.is_read || last_op_info_.is_write) {
- bool conflicting = OperationsConflict(
- index, offset, length, truncate,
- last_op_info_.io_index,
- last_op_info_.io_offset, last_op_info_.io_length,
- last_op_info_.truncate && last_op_info_.is_write);
-
- if (last_op_info_.is_optimistic_write) {
- type = conflicting ? WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC
- : WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC;
- } else if (last_op_info_.is_read) {
- type = conflicting ? WRITE_FOLLOWS_CONFLICTING_READ
- : WRITE_FOLLOWS_NON_CONFLICTING_READ;
- } else {
- type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
- : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
+ switch (operation->type()) {
+ case SimpleEntryOperation::TYPE_OPEN:
+ OpenEntryInternal(operation->have_index(),
+ operation->callback(),
+ operation->out_entry());
+ break;
+ case SimpleEntryOperation::TYPE_CREATE:
+ CreateEntryInternal(operation->have_index(),
+ operation->callback(),
+ operation->out_entry());
+ break;
+ case SimpleEntryOperation::TYPE_CLOSE:
+ CloseInternal();
+ break;
+ case SimpleEntryOperation::TYPE_READ:
+ RecordReadIsParallelizable(*operation);
+ ReadDataInternal(operation->index(),
+ operation->offset(),
+ operation->buf(),
+ operation->length(),
+ operation->callback());
+ break;
+ case SimpleEntryOperation::TYPE_WRITE:
+ RecordWriteDependencyType(*operation);
+ WriteDataInternal(operation->index(),
+ operation->offset(),
+ operation->buf(),
+ operation->length(),
+ operation->callback(),
+ operation->truncate());
+ break;
+ default:
+ NOTREACHED();
}
+ // The operation is kept for histograms. Makes sure it does not leak
+ // resources.
+ executing_operation_.swap(operation);
+ executing_operation_->ReleaseReferences();
+ // |this| may have been deleted.
}
- UMA_HISTOGRAM_ENUMERATION(
- "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX);
- last_op_info_.is_read = false;
- last_op_info_.is_write = true;
- last_op_info_.is_optimistic_write = optimistic;
- last_op_info_.io_index = index;
- last_op_info_.io_offset = offset;
- last_op_info_.io_length = length;
- last_op_info_.truncate = truncate;
- pending_operations_.push(base::Bind(&SimpleEntryImpl::WriteDataInternal,
- this,
- index,
- offset,
- make_scoped_refptr(buf),
- length,
- callback,
- truncate));
}
void SimpleEntryImpl::OpenEntryInternal(bool have_index,
@@ -1204,4 +1132,56 @@ int64 SimpleEntryImpl::GetDiskUsage() const {
return file_size;
}
+void SimpleEntryImpl::RecordReadIsParallelizable(
+ const SimpleEntryOperation& operation) const {
+ if (!executing_operation_)
+ return;
+ // TODO(clamy): The values of this histogram should be changed to something
+ // more useful.
+ bool parallelizable_read =
+ !operation.alone_in_queue() &&
+ executing_operation_->type() == SimpleEntryOperation::TYPE_READ;
+ UMA_HISTOGRAM_BOOLEAN("SimpleCache.ReadIsParallelizable",
+ parallelizable_read);
+}
+
+void SimpleEntryImpl::RecordWriteDependencyType(
+ const SimpleEntryOperation& operation) const {
+ if (!executing_operation_)
+ return;
+ // Used in histograms, please only add entries at the end.
+ enum WriteDependencyType {
+ WRITE_OPTIMISTIC = 0,
+ WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC = 1,
+ WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC = 2,
+ WRITE_FOLLOWS_CONFLICTING_WRITE = 3,
+ WRITE_FOLLOWS_NON_CONFLICTING_WRITE = 4,
+ WRITE_FOLLOWS_CONFLICTING_READ = 5,
+ WRITE_FOLLOWS_NON_CONFLICTING_READ = 6,
+ WRITE_FOLLOWS_OTHER = 7,
+ WRITE_DEPENDENCY_TYPE_MAX = 8,
+ };
+
+ WriteDependencyType type = WRITE_FOLLOWS_OTHER;
+ if (operation.optimistic()) {
+ type = WRITE_OPTIMISTIC;
+ } else if (executing_operation_->type() == SimpleEntryOperation::TYPE_READ ||
+ executing_operation_->type() == SimpleEntryOperation::TYPE_WRITE) {
+ bool conflicting = executing_operation_->ConflictsWith(operation);
+
+ if (executing_operation_->type() == SimpleEntryOperation::TYPE_READ) {
+ type = conflicting ? WRITE_FOLLOWS_CONFLICTING_READ
+ : WRITE_FOLLOWS_NON_CONFLICTING_READ;
+ } else if (executing_operation_->optimistic()) {
+ type = conflicting ? WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC
+ : WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC;
+ } else {
+ type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
+ : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
+ }
+ }
+ UMA_HISTOGRAM_ENUMERATION(
+ "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX);
+}
+
} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h
index be28fb89cd..7eb8914e87 100644
--- a/net/disk_cache/simple/simple_entry_impl.h
+++ b/net/disk_cache/simple/simple_entry_impl.h
@@ -16,6 +16,7 @@
#include "net/base/net_log.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/simple/simple_entry_format.h"
+#include "net/disk_cache/simple/simple_entry_operation.h"
namespace base {
class TaskRunner;
@@ -129,22 +130,6 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>,
CRC_CHECK_MAX = 4,
};
- // Used in histograms.
- struct LastQueuedOpInfo {
- LastQueuedOpInfo();
-
- // Used for SimpleCache.WriteDependencyType.
- int io_index;
- int io_offset;
- int io_length;
- bool is_optimistic_write;
- bool is_write;
- bool truncate;
-
- // Used for SimpleCache.ReadIsParallelizable histogram.
- bool is_read;
- };
-
virtual ~SimpleEntryImpl();
// Sets entry to STATE_UNINITIALIZED.
@@ -169,24 +154,6 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>,
// the last reference.
void RunNextOperationIfNeeded();
- // Adds a non read operation to the queue of operations.
- void EnqueueOperation(const base::Closure& operation);
-
- // Adds a read operation to the queue of operations.
- void EnqueueReadOperation(const base::Closure& operation,
- int index,
- int offset,
- int length);
-
- // Adds a write operation to the queue of operations.
- void EnqueueWriteOperation(bool optimistic,
- int index,
- int offset,
- net::IOBuffer* buf,
- int length,
- bool truncate,
- const CompletionCallback& callback);
-
void OpenEntryInternal(bool have_index,
const CompletionCallback& callback,
Entry** out_entry);
@@ -263,6 +230,10 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>,
int64 GetDiskUsage() const;
+ // Used to report histograms.
+ void RecordReadIsParallelizable(const SimpleEntryOperation& operation) const;
+ void RecordWriteDependencyType(const SimpleEntryOperation& operation) const;
+
// All nonstatic SimpleEntryImpl methods should always be called on the IO
// thread, in all cases. |io_thread_checker_| documents and enforces this.
base::ThreadChecker io_thread_checker_;
@@ -307,11 +278,11 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>,
// is false (i.e. when an operation is not pending on the worker pool).
SimpleSynchronousEntry* synchronous_entry_;
- std::queue<base::Closure> pending_operations_;
+ std::queue<SimpleEntryOperation> pending_operations_;
net::BoundNetLog net_log_;
- LastQueuedOpInfo last_op_info_;
+ scoped_ptr<SimpleEntryOperation> executing_operation_;
};
} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_entry_operation.cc b/net/disk_cache/simple/simple_entry_operation.cc
new file mode 100644
index 0000000000..81d5f7c888
--- /dev/null
+++ b/net/disk_cache/simple/simple_entry_operation.cc
@@ -0,0 +1,184 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/disk_cache/simple/simple_entry_operation.h"
+
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/disk_cache/simple/simple_entry_impl.h"
+
+namespace disk_cache {
+
+SimpleEntryOperation::SimpleEntryOperation(const SimpleEntryOperation& other)
+ : entry_(other.entry_.get()),
+ buf_(other.buf_),
+ callback_(other.callback_),
+ out_entry_(other.out_entry_),
+ offset_(other.offset_),
+ length_(other.length_),
+ type_(other.type_),
+ have_index_(other.have_index_),
+ index_(other.index_),
+ truncate_(other.truncate_),
+ optimistic_(other.optimistic_),
+ alone_in_queue_(other.alone_in_queue_) {
+}
+
+SimpleEntryOperation::~SimpleEntryOperation() {}
+
+// Static.
+SimpleEntryOperation SimpleEntryOperation::OpenOperation(
+ SimpleEntryImpl* entry,
+ bool have_index,
+ const CompletionCallback& callback,
+ Entry** out_entry) {
+ return SimpleEntryOperation(entry,
+ NULL,
+ callback,
+ out_entry,
+ 0,
+ 0,
+ TYPE_OPEN,
+ have_index,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// Static.
+SimpleEntryOperation SimpleEntryOperation::CreateOperation(
+ SimpleEntryImpl* entry,
+ bool have_index,
+ const CompletionCallback& callback,
+ Entry** out_entry) {
+ return SimpleEntryOperation(entry,
+ NULL,
+ callback,
+ out_entry,
+ 0,
+ 0,
+ TYPE_CREATE,
+ have_index,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// Static.
+SimpleEntryOperation SimpleEntryOperation::CloseOperation(
+ SimpleEntryImpl* entry) {
+ return SimpleEntryOperation(entry,
+ NULL,
+ CompletionCallback(),
+ NULL,
+ 0,
+ 0,
+ TYPE_CLOSE,
+ false,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// Static.
+SimpleEntryOperation SimpleEntryOperation::ReadOperation(
+ SimpleEntryImpl* entry,
+ int index,
+ int offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback,
+ bool alone_in_queue) {
+ return SimpleEntryOperation(entry,
+ buf,
+ callback,
+ NULL,
+ offset,
+ length,
+ TYPE_READ,
+ false,
+ index,
+ false,
+ false,
+ alone_in_queue);
+}
+
+// Static.
+SimpleEntryOperation SimpleEntryOperation::WriteOperation(
+ SimpleEntryImpl* entry,
+ int index,
+ int offset,
+ int length,
+ net::IOBuffer* buf,
+ bool truncate,
+ bool optimistic,
+ const CompletionCallback& callback) {
+ return SimpleEntryOperation(entry,
+ buf,
+ callback,
+ NULL,
+ offset,
+ length,
+ TYPE_WRITE,
+ false,
+ index,
+ truncate,
+ optimistic,
+ false);
+}
+
+bool SimpleEntryOperation::ConflictsWith(
+ const SimpleEntryOperation& other_op) const {
+ if (type_ != TYPE_READ && type_ != TYPE_WRITE)
+ return true;
+ if (other_op.type() != TYPE_READ && other_op.type() != TYPE_WRITE)
+ return true;
+ if (type() == TYPE_READ && other_op.type() == TYPE_READ)
+ return false;
+ if (index_ != other_op.index_)
+ return false;
+ int end = (type_ == TYPE_WRITE && truncate_) ? INT_MAX : offset_ + length_;
+ int other_op_end = (other_op.type() == TYPE_WRITE && other_op.truncate())
+ ? INT_MAX
+ : other_op.offset() + other_op.length();
+ return (offset_ < other_op_end && other_op.offset() < end);
+}
+
+void SimpleEntryOperation::ReleaseReferences() {
+ callback_ = CompletionCallback();
+ buf_ = NULL;
+ entry_ = NULL;
+}
+
+SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback,
+ Entry** out_entry,
+ int offset,
+ int length,
+ EntryOperationType type,
+ bool have_index,
+ int index,
+ bool truncate,
+ bool optimistic,
+ bool alone_in_queue)
+ : entry_(entry),
+ buf_(buf),
+ callback_(callback),
+ out_entry_(out_entry),
+ offset_(offset),
+ length_(length),
+ type_(type),
+ have_index_(have_index),
+ index_(index),
+ truncate_(truncate),
+ optimistic_(optimistic),
+ alone_in_queue_(alone_in_queue) {
+}
+
+} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_entry_operation.h b/net/disk_cache/simple/simple_entry_operation.h
new file mode 100644
index 0000000000..acdd60a320
--- /dev/null
+++ b/net/disk_cache/simple/simple_entry_operation.h
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_
+#define NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_
+
+#include "base/memory/ref_counted.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_log.h"
+
+namespace net {
+class IOBuffer;
+}
+
+namespace disk_cache {
+
+class Entry;
+class SimpleEntryImpl;
+
+// SimpleEntryOperation stores the information regarding operations in
+// SimpleEntryImpl, between the moment they are issued by users of the backend,
+// and the moment when they are executed.
+class SimpleEntryOperation {
+ public:
+ typedef net::CompletionCallback CompletionCallback;
+
+ enum EntryOperationType {
+ TYPE_OPEN = 0,
+ TYPE_CREATE = 1,
+ TYPE_CLOSE = 2,
+ TYPE_READ = 3,
+ TYPE_WRITE = 4,
+ };
+
+ SimpleEntryOperation(const SimpleEntryOperation& other);
+ ~SimpleEntryOperation();
+
+ static SimpleEntryOperation OpenOperation(SimpleEntryImpl* entry,
+ bool have_index,
+ const CompletionCallback& callback,
+ Entry** out_entry);
+ static SimpleEntryOperation CreateOperation(
+ SimpleEntryImpl* entry,
+ bool have_index,
+ const CompletionCallback& callback,
+ Entry** out_entry);
+ static SimpleEntryOperation CloseOperation(SimpleEntryImpl* entry);
+ static SimpleEntryOperation ReadOperation(SimpleEntryImpl* entry,
+ int index,
+ int offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback,
+ bool alone_in_queue);
+ static SimpleEntryOperation WriteOperation(
+ SimpleEntryImpl* entry,
+ int index,
+ int offset,
+ int length,
+ net::IOBuffer* buf,
+ bool truncate,
+ bool optimistic,
+ const CompletionCallback& callback);
+
+ bool ConflictsWith(const SimpleEntryOperation& other_op) const;
+ // Releases all references. After calling this operation, SimpleEntryOperation
+ // will only hold POD members.
+ void ReleaseReferences();
+
+ EntryOperationType type() const {
+ return static_cast<EntryOperationType>(type_);
+ }
+ const CompletionCallback& callback() const { return callback_; }
+ Entry** out_entry() { return out_entry_; }
+ bool have_index() const { return have_index_; }
+ int index() const { return index_; }
+ int offset() const { return offset_; }
+ int length() const { return length_; }
+ net::IOBuffer* buf() { return buf_.get(); }
+ bool truncate() const { return truncate_; }
+ bool optimistic() const { return optimistic_; }
+ bool alone_in_queue() const { return alone_in_queue_; }
+
+ private:
+ SimpleEntryOperation(SimpleEntryImpl* entry,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback,
+ Entry** out_entry,
+ int offset,
+ int length,
+ EntryOperationType type,
+ bool have_index,
+ int index,
+ bool truncate,
+ bool optimistic,
+ bool alone_in_queue);
+
+ // This ensures entry will not be deleted until the operation has ran.
+ scoped_refptr<SimpleEntryImpl> entry_;
+ scoped_refptr<net::IOBuffer> buf_;
+ CompletionCallback callback_;
+
+ // Used in open and create operations.
+ Entry** out_entry_;
+
+ // Used in write and read operations.
+ const int offset_;
+ const int length_;
+
+ const unsigned int type_ : 3; /* 3 */
+ // Used in open and create operations.
+ const unsigned int have_index_ : 1; /* 4 */
+ // Used in write and read operations.
+ const unsigned int index_ : 2; /* 6 */
+ // Used only in write operations.
+ const unsigned int truncate_ : 1; /* 7 */
+ const unsigned int optimistic_ : 1; /* 8 */
+ // Used only in SimpleCache.ReadIsParallelizable histogram.
+ const unsigned int alone_in_queue_ : 1; /* 9 */
+};
+
+} // namespace disk_cache
+
+#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_
diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc
index 089a51a8a7..8f79edf4cd 100644
--- a/net/dns/mdns_client_impl.cc
+++ b/net/dns/mdns_client_impl.cc
@@ -622,8 +622,7 @@ void MDnsTransactionImpl::ServeRecordsFromCache() {
client_->core()->QueryCache(rrtype_, name_, &records);
for (std::vector<const RecordParsed*>::iterator i = records.begin();
i != records.end() && weak_this; ++i) {
- weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD,
- records.front());
+ weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD, *i);
}
#if defined(ENABLE_NSEC)
diff --git a/net/net.gyp b/net/net.gyp
index 8942367294..0165031978 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -271,6 +271,9 @@
'cert/crl_set.h',
'cert/ev_root_ca_metadata.cc',
'cert/ev_root_ca_metadata.h',
+ 'cert/jwk_serializer_nss.cc',
+ 'cert/jwk_serializer_openssl.cc',
+ 'cert/jwk_serializer.h',
'cert/multi_threaded_cert_verifier.cc',
'cert/multi_threaded_cert_verifier.h',
'cert/nss_cert_database.cc',
@@ -390,6 +393,8 @@
'disk_cache/simple/simple_entry_format.h',
'disk_cache/simple/simple_entry_impl.cc',
'disk_cache/simple/simple_entry_impl.h',
+ 'disk_cache/simple/simple_entry_operation.cc',
+ 'disk_cache/simple/simple_entry_operation.h',
'disk_cache/simple/simple_index.cc',
'disk_cache/simple/simple_index.h',
'disk_cache/simple/simple_index_file.cc',
@@ -1199,6 +1204,7 @@
'cert/cert_database_nss.cc',
'cert/cert_verify_proc_nss.cc',
'cert/cert_verify_proc_nss.h',
+ 'cert/jwk_serializer_nss.cc',
'cert/nss_cert_database.cc',
'cert/nss_cert_database.h',
'cert/test_root_certs_nss.cc',
@@ -1236,6 +1242,7 @@
'cert/cert_database_openssl.cc',
'cert/cert_verify_proc_openssl.cc',
'cert/cert_verify_proc_openssl.h',
+ 'cert/jwk_serializer_openssl.cc',
'cert/test_root_certs_openssl.cc',
'cert/x509_certificate_openssl.cc',
'cert/x509_util_openssl.cc',
@@ -1524,6 +1531,7 @@
'cert/cert_verify_proc_unittest.cc',
'cert/crl_set_unittest.cc',
'cert/ev_root_ca_metadata_unittest.cc',
+ 'cert/jwk_serializer_unittest.cc',
'cert/multi_threaded_cert_verifier_unittest.cc',
'cert/nss_cert_database_unittest.cc',
'cert/pem_tokenizer_unittest.cc',
@@ -1869,11 +1877,14 @@
'tools/quic/quic_in_memory_cache_test.cc',
'tools/quic/quic_reliable_client_stream_test.cc',
'tools/quic/quic_reliable_server_stream_test.cc',
+ 'tools/quic/quic_server_test.cc',
'tools/quic/quic_spdy_server_stream_test.cc',
'tools/quic/test_tools/http_message_test_utils.cc',
'tools/quic/test_tools/http_message_test_utils.h',
'tools/quic/test_tools/mock_epoll_server.cc',
'tools/quic/test_tools/mock_epoll_server.h',
+ 'tools/quic/test_tools/mock_quic_dispatcher.cc',
+ 'tools/quic/test_tools/mock_quic_dispatcher.h',
'tools/quic/test_tools/quic_client_peer.cc',
'tools/quic/test_tools/quic_client_peer.h',
'tools/quic/test_tools/quic_epoll_connection_helper_peer.cc',
diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk
index 32a09e6590..88d78fc546 100644
--- a/net/net.target.darwin-arm.mk
+++ b/net/net.target.darwin-arm.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk
index 47c7546b98..6fedabc2e6 100644
--- a/net/net.target.darwin-mips.mk
+++ b/net/net.target.darwin-mips.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk
index 24f1ffd8d0..4479a95214 100644
--- a/net/net.target.darwin-x86.mk
+++ b/net/net.target.darwin-x86.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk
index 32a09e6590..88d78fc546 100644
--- a/net/net.target.linux-arm.mk
+++ b/net/net.target.linux-arm.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk
index 47c7546b98..6fedabc2e6 100644
--- a/net/net.target.linux-mips.mk
+++ b/net/net.target.linux-mips.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk
index 24f1ffd8d0..4479a95214 100644
--- a/net/net.target.linux-x86.mk
+++ b/net/net.target.linux-x86.mk
@@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \
net/cert/cert_verify_result.cc \
net/cert/crl_set.cc \
net/cert/ev_root_ca_metadata.cc \
+ net/cert/jwk_serializer_openssl.cc \
net/cert/multi_threaded_cert_verifier.cc \
net/cert/pem_tokenizer.cc \
net/cert/single_request_cert_verifier.cc \
@@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \
net/disk_cache/simple/simple_backend_impl.cc \
net/disk_cache/simple/simple_entry_format.cc \
net/disk_cache/simple/simple_entry_impl.cc \
+ net/disk_cache/simple/simple_entry_operation.cc \
net/disk_cache/simple/simple_index.cc \
net/disk_cache/simple/simple_index_file.cc \
net/disk_cache/simple/simple_net_log_parameters.cc \
diff --git a/net/quic/crypto/crypto_server_config.h b/net/quic/crypto/crypto_server_config.h
index 651e928c29..1a991362bd 100644
--- a/net/quic/crypto/crypto_server_config.h
+++ b/net/quic/crypto/crypto_server_config.h
@@ -198,8 +198,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
public:
Config();
- // serialized contains the bytes of this server config, suitable for sending
- // on the wire.
+ // TODO(rtenneti): since this is a class, we should probably do
+ // getters/setters here.
+ // |serialized| contains the bytes of this server config, suitable for
+ // sending on the wire.
std::string serialized;
// id contains the SCID of this server config.
std::string id;
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index ea738af4d6..30f822ca88 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -877,8 +877,6 @@ void QuicConnection::RetransmitPacket(
RetransmissionInfo retransmission_info(serialized_packet.sequence_number);
retransmission_info.number_retransmissions =
retransmission_it->second.number_retransmissions + 1;
- retransmission_map_.insert(make_pair(serialized_packet.sequence_number,
- retransmission_info));
// Remove info with old sequence number.
unacked_packets_.erase(unacked_it);
retransmission_map_.erase(retransmission_it);
@@ -888,6 +886,8 @@ void QuicConnection::RetransmitPacket(
unacked_packets_.rbegin()->first < serialized_packet.sequence_number);
unacked_packets_.insert(make_pair(serialized_packet.sequence_number,
unacked));
+ retransmission_map_.insert(make_pair(serialized_packet.sequence_number,
+ retransmission_info));
SendOrQueuePacket(unacked->encryption_level(),
serialized_packet.sequence_number,
serialized_packet.packet,
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 19e58c3163..6d69676861 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -111,16 +111,23 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
size_t bytes_consumed = 0;
if (data.size() != 0) {
- size_t min_last_stream_frame_size =
- QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true);
- // Comparing against the last stream frame size including the frame length
- // guarantees that all the bytes will fit. Otherwise there is a
- // discontinuity where the packet goes one byte over due to the length data.
- if (data.size() + min_last_stream_frame_size + kQuicStreamPayloadLengthSize
- >= free_bytes) {
- // Its the last frame, put as much data as possible in.
+ // When a STREAM frame is the last frame in a packet, it consumes two fewer
+ // bytes of framing overhead.
+ // Anytime more data is available than fits in with the extra two bytes,
+ // the frame will be the last, and up to two extra bytes are consumed.
+ // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when
+ // 1 byte is available, because then the STREAM frame isn't the last.
+
+ // The minimum frame size(0 bytes of data) if it's not the last frame.
+ size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
+ framer_->version(), id, offset, false);
+ // Check if it's the last frame in the packet.
+ if (data.size() + min_frame_size > free_bytes) {
+ // The minimum frame size(0 bytes of data) if it is the last frame.
+ size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize(
+ framer_->version(), id, offset, true);
bytes_consumed =
- min<size_t>(free_bytes - min_last_stream_frame_size, data.size());
+ min<size_t>(free_bytes - min_last_frame_size, data.size());
} else {
DCHECK_LT(data.size(), BytesFree());
bytes_consumed = data.size();
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc
index f6f94ccf89..3ade8fba9a 100644
--- a/net/quic/quic_received_packet_manager.cc
+++ b/net/quic/quic_received_packet_manager.cc
@@ -99,6 +99,8 @@ QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
packets_entropy_.upper_bound(sequence_number);
// When this map is empty we should only query entropy for
// |largest_received_sequence_number_|.
+ // TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium.
+ // LOG_IF_EVERY_N_SEC(WARNING, it != packets_entropy_.end(), 10)
LOG_IF(WARNING, it != packets_entropy_.end())
<< "largest_received: " << received_info_.largest_observed
<< " sequence_number: " << sequence_number;
diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h
index fca3904757..6650dbf453 100644
--- a/net/quic/quic_utils.h
+++ b/net/quic/quic_utils.h
@@ -70,6 +70,10 @@ class NET_EXPORT_PRIVATE QuicUtils {
// "0x0010: 001c fb98 4000 4001 7e18 d8ef 2301 455d ....@.@.~...#.E]\n"
// "0x0020: 7fe2 0800 6bcb 0bc6 806e ....k....n\n"
static std::string StringToHexASCIIDump(base::StringPiece in_buffer);
+
+ static char* AsChars(unsigned char* data) {
+ return reinterpret_cast<char*>(data);
+ }
};
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index a5645b997a..d1f28323c6 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -771,8 +771,7 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
////////////////////////////////////////////////////////////////////////////
int DoBufferRecv(IOBuffer* buffer, int len);
int DoBufferSend(IOBuffer* buffer, int len);
- int DoGetDomainBoundCert(const std::string& host,
- const std::vector<uint8>& requested_cert_types);
+ int DoGetDomainBoundCert(const std::string& host);
void OnGetDomainBoundCertComplete(int result);
void OnHandshakeStateUpdated(const HandshakeState& state);
@@ -903,7 +902,6 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
// prior to invoking OnHandshakeIOComplete.
// Read on the NSS task runner when once OnHandshakeIOComplete is invoked
// on the NSS task runner.
- SSLClientCertType domain_bound_cert_type_;
std::string domain_bound_private_key_;
std::string domain_bound_cert_;
@@ -944,8 +942,7 @@ SSLClientSocketNSS::Core::Core(
user_write_buf_len_(0),
network_task_runner_(network_task_runner),
nss_task_runner_(nss_task_runner),
- weak_net_log_(weak_net_log_factory_.GetWeakPtr()),
- domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) {
+ weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
}
SSLClientSocketNSS::Core::~Core() {
@@ -1274,7 +1271,6 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
PRFileDesc* socket,
PRBool checksig,
PRBool is_server) {
-#ifdef SSL_ENABLE_FALSE_START
Core* core = reinterpret_cast<Core*>(arg);
if (!core->handshake_callback_called_) {
// Only need to turn off False Start in the initial handshake. Also, it is
@@ -1296,7 +1292,6 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE);
}
}
-#endif
// Tell NSS to not verify the certificate.
return SECSuccess;
@@ -2318,17 +2313,15 @@ SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
// We have negotiated the TLS channel ID extension.
core->channel_id_xtn_negotiated_ = true;
std::string host = core->host_and_port_.host();
- std::vector<uint8> requested_cert_types;
- requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
int error = ERR_UNEXPECTED;
if (core->OnNetworkTaskRunner()) {
- error = core->DoGetDomainBoundCert(host, requested_cert_types);
+ error = core->DoGetDomainBoundCert(host);
} else {
bool posted = core->network_task_runner_->PostTask(
FROM_HERE,
base::Bind(
IgnoreResult(&Core::DoGetDomainBoundCert),
- core, host, requested_cert_types));
+ core, host));
error = posted ? ERR_IO_PENDING : ERR_ABORTED;
}
@@ -2372,9 +2365,7 @@ int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
return MapNSSError(PORT_GetError());
// Set the private key.
- switch (domain_bound_cert_type_) {
- case CLIENT_CERT_ECDSA_SIGN: {
- if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
+ if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
ServerBoundCertService::kEPKIPassword,
reinterpret_cast<const unsigned char*>(
domain_bound_private_key_.data()),
@@ -2384,15 +2375,8 @@ int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
false,
key,
public_key)) {
- int error = MapNSSError(PORT_GetError());
- return error;
- }
- break;
- }
-
- default:
- NOTREACHED();
- return ERR_INVALID_ARGUMENT;
+ int error = MapNSSError(PORT_GetError());
+ return error;
}
return OK;
@@ -2433,8 +2417,8 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
SSL_CONNECTION_COMPRESSION_MASK) <<
SSL_CONNECTION_COMPRESSION_SHIFT;
- // NSS 3.12.x doesn't have version macros for TLS 1.1 and 1.2 (because NSS
- // doesn't support them yet), so we use 0x0302 and 0x0303 directly.
+ // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't
+ // support it yet), so use 0x0303 directly.
int version = SSL_CONNECTION_VERSION_UNKNOWN;
if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
// All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
@@ -2444,7 +2428,7 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
version = SSL_CONNECTION_VERSION_SSL3;
} else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
version = SSL_CONNECTION_VERSION_TLS1;
- } else if (channel_info.protocolVersion == 0x0302) {
+ } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
version = SSL_CONNECTION_VERSION_TLS1_1;
} else if (channel_info.protocolVersion == 0x0303) {
version = SSL_CONNECTION_VERSION_TLS1_2;
@@ -2454,10 +2438,6 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
SSL_CONNECTION_VERSION_SHIFT;
}
- // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6.
- // Since SSL_MAX_EXTENSIONS was added at the same time, we can test
- // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension.
-#if defined(SSL_MAX_EXTENSIONS)
PRBool peer_supports_renego_ext;
ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
&peer_supports_renego_ext);
@@ -2491,7 +2471,6 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
peer_supports_renego_ext == PR_TRUE);
}
}
-#endif
if (ssl_config_.version_fallback) {
nss_handshake_state_.ssl_connection_status |=
@@ -2620,9 +2599,7 @@ int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
return rv;
}
-int SSLClientSocketNSS::Core::DoGetDomainBoundCert(
- const std::string& host,
- const std::vector<uint8>& requested_cert_types) {
+int SSLClientSocketNSS::Core::DoGetDomainBoundCert(const std::string& host) {
DCHECK(OnNetworkTaskRunner());
if (detached_)
@@ -2632,8 +2609,6 @@ int SSLClientSocketNSS::Core::DoGetDomainBoundCert(
int rv = server_bound_cert_service_->GetDomainBoundCert(
host,
- requested_cert_types,
- &domain_bound_cert_type_,
&domain_bound_private_key_,
&domain_bound_cert_,
base::Bind(&Core::OnGetDomainBoundCertComplete, base::Unretained(this)),
@@ -3168,25 +3143,18 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
}
-#ifdef SSL_ENABLE_SESSION_TICKETS
// Support RFC 5077
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
if (rv != SECSuccess) {
LogFailedNSSFunction(
net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
}
-#else
- #error "You need to install NSS-3.12 or later to build chromium"
-#endif
-#ifdef SSL_ENABLE_FALSE_START
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
ssl_config_.false_start_enabled);
if (rv != SECSuccess)
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
-#endif
-#ifdef SSL_ENABLE_RENEGOTIATION
// We allow servers to request renegotiation. Since we're a client,
// prohibiting this is rather a waste of time. Only servers are in a
// position to prevent renegotiation attacks.
@@ -3198,14 +3166,12 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
LogFailedNSSFunction(
net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
}
-#endif // SSL_ENABLE_RENEGOTIATION
-#ifdef SSL_CBC_RANDOM_IV
rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
if (rv != SECSuccess)
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");
-#endif
+// Added in NSS 3.15
#ifdef SSL_ENABLE_OCSP_STAPLING
if (IsOCSPStaplingSupported()) {
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
@@ -3216,6 +3182,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
}
#endif
+// Chromium patch to libssl
#ifdef SSL_ENABLE_CACHED_INFO
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO,
ssl_config_.cached_info_enabled);
diff --git a/net/spdy/spdy_credential_builder.cc b/net/spdy/spdy_credential_builder.cc
index 1742aff985..79567b668a 100644
--- a/net/spdy/spdy_credential_builder.cc
+++ b/net/spdy/spdy_credential_builder.cc
@@ -26,14 +26,10 @@ std::vector<uint8> ToVector(base::StringPiece piece) {
// static
int SpdyCredentialBuilder::Build(const std::string& tls_unique,
- SSLClientCertType type,
const std::string& key,
const std::string& cert,
size_t slot,
SpdyCredential* credential) {
- if (type != CLIENT_CERT_ECDSA_SIGN)
- return ERR_BAD_SSL_CLIENT_AUTH_CERT;
-
std::string secret = SpdyCredentialBuilder::GetCredentialSecret(tls_unique);
// Extract the SubjectPublicKeyInfo from the certificate.
diff --git a/net/spdy/spdy_credential_builder.h b/net/spdy/spdy_credential_builder.h
index d74b600dd7..3bdc0a1171 100644
--- a/net/spdy/spdy_credential_builder.h
+++ b/net/spdy/spdy_credential_builder.h
@@ -8,7 +8,6 @@
#include <string>
#include "net/base/net_export.h"
-#include "net/ssl/ssl_client_cert_type.h"
namespace net {
@@ -20,7 +19,6 @@ struct SpdyCredential;
class NET_EXPORT_PRIVATE SpdyCredentialBuilder {
public:
static int Build(const std::string& tls_unique,
- SSLClientCertType type,
const std::string& key,
const std::string& cert,
size_t slot,
diff --git a/net/spdy/spdy_credential_builder_unittest.cc b/net/spdy/spdy_credential_builder_unittest.cc
index 89332d5a7f..bc67cc593a 100644
--- a/net/spdy/spdy_credential_builder_unittest.cc
+++ b/net/spdy/spdy_credential_builder_unittest.cc
@@ -30,16 +30,12 @@ void CreateCertAndKey(std::string* cert, std::string* key) {
sequenced_worker_pool));
TestCompletionCallback callback;
- std::vector<uint8> requested_cert_types;
- requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
- SSLClientCertType cert_type;
ServerBoundCertService::RequestHandle request_handle;
int rv = server_bound_cert_service->GetDomainBoundCert(
- "www.google.com", requested_cert_types, &cert_type, key, cert,
+ "www.google.com", key, cert,
callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type);
sequenced_worker_pool->Shutdown();
}
@@ -53,13 +49,9 @@ class SpdyCredentialBuilderTest : public testing::Test {
}
protected:
- int BuildWithType(SSLClientCertType type) {
- return SpdyCredentialBuilder::Build(
- MockClientSocket::kTlsUnique, type, key_, cert_, kSlot, &credential_);
- }
-
int Build() {
- return BuildWithType(CLIENT_CERT_ECDSA_SIGN);
+ return SpdyCredentialBuilder::Build(
+ MockClientSocket::kTlsUnique, key_, cert_, kSlot, &credential_);
}
std::string GetCredentialSecret() {
@@ -89,35 +81,13 @@ TEST_F(SpdyCredentialBuilderTest, MAYBE_GetCredentialSecret) {
}
#if defined(USE_OPENSSL)
-#define MAYBE_SucceedsWithECDSACert DISABLED_SucceedsWithECDSACert
-#else
-#define MAYBE_SucceedsWithECDSACert SucceedsWithECDSACert
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_SucceedsWithECDSACert) {
- EXPECT_EQ(OK, BuildWithType(CLIENT_CERT_ECDSA_SIGN));
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_FailsWithRSACert DISABLED_FailsWithRSACert
-#else
-#define MAYBE_FailsWithRSACert FailsWithRSACert
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_FailsWithRSACert) {
- EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
- BuildWithType(CLIENT_CERT_RSA_SIGN));
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_FailsWithDSACert DISABLED_FailsWithDSACert
+#define MAYBE_Succeeds DISABLED_Succeeds
#else
-#define MAYBE_FailsWithDSACert FailsWithDSACert
+#define MAYBE_Succeeds Succeeds
#endif
-TEST_F(SpdyCredentialBuilderTest, MAYBE_FailsWithDSACert) {
- EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
- BuildWithType(CLIENT_CERT_DSS_SIGN));
+TEST_F(SpdyCredentialBuilderTest, MAYBE_Succeeds) {
+ EXPECT_EQ(OK, Build());
}
#if defined(USE_OPENSSL)
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index 04a8ecade0..55387cf410 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -540,23 +540,18 @@ void GetECServerBoundCertAndProof(
std::string* cert,
std::string* proof) {
TestCompletionCallback callback;
- std::vector<uint8> requested_cert_types;
- requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
- SSLClientCertType cert_type;
std::string key;
ServerBoundCertService::RequestHandle request_handle;
int rv = server_bound_cert_service->GetDomainBoundCert(
- host, requested_cert_types, &cert_type, &key, cert, callback.callback(),
+ host, &key, cert, callback.callback(),
&request_handle);
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type);
SpdyCredential credential;
EXPECT_EQ(OK,
SpdyCredentialBuilder::Build(
- MockClientSocket::kTlsUnique, cert_type, key,
- *cert, 2, &credential));
+ MockClientSocket::kTlsUnique, key, *cert, 2, &credential));
ASSERT_FALSE(credential.certs.empty());
cert->assign(credential.certs[0]);
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 8a730cec34..db47549374 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -793,7 +793,6 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
int SpdySession::CreateCredentialFrame(
const std::string& origin,
- SSLClientCertType type,
const std::string& key,
const std::string& cert,
RequestPriority priority,
@@ -807,7 +806,7 @@ int SpdySession::CreateCredentialFrame(
std::string tls_unique;
ssl_socket->GetTLSUniqueChannelBinding(&tls_unique);
size_t slot = credential_state_.SetHasCredential(GURL(origin));
- int rv = SpdyCredentialBuilder::Build(tls_unique, type, key, cert, slot,
+ int rv = SpdyCredentialBuilder::Build(tls_unique, key, cert, slot,
&credential);
DCHECK_NE(rv, ERR_IO_PENDING);
if (rv != OK)
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index c6a22e67dd..819db111b2 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -35,7 +35,6 @@
#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_stream.h"
#include "net/spdy/spdy_write_queue.h"
-#include "net/ssl/ssl_client_cert_type.h"
#include "net/ssl/ssl_config_service.h"
#include "url/gurl.h"
@@ -299,7 +298,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// |credential_frame| and returns OK. Returns the error (guaranteed
// to not be ERR_IO_PENDING) otherwise.
int CreateCredentialFrame(const std::string& origin,
- SSLClientCertType type,
const std::string& key,
const std::string& cert,
RequestPriority priority,
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index db085cfd82..18d20e8d3a 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -108,7 +108,6 @@ SpdyStream::SpdyStream(SpdyStreamType type,
net_log_(net_log),
send_bytes_(0),
recv_bytes_(0),
- domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE),
just_completed_frame_type_(DATA),
just_completed_frame_size_(0) {
CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
@@ -741,11 +740,10 @@ int SpdyStream::DoGetDomainBoundCert() {
io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE;
ServerBoundCertService* sbc_service = session_->GetServerBoundCertService();
DCHECK(sbc_service != NULL);
- std::vector<uint8> requested_cert_types;
- requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
int rv = sbc_service->GetDomainBoundCert(
- url.GetOrigin().host(), requested_cert_types,
- &domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_,
+ url.GetOrigin().host(),
+ &domain_bound_private_key_,
+ &domain_bound_cert_,
base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()),
&domain_bound_cert_request_handle_);
return rv;
@@ -771,8 +769,11 @@ int SpdyStream::DoSendDomainBoundCert() {
origin.erase(origin.length() - 1); // Trim trailing slash.
scoped_ptr<SpdyFrame> frame;
int rv = session_->CreateCredentialFrame(
- origin, domain_bound_cert_type_, domain_bound_private_key_,
- domain_bound_cert_, priority_, &frame);
+ origin,
+ domain_bound_private_key_,
+ domain_bound_cert_,
+ priority_,
+ &frame);
if (rv != OK) {
DCHECK_NE(rv, ERR_IO_PENDING);
return rv;
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
index 06209a1779..4d18e3eff3 100644
--- a/net/spdy/spdy_stream.h
+++ b/net/spdy/spdy_stream.h
@@ -541,7 +541,6 @@ class NET_EXPORT_PRIVATE SpdyStream {
// Data received before delegate is attached.
ScopedVector<SpdyBuffer> pending_buffers_;
- SSLClientCertType domain_bound_cert_type_;
std::string domain_bound_private_key_;
std::string domain_bound_cert_;
ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_;
diff --git a/net/ssl/default_server_bound_cert_store.cc b/net/ssl/default_server_bound_cert_store.cc
index b189661899..6fb9180e87 100644
--- a/net/ssl/default_server_bound_cert_store.cc
+++ b/net/ssl/default_server_bound_cert_store.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "net/base/net_errors.h"
namespace net {
@@ -60,16 +61,15 @@ DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() {
void DefaultServerBoundCertStore::GetServerBoundCertTask::Run(
DefaultServerBoundCertStore* store) {
- SSLClientCertType type = CLIENT_CERT_INVALID_TYPE;
base::Time expiration_time;
std::string private_key_result;
std::string cert_result;
- bool was_sync = store->GetServerBoundCert(
- server_identifier_, &type, &expiration_time, &private_key_result,
+ int err = store->GetServerBoundCert(
+ server_identifier_, &expiration_time, &private_key_result,
&cert_result, GetCertCallback());
- DCHECK(was_sync);
+ DCHECK(err != ERR_IO_PENDING);
- InvokeCallback(base::Bind(callback_, server_identifier_, type,
+ InvokeCallback(base::Bind(callback_, err, server_identifier_,
expiration_time, private_key_result, cert_result));
}
@@ -79,7 +79,6 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask
: public DefaultServerBoundCertStore::Task {
public:
SetServerBoundCertTask(const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
@@ -89,7 +88,6 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask
private:
std::string server_identifier_;
- SSLClientCertType type_;
base::Time creation_time_;
base::Time expiration_time_;
std::string private_key_;
@@ -98,13 +96,11 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask
DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
const std::string& cert)
: server_identifier_(server_identifier),
- type_(type),
creation_time_(creation_time),
expiration_time_(expiration_time),
private_key_(private_key),
@@ -116,7 +112,7 @@ DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() {
void DefaultServerBoundCertStore::SetServerBoundCertTask::Run(
DefaultServerBoundCertStore* store) {
- store->SyncSetServerBoundCert(server_identifier_, type_, creation_time_,
+ store->SyncSetServerBoundCert(server_identifier_, creation_time_,
expiration_time_, private_key_, cert_);
}
@@ -236,9 +232,8 @@ DefaultServerBoundCertStore::DefaultServerBoundCertStore(
store_(store),
weak_ptr_factory_(this) {}
-bool DefaultServerBoundCertStore::GetServerBoundCert(
+int DefaultServerBoundCertStore::GetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType* type,
base::Time* expiration_time,
std::string* private_key_result,
std::string* cert_result,
@@ -249,34 +244,30 @@ bool DefaultServerBoundCertStore::GetServerBoundCert(
if (!loaded_) {
EnqueueTask(scoped_ptr<Task>(
new GetServerBoundCertTask(server_identifier, callback)));
- return false;
+ return ERR_IO_PENDING;
}
ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier);
- if (it == server_bound_certs_.end()) {
- *type = CLIENT_CERT_INVALID_TYPE;
- return true;
- }
+ if (it == server_bound_certs_.end())
+ return ERR_FILE_NOT_FOUND;
ServerBoundCert* cert = it->second;
- *type = cert->type();
*expiration_time = cert->expiration_time();
*private_key_result = cert->private_key();
*cert_result = cert->cert();
- return true;
+ return OK;
}
void DefaultServerBoundCertStore::SetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
const std::string& cert) {
RunOrEnqueueTask(scoped_ptr<Task>(new SetServerBoundCertTask(
- server_identifier, type, creation_time, expiration_time, private_key,
+ server_identifier, creation_time, expiration_time, private_key,
cert)));
}
@@ -377,7 +368,6 @@ void DefaultServerBoundCertStore::OnLoaded(
void DefaultServerBoundCertStore::SyncSetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
@@ -389,7 +379,7 @@ void DefaultServerBoundCertStore::SyncSetServerBoundCert(
InternalInsertServerBoundCert(
server_identifier,
new ServerBoundCert(
- server_identifier, type, creation_time, expiration_time, private_key,
+ server_identifier, creation_time, expiration_time, private_key,
cert));
}
diff --git a/net/ssl/default_server_bound_cert_store.h b/net/ssl/default_server_bound_cert_store.h
index 8ec680562c..61282182f8 100644
--- a/net/ssl/default_server_bound_cert_store.h
+++ b/net/ssl/default_server_bound_cert_store.h
@@ -43,16 +43,14 @@ class NET_EXPORT DefaultServerBoundCertStore : public ServerBoundCertStore {
virtual ~DefaultServerBoundCertStore();
// ServerBoundCertStore implementation.
- virtual bool GetServerBoundCert(
+ virtual int GetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType* type,
base::Time* expiration_time,
std::string* private_key_result,
std::string* cert_result,
const GetCertCallback& callback) OVERRIDE;
virtual void SetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
@@ -110,7 +108,6 @@ class NET_EXPORT DefaultServerBoundCertStore : public ServerBoundCertStore {
// initialization is complete.
void SyncSetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
diff --git a/net/ssl/default_server_bound_cert_store_unittest.cc b/net/ssl/default_server_bound_cert_store_unittest.cc
index 8673916435..c3f8452fa9 100644
--- a/net/ssl/default_server_bound_cert_store_unittest.cc
+++ b/net/ssl/default_server_bound_cert_store_unittest.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -27,8 +28,8 @@ void NotCalled() {
ADD_FAILURE() << "Unexpected callback execution.";
}
-void GetCertCallbackNotCalled(const std::string& server_identifier,
- SSLClientCertType type,
+void GetCertCallbackNotCalled(int err,
+ const std::string& server_identifier,
base::Time expiration_time,
const std::string& private_key_result,
const std::string& cert_result) {
@@ -39,21 +40,21 @@ class AsyncGetCertHelper {
public:
AsyncGetCertHelper() : called_(false) {}
- void Callback(const std::string& server_identifier,
- SSLClientCertType type,
+ void Callback(int err,
+ const std::string& server_identifier,
base::Time expiration_time,
const std::string& private_key_result,
const std::string& cert_result) {
+ err_ = err;
server_identifier_ = server_identifier;
- type_ = type;
expiration_time_ = expiration_time;
private_key_ = private_key_result;
cert_ = cert_result;
called_ = true;
}
+ int err_;
std::string server_identifier_;
- SSLClientCertType type_;
base::Time expiration_time_;
std::string private_key_;
std::string cert_;
@@ -127,14 +128,12 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) {
persistent_store->AddServerBoundCert(
DefaultServerBoundCertStore::ServerBoundCert(
"google.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b"));
persistent_store->AddServerBoundCert(
DefaultServerBoundCertStore::ServerBoundCert(
"verisign.com",
- CLIENT_CERT_ECDSA_SIGN,
base::Time(),
base::Time(),
"c", "d"));
@@ -145,7 +144,6 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) {
EXPECT_EQ(0, store.GetCertCount());
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"e", "f");
@@ -154,7 +152,6 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) {
EXPECT_EQ(2, store.GetCertCount());
store.SetServerBoundCert(
"twitter.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"g", "h");
@@ -166,32 +163,28 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) {
TEST(DefaultServerBoundCertStoreTest, TestSettingAndGetting) {
// No persistent store, all calls will be synchronous.
DefaultServerBoundCertStore store(NULL);
- SSLClientCertType type;
base::Time expiration_time;
std::string private_key, cert;
EXPECT_EQ(0, store.GetCertCount());
- EXPECT_TRUE(store.GetServerBoundCert("verisign.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type);
+ EXPECT_EQ(ERR_FILE_NOT_FOUND,
+ store.GetServerBoundCert("verisign.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
EXPECT_TRUE(private_key.empty());
EXPECT_TRUE(cert.empty());
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time::FromInternalValue(123),
base::Time::FromInternalValue(456),
"i", "j");
- EXPECT_TRUE(store.GetServerBoundCert("verisign.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type);
+ EXPECT_EQ(OK,
+ store.GetServerBoundCert("verisign.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
EXPECT_EQ(456, expiration_time.ToInternalValue());
EXPECT_EQ("i", private_key);
EXPECT_EQ("j", cert);
@@ -201,19 +194,16 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
DefaultServerBoundCertStore store(persistent_store.get());
- SSLClientCertType type;
base::Time expiration_time;
std::string private_key, cert;
EXPECT_EQ(0, store.GetCertCount());
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time::FromInternalValue(123),
base::Time::FromInternalValue(1234),
"a", "b");
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_ECDSA_SIGN,
base::Time::FromInternalValue(456),
base::Time::FromInternalValue(4567),
"c", "d");
@@ -221,13 +211,12 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) {
// Wait for load & queued set tasks.
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, store.GetCertCount());
- EXPECT_TRUE(store.GetServerBoundCert("verisign.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type);
+ EXPECT_EQ(OK,
+ store.GetServerBoundCert("verisign.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
EXPECT_EQ(4567, expiration_time.ToInternalValue());
EXPECT_EQ("c", private_key);
EXPECT_EQ("d", cert);
@@ -237,29 +226,31 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncGet) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time::FromInternalValue(123),
base::Time::FromInternalValue(1234),
"a", "b"));
DefaultServerBoundCertStore store(persistent_store.get());
AsyncGetCertHelper helper;
- SSLClientCertType type;
base::Time expiration_time;
std::string private_key;
std::string cert = "not set";
EXPECT_EQ(0, store.GetCertCount());
- EXPECT_FALSE(store.GetServerBoundCert(
- "verisign.com", &type, &expiration_time, &private_key, &cert,
- base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&helper))));
+ EXPECT_EQ(ERR_IO_PENDING,
+ store.GetServerBoundCert("verisign.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&AsyncGetCertHelper::Callback,
+ base::Unretained(&helper))));
// Wait for load & queued get tasks.
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, store.GetCertCount());
EXPECT_EQ("not set", cert);
EXPECT_TRUE(helper.called_);
+ EXPECT_EQ(OK, helper.err_);
EXPECT_EQ("verisign.com", helper.server_identifier_);
- EXPECT_EQ(CLIENT_CERT_RSA_SIGN, helper.type_);
EXPECT_EQ(1234, helper.expiration_time_.ToInternalValue());
EXPECT_EQ("a", helper.private_key_);
EXPECT_EQ("b", helper.cert_);
@@ -271,19 +262,16 @@ TEST(DefaultServerBoundCertStoreTest, TestDeleteAll) {
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b");
store.SetServerBoundCert(
"google.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"c", "d");
store.SetServerBoundCert(
"harvard.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"e", "f");
@@ -301,13 +289,11 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncGetAndDeleteAll) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b"));
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"google.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"c", "d"));
@@ -333,13 +319,11 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
DefaultServerBoundCertStore store(persistent_store.get());
- SSLClientCertType type;
base::Time expiration_time;
std::string private_key, cert;
EXPECT_EQ(0, store.GetCertCount());
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b");
@@ -348,7 +332,6 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) {
store.SetServerBoundCert(
"google.com",
- CLIENT_CERT_ECDSA_SIGN,
base::Time(),
base::Time(),
"c", "d");
@@ -359,45 +342,40 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) {
base::Bind(&CallCounter, &delete_finished));
ASSERT_EQ(1, delete_finished);
EXPECT_EQ(1, store.GetCertCount());
- EXPECT_TRUE(store.GetServerBoundCert("verisign.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type);
- EXPECT_TRUE(store.GetServerBoundCert("google.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type);
+ EXPECT_EQ(ERR_FILE_NOT_FOUND,
+ store.GetServerBoundCert("verisign.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
+ EXPECT_EQ(OK,
+ store.GetServerBoundCert("google.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
int delete2_finished = 0;
store.DeleteServerBoundCert("google.com",
base::Bind(&CallCounter, &delete2_finished));
ASSERT_EQ(1, delete2_finished);
EXPECT_EQ(0, store.GetCertCount());
- EXPECT_TRUE(store.GetServerBoundCert("google.com",
- &type,
- &expiration_time,
- &private_key,
- &cert,
- base::Bind(&GetCertCallbackNotCalled)));
- EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type);
+ EXPECT_EQ(ERR_FILE_NOT_FOUND,
+ store.GetServerBoundCert("google.com",
+ &expiration_time,
+ &private_key,
+ &cert,
+ base::Bind(&GetCertCallbackNotCalled)));
}
TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"a.com",
- CLIENT_CERT_RSA_SIGN,
base::Time::FromInternalValue(1),
base::Time::FromInternalValue(2),
"a", "b"));
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"b.com",
- CLIENT_CERT_RSA_SIGN,
base::Time::FromInternalValue(3),
base::Time::FromInternalValue(4),
"c", "d"));
@@ -408,17 +386,20 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) {
AsyncGetCertHelper a_helper;
AsyncGetCertHelper b_helper;
- SSLClientCertType type;
base::Time expiration_time;
std::string private_key;
std::string cert = "not set";
EXPECT_EQ(0, store.GetCertCount());
- EXPECT_FALSE(store.GetServerBoundCert(
- "a.com", &type, &expiration_time, &private_key, &cert,
- base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&a_helper))));
- EXPECT_FALSE(store.GetServerBoundCert(
- "b.com", &type, &expiration_time, &private_key, &cert,
- base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&b_helper))));
+ EXPECT_EQ(ERR_IO_PENDING,
+ store.GetServerBoundCert(
+ "a.com", &expiration_time, &private_key, &cert,
+ base::Bind(&AsyncGetCertHelper::Callback,
+ base::Unretained(&a_helper))));
+ EXPECT_EQ(ERR_IO_PENDING,
+ store.GetServerBoundCert(
+ "b.com", &expiration_time, &private_key, &cert,
+ base::Bind(&AsyncGetCertHelper::Callback,
+ base::Unretained(&b_helper))));
EXPECT_EQ(0, delete_finished);
EXPECT_FALSE(a_helper.called_);
@@ -429,14 +410,14 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) {
EXPECT_EQ(1, store.GetCertCount());
EXPECT_EQ("not set", cert);
EXPECT_TRUE(a_helper.called_);
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, a_helper.err_);
EXPECT_EQ("a.com", a_helper.server_identifier_);
- EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, a_helper.type_);
EXPECT_EQ(0, a_helper.expiration_time_.ToInternalValue());
EXPECT_EQ("", a_helper.private_key_);
EXPECT_EQ("", a_helper.cert_);
EXPECT_TRUE(b_helper.called_);
+ EXPECT_EQ(OK, b_helper.err_);
EXPECT_EQ("b.com", b_helper.server_identifier_);
- EXPECT_EQ(CLIENT_CERT_RSA_SIGN, b_helper.type_);
EXPECT_EQ(4, b_helper.expiration_time_.ToInternalValue());
EXPECT_EQ("c", b_helper.private_key_);
EXPECT_EQ("d", b_helper.cert_);
@@ -449,25 +430,21 @@ TEST(DefaultServerBoundCertStoreTest, TestGetAll) {
EXPECT_EQ(0, store.GetCertCount());
store.SetServerBoundCert(
"verisign.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b");
store.SetServerBoundCert(
"google.com",
- CLIENT_CERT_ECDSA_SIGN,
base::Time(),
base::Time(),
"c", "d");
store.SetServerBoundCert(
"harvard.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"e", "f");
store.SetServerBoundCert(
"mit.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"g", "h");
@@ -486,13 +463,11 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) {
store.SetServerBoundCert(
"preexisting.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b");
store.SetServerBoundCert(
"both.com",
- CLIENT_CERT_ECDSA_SIGN,
base::Time(),
base::Time(),
"c", "d");
@@ -503,14 +478,12 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) {
ServerBoundCertStore::ServerBoundCertList source_certs;
source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
"both.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
// Key differs from above to test that existing entries are overwritten.
"e", "f"));
source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
"copied.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"g", "h"));
@@ -538,13 +511,11 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) {
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"preexisting.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"a", "b"));
persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
"both.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"c", "d"));
@@ -553,14 +524,12 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) {
ServerBoundCertStore::ServerBoundCertList source_certs;
source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
"both.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
// Key differs from above to test that existing entries are overwritten.
"e", "f"));
source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
"copied.com",
- CLIENT_CERT_RSA_SIGN,
base::Time(),
base::Time(),
"g", "h"));
diff --git a/net/ssl/server_bound_cert_service.cc b/net/ssl/server_bound_cert_service.cc
index 37404699f2..4bc82ed5d9 100644
--- a/net/ssl/server_bound_cert_service.cc
+++ b/net/ssl/server_bound_cert_service.cc
@@ -42,15 +42,6 @@ const int kValidityPeriodInDays = 365;
// while.
const int kSystemTimeValidityBufferInDays = 90;
-bool IsSupportedCertType(uint8 type) {
- switch(type) {
- case CLIENT_CERT_ECDSA_SIGN:
- return true;
- default:
- return false;
- }
-}
-
// Used by the GetDomainBoundCertResult histogram to record the final
// outcome of each GetDomainBoundCert call. Do not re-use values.
enum GetCertResult {
@@ -96,7 +87,6 @@ void RecordGetCertTime(base::TimeDelta request_time) {
// unjoined thread, due to relying on a non-leaked LazyInstance
scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert(
const std::string& server_identifier,
- SSLClientCertType type,
uint32 serial_number,
int* error) {
scoped_ptr<ServerBoundCertStore::ServerBoundCert> result;
@@ -107,34 +97,25 @@ scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert(
not_valid_before + base::TimeDelta::FromDays(kValidityPeriodInDays);
std::string der_cert;
std::vector<uint8> private_key_info;
- switch (type) {
- case CLIENT_CERT_ECDSA_SIGN: {
- scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create());
- if (!key.get()) {
- DLOG(ERROR) << "Unable to create key pair for client";
- *error = ERR_KEY_GENERATION_FAILED;
- return result.Pass();
- }
- if (!x509_util::CreateDomainBoundCertEC(key.get(), server_identifier,
- serial_number, not_valid_before,
- not_valid_after, &der_cert)) {
- DLOG(ERROR) << "Unable to create x509 cert for client";
- *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
- return result.Pass();
- }
+ scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create());
+ if (!key.get()) {
+ DLOG(ERROR) << "Unable to create key pair for client";
+ *error = ERR_KEY_GENERATION_FAILED;
+ return result.Pass();
+ }
+ if (!x509_util::CreateDomainBoundCertEC(key.get(), server_identifier,
+ serial_number, not_valid_before,
+ not_valid_after, &der_cert)) {
+ DLOG(ERROR) << "Unable to create x509 cert for client";
+ *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
+ return result.Pass();
+ }
- if (!key->ExportEncryptedPrivateKey(ServerBoundCertService::kEPKIPassword,
- 1, &private_key_info)) {
- DLOG(ERROR) << "Unable to export private key";
- *error = ERR_PRIVATE_KEY_EXPORT_FAILED;
- return result.Pass();
- }
- break;
- }
- default:
- NOTREACHED();
- *error = ERR_INVALID_ARGUMENT;
- return result.Pass();
+ if (!key->ExportEncryptedPrivateKey(ServerBoundCertService::kEPKIPassword,
+ 1, &private_key_info)) {
+ DLOG(ERROR) << "Unable to export private key";
+ *error = ERR_PRIVATE_KEY_EXPORT_FAILED;
+ return result.Pass();
}
// TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
@@ -142,7 +123,10 @@ scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert(
std::string key_out(private_key_info.begin(), private_key_info.end());
result.reset(new ServerBoundCertStore::ServerBoundCert(
- server_identifier, type, not_valid_before, not_valid_after, key_out,
+ server_identifier,
+ not_valid_before,
+ not_valid_after,
+ key_out,
der_cert));
UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime",
base::TimeTicks::Now() - start,
@@ -160,12 +144,10 @@ class ServerBoundCertServiceRequest {
public:
ServerBoundCertServiceRequest(base::TimeTicks request_start,
const CompletionCallback& callback,
- SSLClientCertType* type,
std::string* private_key,
std::string* cert)
: request_start_(request_start),
callback_(callback),
- type_(type),
private_key_(private_key),
cert_(cert) {
}
@@ -174,7 +156,6 @@ class ServerBoundCertServiceRequest {
void Cancel() {
RecordGetDomainBoundCertResult(ASYNC_CANCELLED);
callback_.Reset();
- type_ = NULL;
private_key_ = NULL;
cert_ = NULL;
}
@@ -182,7 +163,6 @@ class ServerBoundCertServiceRequest {
// Copies the contents of |private_key| and |cert| to the caller's output
// arguments and calls the callback.
void Post(int error,
- SSLClientCertType type,
const std::string& private_key,
const std::string& cert) {
switch (error) {
@@ -214,7 +194,6 @@ class ServerBoundCertServiceRequest {
break;
}
if (!callback_.is_null()) {
- *type_ = type;
*private_key_ = private_key;
*cert_ = cert;
callback_.Run(error);
@@ -227,7 +206,6 @@ class ServerBoundCertServiceRequest {
private:
base::TimeTicks request_start_;
CompletionCallback callback_;
- SSLClientCertType* type_;
std::string* private_key_;
std::string* cert_;
};
@@ -244,10 +222,8 @@ class ServerBoundCertServiceWorker {
ServerBoundCertServiceWorker(
const std::string& server_identifier,
- SSLClientCertType type,
const WorkerDoneCallback& callback)
: server_identifier_(server_identifier),
- type_(type),
serial_number_(base::RandInt(0, std::numeric_limits<int>::max())),
origin_loop_(base::MessageLoopProxy::current()),
callback_(callback) {
@@ -269,9 +245,8 @@ class ServerBoundCertServiceWorker {
// Runs on a worker thread.
int error = ERR_FAILED;
scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert =
- GenerateCert(server_identifier_, type_, serial_number_, &error);
- DVLOG(1) << "GenerateCert " << server_identifier_ << " " << type_
- << " returned " << error;
+ GenerateCert(server_identifier_, serial_number_, &error);
+ DVLOG(1) << "GenerateCert " << server_identifier_ << " returned " << error;
#if defined(USE_NSS)
// Detach the thread from NSPR.
// Calling NSS functions attaches the thread to NSPR, which stores
@@ -288,7 +263,6 @@ class ServerBoundCertServiceWorker {
}
const std::string server_identifier_;
- const SSLClientCertType type_;
// Note that serial_number_ must be initialized on a non-worker thread
// (see documentation for GenerateCert).
uint32 serial_number_;
@@ -303,31 +277,25 @@ class ServerBoundCertServiceWorker {
// origin message loop.
class ServerBoundCertServiceJob {
public:
- ServerBoundCertServiceJob(SSLClientCertType type)
- : type_(type) {
- }
+ ServerBoundCertServiceJob() { }
~ServerBoundCertServiceJob() {
if (!requests_.empty())
DeleteAllCanceled();
}
- SSLClientCertType type() const { return type_; }
-
void AddRequest(ServerBoundCertServiceRequest* request) {
requests_.push_back(request);
}
void HandleResult(int error,
- SSLClientCertType type,
const std::string& private_key,
const std::string& cert) {
- PostAll(error, type, private_key, cert);
+ PostAll(error, private_key, cert);
}
private:
void PostAll(int error,
- SSLClientCertType type,
const std::string& private_key,
const std::string& cert) {
std::vector<ServerBoundCertServiceRequest*> requests;
@@ -335,7 +303,7 @@ class ServerBoundCertServiceJob {
for (std::vector<ServerBoundCertServiceRequest*>::iterator
i = requests.begin(); i != requests.end(); i++) {
- (*i)->Post(error, type, private_key, cert);
+ (*i)->Post(error, private_key, cert);
// Post() causes the ServerBoundCertServiceRequest to delete itself.
}
}
@@ -352,7 +320,6 @@ class ServerBoundCertServiceJob {
}
std::vector<ServerBoundCertServiceRequest*> requests_;
- SSLClientCertType type_;
};
// static
@@ -399,7 +366,8 @@ ServerBoundCertService::ServerBoundCertService(
weak_ptr_factory_(this),
requests_(0),
cert_store_hits_(0),
- inflight_joins_(0) {
+ inflight_joins_(0),
+ workers_created_(0) {
base::Time start = base::Time::Now();
base::Time end = start + base::TimeDelta::FromDays(
kValidityPeriodInDays + kSystemTimeValidityBufferInDays);
@@ -422,20 +390,15 @@ std::string ServerBoundCertService::GetDomainForHost(const std::string& host) {
int ServerBoundCertService::GetDomainBoundCert(
const std::string& host,
- const std::vector<uint8>& requested_types,
- SSLClientCertType* type,
std::string* private_key,
std::string* cert,
const CompletionCallback& callback,
RequestHandle* out_req) {
- DVLOG(1) << __FUNCTION__ << " " << host << " "
- << (requested_types.empty() ? -1 : requested_types[0])
- << (requested_types.size() > 1 ? "..." : "");
+ DVLOG(1) << __FUNCTION__ << " " << host;
DCHECK(CalledOnValidThread());
base::TimeTicks request_start = base::TimeTicks::Now();
- if (callback.is_null() || !private_key || !cert || host.empty() ||
- requested_types.empty()) {
+ if (callback.is_null() || !private_key || !cert || host.empty()) {
RecordGetDomainBoundCertResult(INVALID_ARGUMENT);
return ERR_INVALID_ARGUMENT;
}
@@ -446,19 +409,6 @@ int ServerBoundCertService::GetDomainBoundCert(
return ERR_INVALID_ARGUMENT;
}
- SSLClientCertType preferred_type = CLIENT_CERT_INVALID_TYPE;
- for (size_t i = 0; i < requested_types.size(); ++i) {
- if (IsSupportedCertType(requested_types[i])) {
- preferred_type = static_cast<SSLClientCertType>(requested_types[i]);
- break;
- }
- }
- if (preferred_type == CLIENT_CERT_INVALID_TYPE) {
- RecordGetDomainBoundCertResult(UNSUPPORTED_TYPE);
- // None of the requested types are supported.
- return ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED;
- }
-
requests_++;
// See if an identical request is currently in flight.
@@ -469,26 +419,13 @@ int ServerBoundCertService::GetDomainBoundCert(
// An identical request is in flight already. We'll just attach our
// callback.
job = j->second;
- // Check that the job is for an acceptable type of cert.
- if (std::find(requested_types.begin(), requested_types.end(), job->type())
- == requested_types.end()) {
- DVLOG(1) << "Found inflight job of wrong type " << job->type()
- << " for " << domain;
- // If we get here, the server is asking for different types of certs in
- // short succession. This probably means the server is broken or
- // misconfigured. Since we only store one type of cert per domain, we
- // are unable to handle this well. Just return an error and let the first
- // job finish.
- RecordGetDomainBoundCertResult(TYPE_MISMATCH);
- return ERR_ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH;
- }
inflight_joins_++;
ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest(
request_start,
base::Bind(&RequestHandle::OnRequestComplete,
base::Unretained(out_req)),
- type, private_key, cert);
+ private_key, cert);
job->AddRequest(request);
out_req->RequestStarted(this, request, callback);
return ERR_IO_PENDING;
@@ -498,30 +435,30 @@ int ServerBoundCertService::GetDomainBoundCert(
// domain. Note that |expiration_time| is ignored, and expired certs are
// considered valid.
base::Time expiration_time;
- if (server_bound_cert_store_->GetServerBoundCert(
- domain,
- type,
- &expiration_time /* ignored */,
- private_key,
- cert,
- base::Bind(&ServerBoundCertService::GotServerBoundCert,
- weak_ptr_factory_.GetWeakPtr()))) {
- if (IsSupportedCertType(*type)) {
- // Sync lookup found a valid cert.
- DVLOG(1) << "Cert store had valid cert for " << domain
- << " of type " << *type;
- cert_store_hits_++;
- RecordGetDomainBoundCertResult(SYNC_SUCCESS);
- base::TimeDelta request_time = base::TimeTicks::Now() - request_start;
- UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time);
- RecordGetCertTime(request_time);
- return OK;
- }
+ int err = server_bound_cert_store_->GetServerBoundCert(
+ domain,
+ &expiration_time /* ignored */,
+ private_key,
+ cert,
+ base::Bind(&ServerBoundCertService::GotServerBoundCert,
+ weak_ptr_factory_.GetWeakPtr()));
+ if (err == OK) {
+ // Sync lookup found a valid cert.
+ DVLOG(1) << "Cert store had valid cert for " << domain;
+ cert_store_hits_++;
+ RecordGetDomainBoundCertResult(SYNC_SUCCESS);
+ base::TimeDelta request_time = base::TimeTicks::Now() - request_start;
+ UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time);
+ RecordGetCertTime(request_time);
+ return OK;
+ }
+
+ if (err == ERR_FILE_NOT_FOUND) {
// Sync lookup did not find a valid cert. Start generating a new one.
+ workers_created_++;
ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker(
domain,
- preferred_type,
base::Bind(&ServerBoundCertService::GeneratedServerBoundCert,
weak_ptr_factory_.GetWeakPtr()));
if (!worker->Start(task_runner_)) {
@@ -532,23 +469,28 @@ int ServerBoundCertService::GetDomainBoundCert(
}
}
- // We are either waiting for async DB lookup, or waiting for cert generation.
- // Create a job & request to track it.
- job = new ServerBoundCertServiceJob(preferred_type);
- inflight_[domain] = job;
-
- ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest(
- request_start,
- base::Bind(&RequestHandle::OnRequestComplete, base::Unretained(out_req)),
- type, private_key, cert);
- job->AddRequest(request);
- out_req->RequestStarted(this, request, callback);
- return ERR_IO_PENDING;
+ if (err == ERR_IO_PENDING || err == ERR_FILE_NOT_FOUND) {
+ // We are either waiting for async DB lookup, or waiting for cert
+ // generation. Create a job & request to track it.
+ job = new ServerBoundCertServiceJob();
+ inflight_[domain] = job;
+
+ ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest(
+ request_start,
+ base::Bind(&RequestHandle::OnRequestComplete,
+ base::Unretained(out_req)),
+ private_key, cert);
+ job->AddRequest(request);
+ out_req->RequestStarted(this, request, callback);
+ return ERR_IO_PENDING;
+ }
+
+ return err;
}
void ServerBoundCertService::GotServerBoundCert(
+ int err,
const std::string& server_identifier,
- SSLClientCertType type,
base::Time expiration_time,
const std::string& key,
const std::string& cert) {
@@ -560,22 +502,19 @@ void ServerBoundCertService::GotServerBoundCert(
NOTREACHED();
return;
}
- ServerBoundCertServiceJob* job = j->second;
- if (IsSupportedCertType(type)) {
+ if (err == OK) {
// Async DB lookup found a valid cert.
- DVLOG(1) << "Cert store had valid cert for " << server_identifier
- << " of type " << type;
+ DVLOG(1) << "Cert store had valid cert for " << server_identifier;
cert_store_hits_++;
// ServerBoundCertServiceRequest::Post will do the histograms and stuff.
- HandleResult(OK, server_identifier, type, key, cert);
+ HandleResult(OK, server_identifier, key, cert);
return;
}
-
// Async lookup did not find a valid cert. Start generating a new one.
+ workers_created_++;
ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker(
server_identifier,
- job->type(),
base::Bind(&ServerBoundCertService::GeneratedServerBoundCert,
weak_ptr_factory_.GetWeakPtr()));
if (!worker->Start(task_runner_)) {
@@ -583,7 +522,6 @@ void ServerBoundCertService::GotServerBoundCert(
LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started.";
HandleResult(ERR_INSUFFICIENT_RESOURCES,
server_identifier,
- CLIENT_CERT_INVALID_TYPE,
std::string(),
std::string());
return;
@@ -609,24 +547,21 @@ void ServerBoundCertService::GeneratedServerBoundCert(
// TODO(mattm): we should just Pass() the cert object to
// SetServerBoundCert().
server_bound_cert_store_->SetServerBoundCert(
- cert->server_identifier(), cert->type(), cert->creation_time(),
- cert->expiration_time(), cert->private_key(), cert->cert());
+ cert->server_identifier(),
+ cert->creation_time(),
+ cert->expiration_time(),
+ cert->private_key(),
+ cert->cert());
- HandleResult(error, server_identifier, cert->type(), cert->private_key(),
- cert->cert());
+ HandleResult(error, server_identifier, cert->private_key(), cert->cert());
} else {
- HandleResult(error,
- server_identifier,
- CLIENT_CERT_INVALID_TYPE,
- std::string(),
- std::string());
+ HandleResult(error, server_identifier, std::string(), std::string());
}
}
void ServerBoundCertService::HandleResult(
int error,
const std::string& server_identifier,
- SSLClientCertType type,
const std::string& private_key,
const std::string& cert) {
DCHECK(CalledOnValidThread());
@@ -640,7 +575,7 @@ void ServerBoundCertService::HandleResult(
ServerBoundCertServiceJob* job = j->second;
inflight_.erase(j);
- job->HandleResult(error, type, private_key, cert);
+ job->HandleResult(error, private_key, cert);
delete job;
}
diff --git a/net/ssl/server_bound_cert_service.h b/net/ssl/server_bound_cert_service.h
index dd5059071a..d931ec8708 100644
--- a/net/ssl/server_bound_cert_service.h
+++ b/net/ssl/server_bound_cert_service.h
@@ -17,7 +17,6 @@
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/ssl/server_bound_cert_store.h"
-#include "net/ssl/ssl_client_cert_type.h"
namespace base {
class TaskRunner;
@@ -92,17 +91,13 @@ class NET_EXPORT ServerBoundCertService
// longer hold.
bool IsSystemTimeValid() const { return is_system_time_valid_; }
- // Fetches the domain bound cert for the specified host of the specified
- // type if one exists and creates one otherwise. Returns OK if successful or
- // an error code upon failure.
- //
- // |requested_types| is a list of the TLS ClientCertificateTypes the site will
- // accept, ordered from most preferred to least preferred. Types we don't
- // support will be ignored. See ssl_client_cert_type.h.
+ // Fetches the domain bound cert for the specified host if one exists and
+ // creates one otherwise. Returns OK if successful or an error code upon
+ // failure.
//
// On successful completion, |private_key| stores a DER-encoded
- // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate, and
- // |type| specifies the type of certificate that was returned.
+ // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate.
+ // The PrivateKeyInfo is always an ECDSA private key.
//
// |callback| must not be null. ERR_IO_PENDING is returned if the operation
// could not be completed immediately, in which case the result code will
@@ -113,8 +108,6 @@ class NET_EXPORT ServerBoundCertService
// ServerBoundCertService is destroyed.
int GetDomainBoundCert(
const std::string& host,
- const std::vector<uint8>& requested_types,
- SSLClientCertType* type,
std::string* private_key,
std::string* cert,
const CompletionCallback& callback,
@@ -128,6 +121,7 @@ class NET_EXPORT ServerBoundCertService
uint64 requests() const { return requests_; }
uint64 cert_store_hits() const { return cert_store_hits_; }
uint64 inflight_joins() const { return inflight_joins_; }
+ uint64 workers_created() const { return workers_created_; }
private:
// Cancels the specified request. |req| is the handle stored by
@@ -135,8 +129,8 @@ class NET_EXPORT ServerBoundCertService
// callback will not be called.
void CancelRequest(ServerBoundCertServiceRequest* req);
- void GotServerBoundCert(const std::string& server_identifier,
- SSLClientCertType type,
+ void GotServerBoundCert(int err,
+ const std::string& server_identifier,
base::Time expiration_time,
const std::string& key,
const std::string& cert);
@@ -146,7 +140,6 @@ class NET_EXPORT ServerBoundCertService
scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert);
void HandleResult(int error,
const std::string& server_identifier,
- SSLClientCertType type,
const std::string& private_key,
const std::string& cert);
@@ -161,6 +154,7 @@ class NET_EXPORT ServerBoundCertService
uint64 requests_;
uint64 cert_store_hits_;
uint64 inflight_joins_;
+ uint64 workers_created_;
bool is_system_time_valid_;
diff --git a/net/ssl/server_bound_cert_service_unittest.cc b/net/ssl/server_bound_cert_service_unittest.cc
index 37a86a483a..0063f49603 100644
--- a/net/ssl/server_bound_cert_service_unittest.cc
+++ b/net/ssl/server_bound_cert_service_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/task_runner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "crypto/ec_private_key.h"
#include "net/base/net_errors.h"
@@ -47,6 +48,66 @@ class ServerBoundCertServiceTest : public testing::Test {
scoped_ptr<ServerBoundCertService> service_;
};
+class MockServerBoundCertStoreWithAsyncGet
+ : public DefaultServerBoundCertStore {
+ public:
+ MockServerBoundCertStoreWithAsyncGet()
+ : DefaultServerBoundCertStore(NULL), cert_count_(0) {}
+
+ virtual int GetServerBoundCert(const std::string& server_identifier,
+ base::Time* expiration_time,
+ std::string* private_key_result,
+ std::string* cert_result,
+ const GetCertCallback& callback) OVERRIDE;
+
+ virtual void SetServerBoundCert(const std::string& server_identifier,
+ base::Time creation_time,
+ base::Time expiration_time,
+ const std::string& private_key,
+ const std::string& cert) OVERRIDE {
+ cert_count_ = 1;
+ }
+
+ virtual int GetCertCount() OVERRIDE { return cert_count_; }
+
+ void CallGetServerBoundCertCallbackWithResult(int err,
+ base::Time expiration_time,
+ const std::string& private_key,
+ const std::string& cert);
+
+ private:
+ GetCertCallback callback_;
+ std::string server_identifier_;
+ int cert_count_;
+};
+
+int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert(
+ const std::string& server_identifier,
+ base::Time* expiration_time,
+ std::string* private_key_result,
+ std::string* cert_result,
+ const GetCertCallback& callback) {
+ server_identifier_ = server_identifier;
+ callback_ = callback;
+ // Reset the cert count, it'll get incremented in either SetServerBoundCert or
+ // CallGetServerBoundCertCallbackWithResult.
+ cert_count_ = 0;
+ // Do nothing else: the results to be provided will be specified through
+ // CallGetServerBoundCertCallbackWithResult.
+ return ERR_IO_PENDING;
+}
+
+void
+MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult(
+ int err,
+ base::Time expiration_time,
+ const std::string& private_key,
+ const std::string& cert) {
+ if (err == OK)
+ cert_count_ = 1;
+ callback_.Run(err, server_identifier_, expiration_time, private_key, cert);
+}
+
TEST_F(ServerBoundCertServiceTest, GetDomainForHost) {
EXPECT_EQ("google.com",
ServerBoundCertService::GetDomainForHost("google.com"));
@@ -73,38 +134,32 @@ TEST_F(ServerBoundCertServiceTest, CacheHit) {
std::string host("encrypted.google.com");
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
TestCompletionCallback callback;
ServerBoundCertService::RequestHandle request_handle;
// Asynchronous completion.
- SSLClientCertType type1;
std::string private_key_info1, der_cert1;
EXPECT_EQ(0, service_->cert_count());
error = service_->GetDomainBoundCert(
- host, types, &type1, &private_key_info1, &der_cert1,
+ host, &private_key_info1, &der_cert1,
callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle.is_active());
error = callback.WaitForResult();
EXPECT_EQ(OK, error);
EXPECT_EQ(1, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
EXPECT_FALSE(private_key_info1.empty());
EXPECT_FALSE(der_cert1.empty());
EXPECT_FALSE(request_handle.is_active());
// Synchronous completion.
- SSLClientCertType type2;
std::string private_key_info2, der_cert2;
error = service_->GetDomainBoundCert(
- host, types, &type2, &private_key_info2, &der_cert2,
+ host, &private_key_info2, &der_cert2,
callback.callback(), &request_handle);
EXPECT_FALSE(request_handle.is_active());
EXPECT_EQ(OK, error);
EXPECT_EQ(1, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
EXPECT_EQ(private_key_info1, private_key_info2);
EXPECT_EQ(der_cert1, der_cert2);
@@ -113,97 +168,16 @@ TEST_F(ServerBoundCertServiceTest, CacheHit) {
EXPECT_EQ(0u, service_->inflight_joins());
}
-TEST_F(ServerBoundCertServiceTest, UnsupportedTypes) {
- std::string host("encrypted.google.com");
-
- int error;
- std::vector<uint8> types;
- TestCompletionCallback callback;
- ServerBoundCertService::RequestHandle request_handle;
-
- // Empty requested_types.
- SSLClientCertType type1;
- std::string private_key_info1, der_cert1;
- error = service_->GetDomainBoundCert(
- host, types, &type1, &private_key_info1, &der_cert1,
- callback.callback(), &request_handle);
- EXPECT_EQ(ERR_INVALID_ARGUMENT, error);
- EXPECT_FALSE(request_handle.is_active());
-
- // No supported types in requested_types.
- types.push_back(CLIENT_CERT_RSA_SIGN);
- types.push_back(2);
- types.push_back(3);
- error = service_->GetDomainBoundCert(
- host, types, &type1, &private_key_info1, &der_cert1,
- callback.callback(), &request_handle);
- EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, error);
- EXPECT_FALSE(request_handle.is_active());
-
- // Supported types after unsupported ones in requested_types.
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
- // Asynchronous completion.
- EXPECT_EQ(0, service_->cert_count());
- error = service_->GetDomainBoundCert(
- host, types, &type1, &private_key_info1, &der_cert1,
- callback.callback(), &request_handle);
- EXPECT_EQ(ERR_IO_PENDING, error);
- EXPECT_TRUE(request_handle.is_active());
- error = callback.WaitForResult();
- EXPECT_EQ(OK, error);
- EXPECT_EQ(1, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
- EXPECT_FALSE(private_key_info1.empty());
- EXPECT_FALSE(der_cert1.empty());
-
- // Now that the cert is created, doing requests for unsupported types
- // shouldn't affect the created cert.
- // Empty requested_types.
- types.clear();
- SSLClientCertType type2;
- std::string private_key_info2, der_cert2;
- error = service_->GetDomainBoundCert(
- host, types, &type2, &private_key_info2, &der_cert2,
- callback.callback(), &request_handle);
- EXPECT_EQ(ERR_INVALID_ARGUMENT, error);
- EXPECT_FALSE(request_handle.is_active());
-
- // No supported types in requested_types.
- types.push_back(CLIENT_CERT_RSA_SIGN);
- types.push_back(2);
- types.push_back(3);
- error = service_->GetDomainBoundCert(
- host, types, &type2, &private_key_info2, &der_cert2,
- callback.callback(), &request_handle);
- EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, error);
- EXPECT_FALSE(request_handle.is_active());
-
- // If we request EC, the cert we created before should still be there.
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
- error = service_->GetDomainBoundCert(
- host, types, &type2, &private_key_info2, &der_cert2,
- callback.callback(), &request_handle);
- EXPECT_FALSE(request_handle.is_active());
- EXPECT_EQ(OK, error);
- EXPECT_EQ(1, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
- EXPECT_EQ(private_key_info1, private_key_info2);
- EXPECT_EQ(der_cert1, der_cert2);
-}
-
TEST_F(ServerBoundCertServiceTest, StoreCerts) {
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
TestCompletionCallback callback;
ServerBoundCertService::RequestHandle request_handle;
std::string host1("encrypted.google.com");
- SSLClientCertType type1;
std::string private_key_info1, der_cert1;
EXPECT_EQ(0, service_->cert_count());
error = service_->GetDomainBoundCert(
- host1, types, &type1, &private_key_info1, &der_cert1,
+ host1, &private_key_info1, &der_cert1,
callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle.is_active());
@@ -212,10 +186,9 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) {
EXPECT_EQ(1, service_->cert_count());
std::string host2("www.verisign.com");
- SSLClientCertType type2;
std::string private_key_info2, der_cert2;
error = service_->GetDomainBoundCert(
- host2, types, &type2, &private_key_info2, &der_cert2,
+ host2, &private_key_info2, &der_cert2,
callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle.is_active());
@@ -224,10 +197,9 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) {
EXPECT_EQ(2, service_->cert_count());
std::string host3("www.twitter.com");
- SSLClientCertType type3;
std::string private_key_info3, der_cert3;
error = service_->GetDomainBoundCert(
- host3, types, &type3, &private_key_info3, &der_cert3,
+ host3, &private_key_info3, &der_cert3,
callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle.is_active());
@@ -241,38 +213,29 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) {
EXPECT_NE(der_cert1, der_cert3);
EXPECT_NE(private_key_info2, private_key_info3);
EXPECT_NE(der_cert2, der_cert3);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3);
}
// Tests an inflight join.
TEST_F(ServerBoundCertServiceTest, InflightJoin) {
std::string host("encrypted.google.com");
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
- SSLClientCertType type1;
std::string private_key_info1, der_cert1;
TestCompletionCallback callback1;
ServerBoundCertService::RequestHandle request_handle1;
- SSLClientCertType type2;
std::string private_key_info2, der_cert2;
TestCompletionCallback callback2;
ServerBoundCertService::RequestHandle request_handle2;
error = service_->GetDomainBoundCert(
- host, types, &type1, &private_key_info1, &der_cert1,
+ host, &private_key_info1, &der_cert1,
callback1.callback(), &request_handle1);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle1.is_active());
- // If we request RSA and EC in the 2nd request, should still join with the
- // original request.
- types.insert(types.begin(), CLIENT_CERT_RSA_SIGN);
+ // Should join with the original request.
error = service_->GetDomainBoundCert(
- host, types, &type2, &private_key_info2, &der_cert2,
+ host, &private_key_info2, &der_cert2,
callback2.callback(), &request_handle2);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle2.is_active());
@@ -282,8 +245,6 @@ TEST_F(ServerBoundCertServiceTest, InflightJoin) {
error = callback2.WaitForResult();
EXPECT_EQ(OK, error);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
EXPECT_EQ(2u, service_->requests());
EXPECT_EQ(0u, service_->cert_store_hits());
EXPECT_EQ(1u, service_->inflight_joins());
@@ -291,16 +252,13 @@ TEST_F(ServerBoundCertServiceTest, InflightJoin) {
TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) {
std::string host("encrypted.google.com");
- SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
TestCompletionCallback callback;
ServerBoundCertService::RequestHandle request_handle;
error = service_->GetDomainBoundCert(
- host, types, &type, &private_key_info, &der_cert, callback.callback(),
+ host, &private_key_info, &der_cert, callback.callback(),
&request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle.is_active());
@@ -329,16 +287,11 @@ TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) {
// Tests that the callback of a canceled request is never made.
TEST_F(ServerBoundCertServiceTest, CancelRequest) {
std::string host("encrypted.google.com");
- SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
ServerBoundCertService::RequestHandle request_handle;
error = service_->GetDomainBoundCert(host,
- types,
- &type,
&private_key_info,
&der_cert,
base::Bind(&FailTest),
@@ -362,17 +315,12 @@ TEST_F(ServerBoundCertServiceTest, CancelRequest) {
// Tests that destructing the RequestHandle cancels the request.
TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) {
std::string host("encrypted.google.com");
- SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
{
ServerBoundCertService::RequestHandle request_handle;
error = service_->GetDomainBoundCert(host,
- types,
- &type,
&private_key_info,
&der_cert,
base::Bind(&FailTest),
@@ -394,16 +342,11 @@ TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) {
TEST_F(ServerBoundCertServiceTest, DestructionWithPendingRequest) {
std::string host("encrypted.google.com");
- SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
ServerBoundCertService::RequestHandle request_handle;
error = service_->GetDomainBoundCert(host,
- types,
- &type,
&private_key_info,
&der_cert,
base::Bind(&FailTest),
@@ -438,16 +381,11 @@ TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) {
// Make a request that will force synchronous completion.
std::string host("encrypted.google.com");
- SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
ServerBoundCertService::RequestHandle request_handle;
error = service_->GetDomainBoundCert(host,
- types,
- &type,
&private_key_info,
&der_cert,
base::Bind(&FailTest),
@@ -460,30 +398,23 @@ TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) {
// Tests that simultaneous creation of different certs works.
TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
std::string host1("encrypted.google.com");
- SSLClientCertType type1;
std::string private_key_info1, der_cert1;
TestCompletionCallback callback1;
ServerBoundCertService::RequestHandle request_handle1;
std::string host2("foo.com");
- SSLClientCertType type2;
std::string private_key_info2, der_cert2;
TestCompletionCallback callback2;
ServerBoundCertService::RequestHandle request_handle2;
std::string host3("bar.com");
- SSLClientCertType type3;
std::string private_key_info3, der_cert3;
TestCompletionCallback callback3;
ServerBoundCertService::RequestHandle request_handle3;
error = service_->GetDomainBoundCert(host1,
- types,
- &type1,
&private_key_info1,
&der_cert1,
callback1.callback(),
@@ -492,8 +423,6 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
EXPECT_TRUE(request_handle1.is_active());
error = service_->GetDomainBoundCert(host2,
- types,
- &type2,
&private_key_info2,
&der_cert2,
callback2.callback(),
@@ -502,8 +431,6 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
EXPECT_TRUE(request_handle2.is_active());
error = service_->GetDomainBoundCert(host3,
- types,
- &type3,
&private_key_info3,
&der_cert3,
callback3.callback(),
@@ -513,19 +440,16 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
error = callback1.WaitForResult();
EXPECT_EQ(OK, error);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
EXPECT_FALSE(private_key_info1.empty());
EXPECT_FALSE(der_cert1.empty());
error = callback2.WaitForResult();
EXPECT_EQ(OK, error);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
EXPECT_FALSE(private_key_info2.empty());
EXPECT_FALSE(der_cert2.empty());
error = callback3.WaitForResult();
EXPECT_EQ(OK, error);
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3);
EXPECT_FALSE(private_key_info3.empty());
EXPECT_FALSE(der_cert3.empty());
@@ -545,13 +469,11 @@ TEST_F(ServerBoundCertServiceTest, Expiration) {
ServerBoundCertStore* store = service_->GetCertStore();
base::Time now = base::Time::Now();
store->SetServerBoundCert("good",
- CLIENT_CERT_ECDSA_SIGN,
now,
now + base::TimeDelta::FromDays(1),
"a",
"b");
store->SetServerBoundCert("expired",
- CLIENT_CERT_ECDSA_SIGN,
now - base::TimeDelta::FromDays(2),
now - base::TimeDelta::FromDays(1),
"c",
@@ -559,38 +481,99 @@ TEST_F(ServerBoundCertServiceTest, Expiration) {
EXPECT_EQ(2, service_->cert_count());
int error;
- std::vector<uint8> types;
- types.push_back(CLIENT_CERT_ECDSA_SIGN);
TestCompletionCallback callback;
ServerBoundCertService::RequestHandle request_handle;
// Cert is valid - synchronous completion.
- SSLClientCertType type1;
std::string private_key_info1, der_cert1;
error = service_->GetDomainBoundCert(
- "good", types, &type1, &private_key_info1, &der_cert1,
+ "good", &private_key_info1, &der_cert1,
callback.callback(), &request_handle);
EXPECT_EQ(OK, error);
EXPECT_FALSE(request_handle.is_active());
EXPECT_EQ(2, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
EXPECT_STREQ("a", private_key_info1.c_str());
EXPECT_STREQ("b", der_cert1.c_str());
// Expired cert is valid as well - synchronous completion.
- SSLClientCertType type2;
std::string private_key_info2, der_cert2;
error = service_->GetDomainBoundCert(
- "expired", types, &type2, &private_key_info2, &der_cert2,
+ "expired", &private_key_info2, &der_cert2,
callback.callback(), &request_handle);
EXPECT_EQ(OK, error);
EXPECT_FALSE(request_handle.is_active());
EXPECT_EQ(2, service_->cert_count());
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
EXPECT_STREQ("c", private_key_info2.c_str());
EXPECT_STREQ("d", der_cert2.c_str());
}
+TEST_F(ServerBoundCertServiceTest, AsyncStoreGetNoCertsInStore) {
+ MockServerBoundCertStoreWithAsyncGet* mock_store =
+ new MockServerBoundCertStoreWithAsyncGet();
+ service_ = scoped_ptr<ServerBoundCertService>(
+ new ServerBoundCertService(mock_store, sequenced_worker_pool_));
+
+ std::string host("encrypted.google.com");
+
+ int error;
+ TestCompletionCallback callback;
+ ServerBoundCertService::RequestHandle request_handle;
+
+ // Asynchronous completion with no certs in the store.
+ std::string private_key_info, der_cert;
+ EXPECT_EQ(0, service_->cert_count());
+ error = service_->GetDomainBoundCert(
+ host, &private_key_info, &der_cert, callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle.is_active());
+
+ mock_store->CallGetServerBoundCertCallbackWithResult(
+ ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string());
+
+ error = callback.WaitForResult();
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service_->cert_count());
+ EXPECT_FALSE(private_key_info.empty());
+ EXPECT_FALSE(der_cert.empty());
+ EXPECT_FALSE(request_handle.is_active());
+}
+
+TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOneCertInStore) {
+ MockServerBoundCertStoreWithAsyncGet* mock_store =
+ new MockServerBoundCertStoreWithAsyncGet();
+ service_ = scoped_ptr<ServerBoundCertService>(
+ new ServerBoundCertService(mock_store, sequenced_worker_pool_));
+
+ std::string host("encrypted.google.com");
+
+ int error;
+ TestCompletionCallback callback;
+ ServerBoundCertService::RequestHandle request_handle;
+
+ // Asynchronous completion with a cert in the store.
+ std::string private_key_info, der_cert;
+ EXPECT_EQ(0, service_->cert_count());
+ error = service_->GetDomainBoundCert(
+ host, &private_key_info, &der_cert, callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle.is_active());
+
+ mock_store->CallGetServerBoundCertCallbackWithResult(
+ OK, base::Time(), "ab", "cd");
+
+ error = callback.WaitForResult();
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service_->cert_count());
+ EXPECT_EQ(1u, service_->requests());
+ EXPECT_EQ(1u, service_->cert_store_hits());
+ // Because the cert was found in the store, no new workers should have been
+ // created.
+ EXPECT_EQ(0u, service_->workers_created());
+ EXPECT_STREQ("ab", private_key_info.c_str());
+ EXPECT_STREQ("cd", der_cert.c_str());
+ EXPECT_FALSE(request_handle.is_active());
+}
+
#endif // !defined(USE_OPENSSL)
} // namespace
diff --git a/net/ssl/server_bound_cert_store.cc b/net/ssl/server_bound_cert_store.cc
index d0d520dcb9..e778362c0b 100644
--- a/net/ssl/server_bound_cert_store.cc
+++ b/net/ssl/server_bound_cert_store.cc
@@ -6,19 +6,16 @@
namespace net {
-ServerBoundCertStore::ServerBoundCert::ServerBoundCert()
- : type_(CLIENT_CERT_INVALID_TYPE) {
+ServerBoundCertStore::ServerBoundCert::ServerBoundCert() {
}
ServerBoundCertStore::ServerBoundCert::ServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
const std::string& cert)
: server_identifier_(server_identifier),
- type_(type),
creation_time_(creation_time),
expiration_time_(expiration_time),
private_key_(private_key),
@@ -29,7 +26,7 @@ ServerBoundCertStore::ServerBoundCert::~ServerBoundCert() {}
void ServerBoundCertStore::InitializeFrom(const ServerBoundCertList& list) {
for (ServerBoundCertList::const_iterator i = list.begin(); i != list.end();
++i) {
- SetServerBoundCert(i->server_identifier(), i->type(), i->creation_time(),
+ SetServerBoundCert(i->server_identifier(), i->creation_time(),
i->expiration_time(), i->private_key(), i->cert());
}
}
diff --git a/net/ssl/server_bound_cert_store.h b/net/ssl/server_bound_cert_store.h
index ad0ecb0d8b..0de0f3eebd 100644
--- a/net/ssl/server_bound_cert_store.h
+++ b/net/ssl/server_bound_cert_store.h
@@ -12,7 +12,6 @@
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
-#include "net/ssl/ssl_client_cert_type.h"
namespace net {
@@ -27,12 +26,11 @@ class NET_EXPORT ServerBoundCertStore
: NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
// The ServerBoundCert class contains a private key in addition to the server
- // cert, and cert type.
+ // cert.
class NET_EXPORT ServerBoundCert {
public:
ServerBoundCert();
ServerBoundCert(const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
@@ -41,8 +39,6 @@ class NET_EXPORT ServerBoundCertStore
// Server identifier. For domain bound certs, for instance "verisign.com".
const std::string& server_identifier() const { return server_identifier_; }
- // TLS ClientCertificateType.
- SSLClientCertType type() const { return type_; }
// The time the certificate was created, also the start of the certificate
// validity period.
base::Time creation_time() const { return creation_time_; }
@@ -57,7 +53,6 @@ class NET_EXPORT ServerBoundCertStore
private:
std::string server_identifier_;
- SSLClientCertType type_;
base::Time creation_time_;
base::Time expiration_time_;
std::string private_key_;
@@ -67,8 +62,8 @@ class NET_EXPORT ServerBoundCertStore
typedef std::list<ServerBoundCert> ServerBoundCertList;
typedef base::Callback<void(
+ int,
const std::string&,
- SSLClientCertType,
base::Time,
const std::string&,
const std::string&)> GetCertCallback;
@@ -77,14 +72,13 @@ class NET_EXPORT ServerBoundCertStore
virtual ~ServerBoundCertStore() {}
// GetServerBoundCert may return the result synchronously through the
- // output parameters, in which case it will return true. Otherwise it will
- // return false and the callback will be called with the result
+ // output parameters, in which case it will return either OK if a cert is
+ // found in the store, or ERR_FILE_NOT_FOUND if none is found. If the
+ // result cannot be returned synchronously, GetServerBoundCert will
+ // return ERR_IO_PENDING and the callback will be called with the result
// asynchronously.
- // In either case, the type will be CLIENT_CERT_INVALID_TYPE if no cert
- // existed for the given |server_identifier|.
- virtual bool GetServerBoundCert(
+ virtual int GetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType* type,
base::Time* expiration_time,
std::string* private_key_result,
std::string* cert_result,
@@ -93,7 +87,6 @@ class NET_EXPORT ServerBoundCertStore
// Adds a server bound cert and the corresponding private key to the store.
virtual void SetServerBoundCert(
const std::string& server_identifier,
- SSLClientCertType type,
base::Time creation_time,
base::Time expiration_time,
const std::string& private_key,
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium
index d183ca8451..ae77651f6f 100644
--- a/net/third_party/nss/README.chromium
+++ b/net/third_party/nss/README.chromium
@@ -75,10 +75,6 @@ Patches:
patches/cbc.patch
https://code.google.com/p/chromium/issues/detail?id=172658#c12
- * Define AES_256_KEY_LENGTH if the system blapit.h header doesn't define it.
- Remove this patch when all system NSS packages are NSS 3.12.10 or later.
- patches/aes256keylength.patch
-
* Change ssl3_SuiteBOnly to always return PR_TRUE. The softoken in NSS
versions older than 3.15 report an EC key size range of 112 bits to 571
bits, even when it is compiled to support only the NIST P-256, P-384, and
diff --git a/net/third_party/nss/patches/aes256keylength.patch b/net/third_party/nss/patches/aes256keylength.patch
deleted file mode 100644
index 2fc2506297..0000000000
--- a/net/third_party/nss/patches/aes256keylength.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff -pu a/nss/lib/ssl/sslsnce.c b/nss/lib/ssl/sslsnce.c
---- a/nss/lib/ssl/sslsnce.c 2013-07-31 12:07:10.974699609 -0700
-+++ b/nss/lib/ssl/sslsnce.c 2013-07-31 14:12:33.185058439 -0700
-@@ -86,6 +86,11 @@
- #include "nspr.h"
- #include "sslmutex.h"
-
-+/* AES_256_KEY_LENGTH was added to blapit.h in NSS 3.12.10. */
-+#ifndef AES_256_KEY_LENGTH
-+#define AES_256_KEY_LENGTH 32 /* bytes */
-+#endif
-+
- /*
- ** Format of a cache entry in the shared memory.
- */
diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh
index 86444a22c2..81192a4d3b 100755
--- a/net/third_party/nss/patches/applypatches.sh
+++ b/net/third_party/nss/patches/applypatches.sh
@@ -38,8 +38,6 @@ patch -p4 < $patches_dir/secretexporterlocks.patch
patch -p4 < $patches_dir/cbc.patch
-patch -p4 < $patches_dir/aes256keylength.patch
-
patch -p4 < $patches_dir/suitebonly.patch
patch -p4 < $patches_dir/secitemarray.patch
diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp
index 49cfbd8732..fc526733c0 100644
--- a/net/third_party/nss/ssl.gyp
+++ b/net/third_party/nss/ssl.gyp
@@ -68,7 +68,6 @@
'ssl/win32err.c',
'ssl/win32err.h',
'ssl/bodge/secitem_array.c',
- 'ssl/bodge/secure_memcmp.c',
],
'sources!': [
'ssl/os2_err.c',
diff --git a/net/third_party/nss/ssl/bodge/secure_memcmp.c b/net/third_party/nss/ssl/bodge/secure_memcmp.c
deleted file mode 100644
index b18579c6ea..0000000000
--- a/net/third_party/nss/ssl/bodge/secure_memcmp.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// This file exists to provide the secure memcmp function. This was added in
-// NSS 3.12.5.
-
-#include <stdlib.h>
-
-/*
- * Perform a constant-time compare of two memory regions. The return value is
- * 0 if the memory regions are equal and non-zero otherwise.
- */
-int
-NSS_SecureMemcmp(const void *ia, const void *ib, size_t n)
-{
- const unsigned char *a = (const unsigned char*) ia;
- const unsigned char *b = (const unsigned char*) ib;
- size_t i;
- unsigned char r = 0;
-
- for (i = 0; i < n; ++i) {
- r |= *a++ ^ *b++;
- }
-
- return r;
-}
diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c
index 4b8825a717..b0446adc17 100644
--- a/net/third_party/nss/ssl/sslsnce.c
+++ b/net/third_party/nss/ssl/sslsnce.c
@@ -86,11 +86,6 @@
#include "nspr.h"
#include "sslmutex.h"
-/* AES_256_KEY_LENGTH was added to blapit.h in NSS 3.12.10. */
-#ifndef AES_256_KEY_LENGTH
-#define AES_256_KEY_LENGTH 32 /* bytes */
-#endif
-
/*
** Format of a cache entry in the shared memory.
*/
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 36a9d4b9d0..d18525f634 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -179,6 +179,19 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
}
}
+/* static */
+void QuicServer::MaybeDispatchPacket(QuicDispatcher* dispatcher,
+ const QuicEncryptedPacket& packet,
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address) {
+ QuicGuid guid;
+ if (!QuicFramer::ReadGuidFromPacket(packet, &guid)) {
+ return;
+ }
+
+ dispatcher->ProcessPacket(server_address, client_address, guid, packet);
+}
+
bool QuicServer::ReadAndDispatchSinglePacket(int fd,
int port,
QuicDispatcher* dispatcher,
@@ -199,19 +212,9 @@ bool QuicServer::ReadAndDispatchSinglePacket(int fd,
}
QuicEncryptedPacket packet(buf, bytes_read, false);
- QuicGuid guid;
- QuicDataReader reader(packet.data(), packet.length());
- uint8 public_flags;
- if (!reader.ReadBytes(&public_flags, 1)) {
- LOG(DFATAL) << "Unable to read public flags.";
- return false;
- }
- if (!reader.ReadUInt64(&guid)) {
- return true; // We read, we just didn't like the results.
- }
IPEndPoint server_address(server_ip, port);
- dispatcher->ProcessPacket(server_address, client_address, guid, packet);
+ MaybeDispatchPacket(dispatcher, packet, server_address, client_address);
return true;
}
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 63995665cc..142d1d1572 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -59,6 +59,14 @@ class QuicServer : public EpollCallbackInterface {
virtual void OnShutdown(EpollServer* eps, int fd) OVERRIDE {}
+ // Dispatches the given packet only if it looks like a valid QUIC packet.
+ // TODO(rjshade): Return a status describing why a packet was dropped, and log
+ // somehow. Maybe expose as a varz.
+ static void MaybeDispatchPacket(QuicDispatcher* dispatcher,
+ const QuicEncryptedPacket& packet,
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address);
+
bool overflow_supported() { return overflow_supported_; }
int packets_dropped() { return packets_dropped_; }
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc
new file mode 100644
index 0000000000..7d1d66939c
--- /dev/null
+++ b/net/tools/quic/quic_server_test.cc
@@ -0,0 +1,74 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/quic_server.h"
+
+#include "net/quic/crypto/quic_random.h"
+#include "net/quic/quic_utils.h"
+#include "net/tools/quic/test_tools/mock_quic_dispatcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace net {
+namespace tools {
+namespace test {
+
+namespace {
+
+class QuicServerDispatchPacketTest : public ::testing::Test {
+ public:
+ QuicServerDispatchPacketTest()
+ : crypto_config_("blah", QuicRandom::GetInstance()),
+ dispatcher_(config_, crypto_config_, 1234, &eps_) {}
+
+
+ void MaybeDispatchPacket(const QuicEncryptedPacket& packet) {
+ IPEndPoint client_addr, server_addr;
+ QuicServer::MaybeDispatchPacket(&dispatcher_, packet,
+ client_addr, server_addr);
+ }
+
+ protected:
+ QuicConfig config_;
+ QuicCryptoServerConfig crypto_config_;
+ EpollServer eps_;
+ MockQuicDispatcher dispatcher_;
+};
+
+TEST_F(QuicServerDispatchPacketTest, DoNotDispatchPacketWithoutGUID) {
+ // Packet too short to be considered valid.
+ unsigned char invalid_packet[] = { 0x00 };
+ QuicEncryptedPacket encrypted_invalid_packet(
+ QuicUtils::AsChars(invalid_packet), arraysize(invalid_packet), false);
+
+ // We expect the invalid packet to be dropped, and ProcessPacket should never
+ // be called.
+ EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(0);
+ MaybeDispatchPacket(encrypted_invalid_packet);
+}
+
+TEST_F(QuicServerDispatchPacketTest, DispatchValidPacket) {
+ unsigned char valid_packet[] = {
+ // public flags (8 byte guid)
+ 0x3C,
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags
+ 0x00 };
+ QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
+ arraysize(valid_packet), false);
+
+ EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(1);
+ MaybeDispatchPacket(encrypted_valid_packet);
+}
+
+} // namespace
+} // namespace test
+} // namespace tools
+} // namespace net
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.cc b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
new file mode 100644
index 0000000000..3a2b1d9825
--- /dev/null
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
@@ -0,0 +1,21 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/mock_quic_dispatcher.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+MockQuicDispatcher::MockQuicDispatcher(
+ const QuicConfig& config,
+ const QuicCryptoServerConfig& crypto_config,
+ QuicGuid guid,
+ EpollServer* eps)
+ : QuicDispatcher(config, crypto_config, guid, eps) { }
+MockQuicDispatcher::~MockQuicDispatcher() {}
+
+} // namespace test
+} // namespace tools
+} // namespace net
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.h b/net/tools/quic/test_tools/mock_quic_dispatcher.h
new file mode 100644
index 0000000000..563ab0de5f
--- /dev/null
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.h
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
+
+#include "net/base/ip_endpoint.h"
+#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/quic_config.h"
+#include "net/quic/quic_protocol.h"
+#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/quic/quic_dispatcher.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+class MockQuicDispatcher : public QuicDispatcher {
+ public:
+ MockQuicDispatcher(const QuicConfig& config,
+ const QuicCryptoServerConfig& crypto_config,
+ QuicGuid guid,
+ EpollServer* eps);
+ virtual ~MockQuicDispatcher();
+
+ MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
+ const IPEndPoint& client_address,
+ QuicGuid guid,
+ const QuicEncryptedPacket& packet));
+};
+
+} // namespace test
+} // namespace tools
+} // namespace net
+
+#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_