summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/base/cert_database.h5
-rw-r--r--net/base/cert_database_nss.cc6
-rw-r--r--net/base/cert_test_util.cc56
-rw-r--r--net/base/cert_test_util.h2
-rw-r--r--net/base/cert_type.h10
-rw-r--r--net/base/connection_type_histograms.h5
-rw-r--r--net/base/cookie_monster.cc41
-rw-r--r--net/base/cookie_monster_perftest.cc4
-rw-r--r--net/base/cookie_monster_unittest.cc17
-rw-r--r--net/base/directory_lister_unittest.cc12
-rw-r--r--net/base/ev_root_ca_metadata.cc84
-rw-r--r--net/base/ev_root_ca_metadata.h27
-rw-r--r--net/base/host_resolver.h13
-rw-r--r--net/base/host_resolver_impl.cc38
-rw-r--r--net/base/host_resolver_impl_unittest.cc84
-rw-r--r--net/base/listen_socket.cc4
-rw-r--r--net/base/mime_util.cc4
-rw-r--r--net/base/mock_host_resolver.cc4
-rw-r--r--net/base/net_error_list.h14
-rw-r--r--net/base/net_log_event_type_list.h11
-rw-r--r--net/base/net_test_suite.h6
-rw-r--r--net/base/net_util.cc91
-rw-r--r--net/base/net_util.h31
-rw-r--r--net/base/net_util_unittest.cc117
-rw-r--r--net/base/network_config_watcher_mac.cc88
-rw-r--r--net/base/network_config_watcher_mac.h15
-rw-r--r--net/base/openssl_util.cc4
-rw-r--r--net/base/openssl_util.h8
-rw-r--r--net/base/ssl_cipher_suite_names.cc26
-rw-r--r--net/base/ssl_cipher_suite_names.h6
-rw-r--r--net/base/ssl_config_service.cc13
-rw-r--r--net/base/ssl_config_service.h6
-rw-r--r--net/base/ssl_config_service_win.cc8
-rw-r--r--net/base/ssl_connection_status_flags.h23
-rw-r--r--net/base/ssl_false_start_blacklist.cc4
-rw-r--r--net/base/ssl_false_start_blacklist.h2
-rw-r--r--net/base/ssl_false_start_blacklist.txt4444
-rw-r--r--net/base/ssl_false_start_blacklist_process.cc65
-rw-r--r--net/base/ssl_info.h5
-rw-r--r--net/base/transport_security_state.cc5
-rw-r--r--net/base/transport_security_state_unittest.cc3
-rw-r--r--net/base/x509_certificate.cc44
-rw-r--r--net/base/x509_certificate.h32
-rw-r--r--net/base/x509_certificate_mac.cc5
-rw-r--r--net/base/x509_certificate_openssl.cc96
-rw-r--r--net/base/x509_certificate_unittest.cc76
-rw-r--r--net/base/x509_certificate_win.cc157
-rw-r--r--net/base/x509_openssl_util.cc113
-rw-r--r--net/base/x509_openssl_util.h39
-rw-r--r--net/data/ftp/dir-listing-ls-192
-rw-r--r--net/data/ftp/dir-listing-ls-19.expected8
-rw-r--r--net/data/valgrind/DIRECTORY_MOVED4
-rw-r--r--net/data/valgrind/net_unittests.gtest-drmemory_win32.txt14
-rw-r--r--net/data/valgrind/net_unittests.gtest-memcheck.txt19
-rw-r--r--net/data/valgrind/net_unittests.gtest-tsan.txt18
-rw-r--r--net/data/valgrind/net_unittests.gtest-tsan_mac.txt8
-rw-r--r--net/data/valgrind/net_unittests.gtest-tsan_win32.txt35
-rw-r--r--net/data/valgrind/net_unittests.gtest.txt6
-rw-r--r--net/data/valgrind/net_unittests.gtest_linux.txt3
-rw-r--r--net/data/valgrind/net_unittests.gtest_mac.txt2
-rw-r--r--net/data/valgrind/net_unittests.gtest_wine.txt49
-rw-r--r--net/data/valgrind/suppressions.txt39
-rw-r--r--net/disk_cache/backend_impl.cc20
-rw-r--r--net/disk_cache/backend_impl.h3
-rw-r--r--net/disk_cache/backend_unittest.cc28
-rw-r--r--net/disk_cache/disk_cache_perftest.cc8
-rw-r--r--net/disk_cache/entry_impl.cc32
-rw-r--r--net/disk_cache/entry_unittest.cc191
-rw-r--r--net/disk_cache/file_posix.cc14
-rw-r--r--net/disk_cache/in_flight_backend_io.cc131
-rw-r--r--net/disk_cache/in_flight_backend_io.h21
-rw-r--r--net/disk_cache/in_flight_io.cc4
-rw-r--r--net/disk_cache/mem_entry_impl.cc8
-rw-r--r--net/disk_cache/sparse_control.cc24
-rw-r--r--net/disk_cache/stats_histogram.cc8
-rw-r--r--net/disk_cache/stats_histogram.h1
-rw-r--r--net/disk_cache/stress_cache.cc6
-rw-r--r--net/ftp/ftp_ctrl_response_buffer.cc2
-rw-r--r--net/ftp/ftp_directory_listing_buffer_unittest.cc1
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.cc24
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls_unittest.cc28
-rw-r--r--net/ftp/ftp_directory_listing_parser_mlsd.cc18
-rw-r--r--net/ftp/ftp_network_transaction.cc11
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc57
-rw-r--r--net/ftp/ftp_util.cc16
-rw-r--r--net/http/des.cc9
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc7
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h7
-rw-r--r--net/http/http_auth.h3
-rw-r--r--net/http/http_auth_handler_basic.cc2
-rw-r--r--net/http/http_auth_handler_digest.cc9
-rw-r--r--net/http/http_auth_unittest.cc44
-rw-r--r--net/http/http_basic_stream.cc25
-rw-r--r--net/http/http_basic_stream.h11
-rw-r--r--net/http/http_cache.cc12
-rw-r--r--net/http/http_cache.h6
-rw-r--r--net/http/http_cache_transaction.cc2
-rw-r--r--net/http/http_cache_unittest.cc24
-rw-r--r--net/http/http_chunked_decoder.cc2
-rw-r--r--net/http/http_network_transaction.cc55
-rw-r--r--net/http/http_network_transaction.h3
-rw-r--r--net/http/http_network_transaction_unittest.cc155
-rw-r--r--net/http/http_proxy_client_socket.cc14
-rw-r--r--net/http/http_proxy_client_socket.h1
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc3
-rw-r--r--net/http/http_response_body_drainer_unittest.cc2
-rw-r--r--net/http/http_response_headers.cc28
-rw-r--r--net/http/http_response_headers_unittest.cc80
-rw-r--r--net/http/http_response_info.cc1
-rw-r--r--net/http/http_stream.h5
-rw-r--r--net/http/http_stream_parser.cc19
-rw-r--r--net/http/http_stream_request.cc24
-rw-r--r--net/http/http_transaction_unittest.cc2
-rw-r--r--net/http/http_util.cc25
-rw-r--r--net/http/http_util.h27
-rw-r--r--net/http/http_util_unittest.cc123
-rw-r--r--net/net.gyp77
-rw-r--r--net/ocsp/nss_ocsp.cc281
-rw-r--r--net/proxy/init_proxy_resolver.cc8
-rw-r--r--net/proxy/multi_threaded_proxy_resolver.cc10
-rw-r--r--net/proxy/proxy_bypass_rules.cc14
-rw-r--r--net/proxy/proxy_config_service_win.cc8
-rw-r--r--net/proxy/proxy_script_fetcher_impl_unittest.cc18
-rw-r--r--net/proxy/proxy_service.cc14
-rw-r--r--net/server/http_listen_socket.cc4
-rw-r--r--net/socket/client_socket.cc8
-rw-r--r--net/socket/client_socket.h8
-rw-r--r--net/socket/client_socket_factory.cc24
-rw-r--r--net/socket/client_socket_factory.h7
-rw-r--r--net/socket/client_socket_handle.cc3
-rw-r--r--net/socket/client_socket_pool_base.cc26
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc8
-rw-r--r--net/socket/deterministic_socket_data_unittest.cc4
-rw-r--r--net/socket/dns_cert_provenance_check.cc111
-rw-r--r--net/socket/dns_cert_provenance_check.h26
-rw-r--r--net/socket/socket_test_util.cc10
-rw-r--r--net/socket/socket_test_util.h9
-rw-r--r--net/socket/socks5_client_socket.cc37
-rw-r--r--net/socket/socks5_client_socket.h1
-rw-r--r--net/socket/socks5_client_socket_unittest.cc2
-rw-r--r--net/socket/socks_client_socket.cc9
-rw-r--r--net/socket/socks_client_socket.h1
-rw-r--r--net/socket/socks_client_socket_unittest.cc2
-rw-r--r--net/socket/ssl_client_socket_mac.cc12
-rw-r--r--net/socket/ssl_client_socket_mac.h1
-rw-r--r--net/socket/ssl_client_socket_mac_factory.cc3
-rw-r--r--net/socket/ssl_client_socket_mac_factory.h4
-rw-r--r--net/socket/ssl_client_socket_nss.cc882
-rw-r--r--net/socket/ssl_client_socket_nss.h48
-rw-r--r--net/socket/ssl_client_socket_nss_factory.cc17
-rw-r--r--net/socket/ssl_client_socket_nss_factory.h4
-rw-r--r--net/socket/ssl_client_socket_openssl.cc8
-rw-r--r--net/socket/ssl_client_socket_openssl.h1
-rw-r--r--net/socket/ssl_client_socket_pool.cc6
-rw-r--r--net/socket/ssl_client_socket_unittest.cc45
-rw-r--r--net/socket/ssl_client_socket_win.cc8
-rw-r--r--net/socket/ssl_client_socket_win.h1
-rw-r--r--net/socket/ssl_host_info.cc79
-rw-r--r--net/socket/ssl_host_info.h52
-rw-r--r--net/socket/tcp_client_socket.cc19
-rw-r--r--net/socket/tcp_client_socket.h7
-rw-r--r--net/socket/tcp_client_socket_libevent.cc77
-rw-r--r--net/socket/tcp_client_socket_libevent.h13
-rw-r--r--net/socket/tcp_client_socket_pool.cc8
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc22
-rw-r--r--net/socket/tcp_client_socket_unittest.cc28
-rw-r--r--net/socket/tcp_client_socket_win.cc22
-rw-r--r--net/socket/tcp_client_socket_win.h4
-rw-r--r--net/socket_stream/socket_stream.cc11
-rw-r--r--net/socket_stream/socket_stream_unittest.cc8
-rw-r--r--net/spdy/spdy_http_stream.cc10
-rw-r--r--net/spdy/spdy_http_stream.h2
-rw-r--r--net/spdy/spdy_http_stream_unittest.cc6
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc128
-rw-r--r--net/spdy/spdy_proxy_client_socket.cc15
-rw-r--r--net/spdy/spdy_proxy_client_socket.h1
-rw-r--r--net/spdy/spdy_session.cc80
-rw-r--r--net/spdy/spdy_session.h11
-rw-r--r--net/spdy/spdy_session_pool.cc28
-rw-r--r--net/spdy/spdy_session_unittest.cc8
-rw-r--r--net/spdy/spdy_stream.cc37
-rw-r--r--net/spdy/spdy_stream_unittest.cc4
-rw-r--r--net/spdy/spdy_test_util.cc59
-rw-r--r--net/spdy/spdy_test_util.h8
-rw-r--r--net/test/test_server.cc177
-rw-r--r--net/test/test_server.h88
-rw-r--r--net/test/test_server_posix.cc52
-rw-r--r--net/test/test_server_win.cc90
-rw-r--r--net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp9
-rw-r--r--net/third_party/nss/ssl.gyp14
-rw-r--r--net/third_party/nss/ssl/snapstart.c7
-rw-r--r--net/third_party/nss/ssl/ssl.def1
-rw-r--r--net/third_party/nss/ssl/ssl.h40
-rw-r--r--net/third_party/nss/ssl/ssl3con.c117
-rw-r--r--net/third_party/nss/ssl/ssl3ext.c2
-rw-r--r--net/third_party/nss/ssl/sslauth.c58
-rw-r--r--net/third_party/nss/ssl/sslimpl.h80
-rw-r--r--net/third_party/nss/ssl/sslnonce.c5
-rw-r--r--net/third_party/nss/ssl/sslplatf.c561
-rw-r--r--net/third_party/nss/ssl/sslsnce.c5
-rw-r--r--net/third_party/nss/ssl/sslsock.c14
-rw-r--r--net/tools/fetch/fetch_client.cc2
-rw-r--r--net/tools/fetch/http_listen_socket.cc4
-rwxr-xr-x[-rw-r--r--]net/tools/testserver/testserver.py73
-rw-r--r--net/tools/testserver/xmppserver.py527
-rw-r--r--net/tools/testserver/xmppserver_test.py250
-rw-r--r--net/url_request/url_request.cc8
-rw-r--r--net/url_request/url_request.h4
-rw-r--r--net/url_request/url_request_file_job.cc18
-rw-r--r--net/url_request/url_request_file_job.h3
-rw-r--r--net/url_request/url_request_ftp_job.cc2
-rw-r--r--net/url_request/url_request_job.cc4
-rw-r--r--net/url_request/url_request_unittest.cc50
-rw-r--r--net/url_request/url_request_unittest.h4
-rw-r--r--net/url_request/view_cache_helper_unittest.cc4
-rw-r--r--net/websockets/websocket.cc6
-rw-r--r--net/websockets/websocket_job.cc7
-rw-r--r--net/websockets/websocket_throttle_unittest.cc42
218 files changed, 10264 insertions, 2147 deletions
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 377c0a8..7915cc6 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -67,7 +67,7 @@ class CertDatabase {
// the platform cert database, or possibly other network error codes.
int AddUserCert(X509Certificate* cert);
-#if defined(USE_NSS)
+#if defined(USE_NSS) || defined(USE_OPENSSL)
// Get a list of unique certificates in the certificate database. (One
// instance of all certificates.)
void ListCerts(CertificateList* certs);
@@ -124,6 +124,9 @@ class CertDatabase {
// Returns true on success or false on failure.
// |cert| is still valid when this function returns.
bool DeleteCertAndKey(const X509Certificate* cert);
+
+ // Check whether cert is stored in a readonly slot.
+ bool IsReadOnly(const X509Certificate* cert) const;
#endif
private:
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc
index 8445d4d..a32a7a3 100644
--- a/net/base/cert_database_nss.cc
+++ b/net/base/cert_database_nss.cc
@@ -168,7 +168,6 @@ unsigned int CertDatabase::GetCertTrust(
trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL +
trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN;
case SERVER_CERT:
- case EMAIL_CERT:
return trust.HasTrustedPeer(PR_TRUE, PR_FALSE, PR_FALSE) * TRUSTED_SSL +
trust.HasTrustedPeer(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL +
trust.HasTrustedPeer(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN;
@@ -205,4 +204,9 @@ bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
return true;
}
+bool CertDatabase::IsReadOnly(const X509Certificate* cert) const {
+ PK11SlotInfo* slot = cert->os_cert_handle()->slot;
+ return slot && PK11_IsReadOnly(slot);
+}
+
} // namespace net
diff --git a/net/base/cert_test_util.cc b/net/base/cert_test_util.cc
index cb7f9a8..1042d50 100644
--- a/net/base/cert_test_util.cc
+++ b/net/base/cert_test_util.cc
@@ -26,9 +26,27 @@
namespace net {
#if defined(USE_OPENSSL)
-X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
+X509Certificate* AddTemporaryRootCertToStore(X509* x509_cert) {
OpenSSLInitSingleton* openssl_init = GetOpenSSLInitSingleton();
+ if (!X509_STORE_add_cert(openssl_init->x509_store(), x509_cert)) {
+ unsigned long error_code = ERR_get_error();
+ if (ERR_GET_LIB(error_code) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ do {
+ LOG(ERROR) << "X509_STORE_add_cert error: " << error_code;
+ } while ((error_code = ERR_get_error()) != 0);
+ return NULL;
+ }
+ }
+ return X509Certificate::CreateFromHandle(
+ x509_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
+ X509Certificate::OSCertHandles());
+}
+
+X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
+ EnsureOpenSSLInit();
+
std::string rawcert;
if (!file_util::ReadFileToString(filename, &rawcert)) {
LOG(ERROR) << "Can't load certificate " << filename.value();
@@ -43,27 +61,21 @@ X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
return NULL;
}
- ScopedSSL<X509, X509_free> x509_cert(PEM_read_bio_X509(cert_bio.get(),
- NULL, NULL, NULL));
- if (!x509_cert.get()) {
- LOG(ERROR) << "Can't parse certificate " << filename.value();
- return NULL;
- }
-
- if (!X509_STORE_add_cert(openssl_init->x509_store(), x509_cert.get())) {
- unsigned long error_code = ERR_get_error();
- if (ERR_GET_LIB(error_code) != ERR_LIB_X509 ||
- ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
- do {
- LOG(ERROR) << "X509_STORE_add_cert error: " << error_code;
- } while ((error_code = ERR_get_error()) != 0);
- return NULL;
- }
- }
-
- return X509Certificate::CreateFromHandle(
- x509_cert.get(), X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ ScopedSSL<X509, X509_free> pem_cert(PEM_read_bio_X509(cert_bio.get(),
+ NULL, NULL, NULL));
+ if (pem_cert.get())
+ return AddTemporaryRootCertToStore(pem_cert.get());
+
+ // File does not contain PEM data, let's try DER.
+ const unsigned char* der_data =
+ reinterpret_cast<const unsigned char*>(rawcert.c_str());
+ int der_length = rawcert.length();
+ ScopedSSL<X509, X509_free> der_cert(d2i_X509(NULL, &der_data, der_length));
+ if (der_cert.get())
+ return AddTemporaryRootCertToStore(der_cert.get());
+
+ LOG(ERROR) << "Can't parse certificate " << filename.value();
+ return NULL;
}
#elif defined(USE_NSS)
X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
diff --git a/net/base/cert_test_util.h b/net/base/cert_test_util.h
index 45c8ed3..8709156 100644
--- a/net/base/cert_test_util.h
+++ b/net/base/cert_test_util.h
@@ -14,7 +14,7 @@ namespace net {
class X509Certificate;
-#if defined(USE_NSS) || defined(OS_MACOSX)
+#if defined(USE_NSS) || defined(OS_MACOSX) || defined(USE_OPENSSL)
// Loads and trusts a root CA certificate (stored in a file) temporarily.
// TODO(wtc): Implement this function on Windows (http://crbug.com/8470).
X509Certificate* LoadTemporaryRootCert(const FilePath& filename);
diff --git a/net/base/cert_type.h b/net/base/cert_type.h
index fbe4339..d9cb8a5 100644
--- a/net/base/cert_type.h
+++ b/net/base/cert_type.h
@@ -11,16 +11,14 @@ namespace net {
// This is only used in the context of CertDatabase, but is defined outside to
// avoid an awkwardly long type name.
// The type is a combination of intrinsic properties, such as the presense of an
-// email address or Certificate Authority Basic Constraint, and assigned trust
-// values. For example, a cert with no email address, basic constraints, or
-// trust, would be classified as UNKNOWN_CERT. If that cert is then trusted
-// with SetCertTrust(cert, SERVER_CERT, TRUSTED_SSL), it would become a
-// SERVER_CERT.
+// Certificate Authority Basic Constraint, and assigned trust values. For
+// example, a cert with no basic constraints or trust would be classified as
+// UNKNOWN_CERT. If that cert is then trusted with SetCertTrust(cert,
+// SERVER_CERT, TRUSTED_SSL), it would become a SERVER_CERT.
enum CertType {
UNKNOWN_CERT,
CA_CERT,
USER_CERT,
- EMAIL_CERT,
SERVER_CERT,
NUM_CERT_TYPES
};
diff --git a/net/base/connection_type_histograms.h b/net/base/connection_type_histograms.h
index e6c2a59..e3e4a84 100644
--- a/net/base/connection_type_histograms.h
+++ b/net/base/connection_type_histograms.h
@@ -30,6 +30,11 @@ enum ConnectionType {
// in the certificate chain (excluding root)
CONNECTION_HTTP = 7, // An HTTP connection
CONNECTION_SPDY = 8, // A SPDY connection
+ CONNECTION_SSL_SSL2 = 9, // An SSL connection that uses SSL 2.0
+ CONNECTION_SSL_SSL3 = 10, // An SSL connection that uses SSL 3.0
+ CONNECTION_SSL_TLS1 = 11, // An SSL connection that uses TLS 1.0
+ CONNECTION_SSL_TLS1_1 = 12, // An SSL connection that uses TLS 1.1
+ CONNECTION_SSL_TLS1_2 = 13, // An SSL connection that uses TLS 1.2
NUM_OF_CONNECTION_TYPES
};
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index de00016..2fb8d0f 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -90,6 +90,13 @@ struct OrderByCreationTimeDesc {
}
};
+// Constants for use in VLOG
+const int kVlogPerCookieMonster = 1;
+const int kVlogPeriodic = 3;
+const int kVlogGarbageCollection = 5;
+const int kVlogSetCookies = 7;
+const int kVlogGetCookies = 9;
+
} // namespace
// static
@@ -724,7 +731,8 @@ bool CookieMonster::HasCookieableScheme(const GURL& url) {
}
// The scheme didn't match any in our whitelist.
- DVLOG(1) << "WARNING: Unsupported cookie scheme: " << url.scheme();
+ VLOG(kVlogPerCookieMonster) << "WARNING: Unsupported cookie scheme: "
+ << url.scheme();
return false;
}
@@ -747,7 +755,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
const CookieOptions& options) {
lock_.AssertAcquired();
- DVLOG(1) << "SetCookie() line: " << cookie_line;
+ VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
Time creation_time = creation_time_or_null;
if (creation_time.is_null()) {
@@ -759,12 +767,12 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
ParsedCookie pc(cookie_line);
if (!pc.IsValid()) {
- DVLOG(1) << "WARNING: Couldn't parse cookie";
+ VLOG(kVlogSetCookies) << "WARNING: Couldn't parse cookie";
return false;
}
if (options.exclude_httponly() && pc.IsHttpOnly()) {
- DVLOG(1) << "SetCookie() not setting httponly cookie";
+ VLOG(kVlogSetCookies) << "SetCookie() not setting httponly cookie";
return false;
}
@@ -785,7 +793,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
!cookie_expires.is_null(), cookie_expires));
if (!cc.get()) {
- DVLOG(1) << "WARNING: Failed to allocate CanonicalCookie";
+ VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
return false;
}
return SetCanonicalCookie(&cc, creation_time, options);
@@ -839,11 +847,12 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
const CookieOptions& options) {
const std::string key(GetKey((*cc)->Domain()));
if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly())) {
- DVLOG(1) << "SetCookie() not clobbering httponly cookie";
+ VLOG(kVlogSetCookies) << "SetCookie() not clobbering httponly cookie";
return false;
}
- DVLOG(1) << "SetCookie() key: " << key << " cc: " << (*cc)->DebugString();
+ VLOG(kVlogSetCookies) << "SetCookie() key: " << key << " cc: "
+ << (*cc)->DebugString();
// Realize that we might be setting an expired cookie, and the only point
// was to delete the cookie which we've already done.
@@ -906,7 +915,7 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
histogram_cookie_deletion_cause_->Add(deletion_cause);
CanonicalCookie* cc = it->second;
- DVLOG(1) << "InternalDeleteCookie() cc: " << cc->DebugString();
+ VLOG(kVlogSetCookies) << "InternalDeleteCookie() cc: " << cc->DebugString();
if (cc->IsPersistent() && store_ && sync_to_store)
store_->DeleteCookie(*cc);
@@ -973,7 +982,8 @@ static bool FindLeastRecentlyAccessed(
std::vector<CookieMonster::CookieMap::iterator>* cookie_its) {
DCHECK_LE(num_purge, num_max);
if (cookie_its->size() > num_max) {
- DVLOG(1) << "FindLeastRecentlyAccessed() Deep Garbage Collect.";
+ VLOG(kVlogGarbageCollection)
+ << "FindLeastRecentlyAccessed() Deep Garbage Collect.";
num_purge += cookie_its->size() - num_max;
DCHECK_GT(cookie_its->size(), num_purge);
@@ -1020,7 +1030,7 @@ int CookieMonster::GarbageCollect(const Time& current,
// Collect garbage for this key.
if (cookies_.count(key) > kDomainMaxCookies) {
- DVLOG(1) << "GarbageCollect() key: " << key;
+ VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key;
std::vector<CookieMap::iterator> cookie_its;
num_deleted += GarbageCollectExpired(
@@ -1056,7 +1066,7 @@ int CookieMonster::GarbageCollect(const Time& current,
(expiry_and_key_scheme_ == EKS_DISCARD_RECENT_AND_PURGE_DOMAIN ||
earliest_access_time_ <
Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays))) {
- DVLOG(1) << "GarbageCollect() everything";
+ VLOG(kVlogGarbageCollection) << "GarbageCollect() everything";
std::vector<CookieMap::iterator> cookie_its;
base::Time oldest_left;
num_deleted += GarbageCollectExpired(
@@ -1067,7 +1077,7 @@ int CookieMonster::GarbageCollect(const Time& current,
Time oldest_safe_cookie(
expiry_and_key_scheme_ == EKS_KEEP_RECENT_AND_PURGE_ETLDP1 ?
(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays)) :
- Time::Now());
+ Time()); // Null time == ignore access time.
int num_evicted = GarbageCollectDeleteList(
current,
oldest_safe_cookie,
@@ -1259,7 +1269,7 @@ std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
- DVLOG(1) << "GetCookies() result: " << cookie_line;
+ VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
return cookie_line;
}
@@ -1497,8 +1507,9 @@ void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
it_key = its_cookies.second;
}
- DVLOG(1) << "Time for recording cookie stats (us): "
- << (TimeTicks::Now() - beginning_of_time).InMicroseconds();
+ VLOG(kVlogPeriodic)
+ << "Time for recording cookie stats (us): "
+ << (TimeTicks::Now() - beginning_of_time).InMicroseconds();
last_statistic_record_time_ = current_time;
}
diff --git a/net/base/cookie_monster_perftest.cc b/net/base/cookie_monster_perftest.cc
index c006128..8c64d9a 100644
--- a/net/base/cookie_monster_perftest.cc
+++ b/net/base/cookie_monster_perftest.cc
@@ -283,10 +283,10 @@ TEST(CookieMonsterTest, TestGCTimes) {
};
for (int ci = 0; ci < static_cast<int>(ARRAYSIZE_UNSAFE(test_cases)); ++ci) {
const TestCase& test_case(test_cases[ci]);
- scoped_refptr<CookieMonster> cm =
+ scoped_refptr<CookieMonster> cm(
CreateMonsterFromStoreForGC(
test_case.num_cookies, test_case.num_old_cookies,
- CookieMonster::kSafeFromGlobalPurgeDays * 2);
+ CookieMonster::kSafeFromGlobalPurgeDays * 2));
GURL gurl("http://google.com");
std::string cookie_line("z=3");
diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc
index 80d58ed..751b255 100644
--- a/net/base/cookie_monster_unittest.cc
+++ b/net/base/cookie_monster_unittest.cc
@@ -1852,7 +1852,7 @@ TEST(CookieMonsterTest, BackingStoreCommunication) {
// Create new cookies and flush them to the store.
{
- scoped_refptr<net::CookieMonster> cmout = new CookieMonster(store, NULL);
+ scoped_refptr<net::CookieMonster> cmout(new CookieMonster(store, NULL));
for (const CookiesInputInfo* p = input_info;
p < &input_info[ARRAYSIZE_UNSAFE(input_info)]; p++) {
EXPECT_TRUE(cmout->SetCookieWithDetails(GURL(p->gurl), p->name, p->value,
@@ -1866,7 +1866,7 @@ TEST(CookieMonsterTest, BackingStoreCommunication) {
// Create a new cookie monster and make sure that everything is correct
{
- scoped_refptr<net::CookieMonster> cmin = new CookieMonster(store, NULL);
+ scoped_refptr<net::CookieMonster> cmin(new CookieMonster(store, NULL));
CookieMonster::CookieList cookies(cmin->GetAllCookies());
ASSERT_EQ(2u, cookies.size());
// Ordering is path length, then creation time. So second cookie
@@ -1895,7 +1895,7 @@ TEST(CookieMonsterTest, BackingStoreCommunication) {
TEST(CookieMonsterTest, CookieOrdering) {
// Put a random set of cookies into a monster and make sure
// they're returned in the right order.
- scoped_refptr<net::CookieMonster> cm = new CookieMonster(NULL, NULL);
+ scoped_refptr<net::CookieMonster> cm(new CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(GURL("http://d.c.b.a.google.com/aa/x.html"),
"c=1"));
EXPECT_TRUE(cm->SetCookie(GURL("http://b.a.google.com/aa/bb/cc/x.html"),
@@ -1953,13 +1953,12 @@ static net::CookieMonster* CreateMonsterForGC(int num_cookies) {
// get rid of cookies when we should). The perftest is probing for
// whether garbage collection happens when it shouldn't. See comments
// before that test for more details.
-// Flaky as per http://crbug.com/60015
-TEST(CookieMonsterTest, FLAKY_GarbageCollectionTriggers) {
+TEST(CookieMonsterTest, GarbageCollectionTriggers) {
// First we check to make sure that a whole lot of recent cookies
// doesn't get rid of anything after garbage collection is checked for.
{
- scoped_refptr<net::CookieMonster> cm =
- CreateMonsterForGC(CookieMonster::kMaxCookies * 2);
+ scoped_refptr<net::CookieMonster> cm(
+ CreateMonsterForGC(CookieMonster::kMaxCookies * 2));
EXPECT_EQ(CookieMonster::kMaxCookies * 2, cm->GetAllCookies().size());
cm->SetCookie(GURL("http://newdomain.com"), "b=2");
EXPECT_EQ(CookieMonster::kMaxCookies * 2 + 1, cm->GetAllCookies().size());
@@ -2017,10 +2016,10 @@ TEST(CookieMonsterTest, FLAKY_GarbageCollectionTriggers) {
recent_scheme < static_cast<int>(ARRAYSIZE_UNSAFE(schemes));
recent_scheme++) {
const TestCase *test_case = &test_cases[ci];
- scoped_refptr<net::CookieMonster> cm =
+ scoped_refptr<net::CookieMonster> cm(
CreateMonsterFromStoreForGC(
test_case->num_cookies, test_case->num_old_cookies,
- CookieMonster::kSafeFromGlobalPurgeDays * 2);
+ CookieMonster::kSafeFromGlobalPurgeDays * 2));
cm->SetExpiryAndKeyScheme(schemes[recent_scheme]);
EXPECT_EQ(test_case->expected_initial_cookies,
static_cast<int>(cm->GetAllCookies().size()))
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc
index f75d8d8..5607bc5 100644
--- a/net/base/directory_lister_unittest.cc
+++ b/net/base/directory_lister_unittest.cc
@@ -77,8 +77,8 @@ TEST(DirectoryListerTest, BigDirTest) {
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &path));
ListerDelegate delegate(false);
- scoped_refptr<net::DirectoryLister> lister =
- new net::DirectoryLister(path, &delegate);
+ scoped_refptr<net::DirectoryLister> lister(
+ new net::DirectoryLister(path, &delegate));
lister->Start();
@@ -92,11 +92,11 @@ TEST(DirectoryListerTest, BigDirRecursiveTest) {
ASSERT_TRUE(PathService::Get(base::DIR_EXE, &path));
ListerDelegate delegate(true);
- scoped_refptr<net::DirectoryLister> lister =
+ scoped_refptr<net::DirectoryLister> lister(
new net::DirectoryLister(path,
true,
net::DirectoryLister::FULL_PATH,
- &delegate);
+ &delegate));
lister->Start();
@@ -110,8 +110,8 @@ TEST(DirectoryListerTest, CancelTest) {
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &path));
ListerDelegate delegate(false);
- scoped_refptr<net::DirectoryLister> lister =
- new net::DirectoryLister(path, &delegate);
+ scoped_refptr<net::DirectoryLister> lister(
+ new net::DirectoryLister(path, &delegate));
lister->Start();
lister->Cancel();
diff --git a/net/base/ev_root_ca_metadata.cc b/net/base/ev_root_ca_metadata.cc
index 7c1c96a..7de971b 100644
--- a/net/base/ev_root_ca_metadata.cc
+++ b/net/base/ev_root_ca_metadata.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -9,6 +9,8 @@
#include <pkcs11n.h>
#include <secerr.h>
#include <secoid.h>
+#elif defined(OS_WIN)
+#include <stdlib.h>
#endif
#include "base/logging.h"
@@ -251,6 +253,36 @@ static const EVMetadata ev_root_ca_metadata[] = {
}
};
+#if defined(OS_WIN)
+// static
+const EVRootCAMetadata::PolicyOID EVRootCAMetadata::policy_oids_[] = {
+ // The OIDs must be sorted in ascending order.
+ "1.2.392.200091.100.721.1",
+ "1.3.6.1.4.1.14370.1.6",
+ "1.3.6.1.4.1.22234.2.5.2.3.1",
+ "1.3.6.1.4.1.23223.1.1.1",
+ "1.3.6.1.4.1.34697.2.1",
+ "1.3.6.1.4.1.34697.2.2",
+ "1.3.6.1.4.1.34697.2.3",
+ "1.3.6.1.4.1.34697.2.4",
+ "1.3.6.1.4.1.4146.1.1",
+ "1.3.6.1.4.1.6334.1.100.1",
+ "1.3.6.1.4.1.6449.1.2.1.5.1",
+ "1.3.6.1.4.1.782.1.2.1.8.1",
+ "1.3.6.1.4.1.8024.0.2.100.1.2",
+ "2.16.528.1.1001.1.1.1.12.6.1.1.1",
+ "2.16.756.1.89.1.2.1.1",
+ "2.16.840.1.113733.1.7.23.6",
+ "2.16.840.1.113733.1.7.48.1",
+ "2.16.840.1.114028.10.1.2",
+ "2.16.840.1.114171.500.9",
+ "2.16.840.1.114404.1.1.2.4.1",
+ "2.16.840.1.114412.2.1",
+ "2.16.840.1.114413.1.7.23.3",
+ "2.16.840.1.114414.1.7.23.3",
+};
+#endif
+
// static
EVRootCAMetadata* EVRootCAMetadata::GetInstance() {
return Singleton<EVRootCAMetadata>::get();
@@ -266,6 +298,35 @@ bool EVRootCAMetadata::GetPolicyOID(
return true;
}
+#if defined(OS_WIN)
+static int PolicyOIDCmp(const void* keyval, const void* datum) {
+ const char* oid1 = reinterpret_cast<const char*>(keyval);
+ const char* const* oid2 = reinterpret_cast<const char* const*>(datum);
+ return strcmp(oid1, *oid2);
+}
+
+bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const {
+ return bsearch(policy_oid, &policy_oids_[0], num_policy_oids_,
+ sizeof(PolicyOID), PolicyOIDCmp) != NULL;
+}
+#else
+bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const {
+ for (size_t i = 0; i < policy_oids_.size(); ++i) {
+ if (PolicyOIDsAreEqual(policy_oid, policy_oids_[i]))
+ return true;
+ }
+ return false;
+}
+#endif
+
+bool EVRootCAMetadata::HasEVPolicyOID(const SHA1Fingerprint& fingerprint,
+ PolicyOID policy_oid) const {
+ PolicyOID ev_policy_oid;
+ if (!GetPolicyOID(fingerprint, &ev_policy_oid))
+ return false;
+ return PolicyOIDsAreEqual(ev_policy_oid, policy_oid);
+}
+
EVRootCAMetadata::EVRootCAMetadata() {
// Constructs the object from the raw metadata in ev_root_ca_metadata.
#if defined(USE_NSS)
@@ -293,6 +354,18 @@ EVRootCAMetadata::EVRootCAMetadata() {
ev_policy_[metadata.fingerprint] = policy;
policy_oids_.push_back(policy);
}
+#elif defined(OS_WIN)
+ num_policy_oids_ = arraysize(policy_oids_);
+ // Verify policy_oids_ is in ascending order.
+ for (int i = 0; i < num_policy_oids_ - 1; i++)
+ CHECK(strcmp(policy_oids_[i], policy_oids_[i + 1]) < 0);
+
+ for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) {
+ const EVMetadata& metadata = ev_root_ca_metadata[i];
+ ev_policy_[metadata.fingerprint] = metadata.policy_oid;
+ // Verify policy_oids_ contains every EV policy OID.
+ DCHECK(IsEVPolicyOID(metadata.policy_oid));
+ }
#else
for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) {
const EVMetadata& metadata = ev_root_ca_metadata[i];
@@ -308,4 +381,13 @@ EVRootCAMetadata::EVRootCAMetadata() {
EVRootCAMetadata::~EVRootCAMetadata() {
}
+// static
+bool EVRootCAMetadata::PolicyOIDsAreEqual(PolicyOID a, PolicyOID b) {
+#if defined(USE_NSS)
+ return a == b;
+#else
+ return !strcmp(a, b);
+#endif
+}
+
} // namespace net
diff --git a/net/base/ev_root_ca_metadata.h b/net/base/ev_root_ca_metadata.h
index e9e8130..e0961f3 100644
--- a/net/base/ev_root_ca_metadata.h
+++ b/net/base/ev_root_ca_metadata.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -40,21 +40,40 @@ class EVRootCAMetadata {
PolicyOID* policy_oid) const;
const PolicyOID* GetPolicyOIDs() const { return &policy_oids_[0]; }
+#if defined(OS_WIN)
+ int NumPolicyOIDs() const { return num_policy_oids_; }
+#else
int NumPolicyOIDs() const { return policy_oids_.size(); }
+#endif
- private:
- EVRootCAMetadata();
- ~EVRootCAMetadata();
+ // Returns true if policy_oid is an EV policy OID of some root CA.
+ bool IsEVPolicyOID(PolicyOID policy_oid) const;
+
+ // Returns true if the root CA with the given certificate fingerprint has
+ // the EV policy OID policy_oid.
+ bool HasEVPolicyOID(const SHA1Fingerprint& fingerprint,
+ PolicyOID policy_oid) const;
+ private:
friend struct DefaultSingletonTraits<EVRootCAMetadata>;
typedef std::map<SHA1Fingerprint, PolicyOID,
SHA1FingerprintLessThan> PolicyOidMap;
+ EVRootCAMetadata();
+ ~EVRootCAMetadata();
+
+ static bool PolicyOIDsAreEqual(PolicyOID a, PolicyOID b);
+
// Maps an EV root CA cert's SHA-1 fingerprint to its EV policy OID.
PolicyOidMap ev_policy_;
+#if defined(OS_WIN)
+ static const PolicyOID policy_oids_[];
+ int num_policy_oids_;
+#else
std::vector<PolicyOID> policy_oids_;
+#endif
DISALLOW_COPY_AND_ASSIGN(EVRootCAMetadata);
};
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index 2fb7067..471ad8a 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -20,6 +20,7 @@ namespace net {
class AddressList;
class BoundNetLog;
class HostResolverImpl;
+class HostResolverProc;
class NetLog;
// This class represents the task of resolving hostnames (or IP address
@@ -230,13 +231,13 @@ class SingleRequestHostResolver {
DISALLOW_COPY_AND_ASSIGN(SingleRequestHostResolver);
};
-// Creates a HostResolver implementation that queries the underlying system.
-// (Except if a unit-test has changed the global HostResolverProc using
-// ScopedHostResolverProc to intercept requests to the system).
-// |max_concurrent_resolves| is how many resolve requests will be allowed to
-// run in parallel. Pass HostResolver::kDefaultParallelism to choose a
-// default value.
+// Creates a HostResolver implementation using |resolver_proc| as resolver,
+// (which if NULL, will default to getaddrinfo() wrapper) that queries the
+// underlying system, |max_concurrent_resolves| is how many resolve
+// requests will be allowed to run in parallel. Pass
+// HostResolver::kDefaultParallelism to choose a default value.
HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
+ HostResolverProc* resolver_proc,
NetLog* net_log);
} // namespace net
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index 37063af..5812d17 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -16,7 +16,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/debug_util.h"
+#include "base/debug/debugger.h"
+#include "base/debug/stack_trace.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "base/metrics/field_trial.h"
@@ -71,7 +72,9 @@ HostCache* CreateDefaultCache() {
} // anonymous namespace
HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
+ HostResolverProc* resolver_proc,
NetLog* net_log) {
+<<<<<<< HEAD
// Maximum of 50 concurrent threads.
// TODO(eroman): Adjust this, do some A/B experiments.
#ifdef ANDROID
@@ -80,6 +83,13 @@ HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
#else
static const size_t kDefaultMaxJobs = 50u;
#endif
+=======
+ // Maximum of 8 concurrent resolver threads.
+ // Some routers (or resolvers) appear to start to provide host-not-found if
+ // too many simultaneous resolutions are pending. This number needs to be
+ // further optimized, but 8 is what FF currently does.
+ static const size_t kDefaultMaxJobs = 8u;
+>>>>>>> chromium.org at r65505
if (max_concurrent_resolves == HostResolver::kDefaultParallelism)
max_concurrent_resolves = kDefaultMaxJobs;
@@ -93,7 +103,7 @@ HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
return systemResolver;
#else
HostResolverImpl* resolver =
- new HostResolverImpl(NULL, CreateDefaultCache(),
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(),
max_concurrent_resolves, net_log);
return resolver;
@@ -369,9 +379,10 @@ class HostResolverImpl::Job
had_non_speculative_request_(false),
net_log_(BoundNetLog::Make(net_log,
NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) {
- net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
- new JobCreationParameters(key.hostname,
- source_net_log.source()));
+ net_log_.BeginEvent(
+ NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
+ make_scoped_refptr(
+ new JobCreationParameters(key.hostname, source_net_log.source())));
}
// Attaches a request to this job. The job takes ownership of |req| and will
@@ -379,7 +390,8 @@ class HostResolverImpl::Job
void AddRequest(Request* req) {
req->request_net_log().BeginEvent(
NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH,
- new NetLogSourceParameter("source_dependency", net_log_.source()));
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", net_log_.source())));
req->set_job(this);
requests_.push_back(req);
@@ -1082,7 +1094,7 @@ void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
// Because we destroy outstanding requests during Shutdown(),
// |req_handle| is already cancelled.
LOG(ERROR) << "Called HostResolverImpl::CancelRequest() after Shutdown().";
- StackTrace().PrintBacktrace();
+ base::debug::StackTrace().PrintBacktrace();
return;
}
Request* req = reinterpret_cast<Request*>(req_handle);
@@ -1251,11 +1263,13 @@ void HostResolverImpl::OnStartRequest(const BoundNetLog& source_net_log,
const RequestInfo& info) {
source_net_log.BeginEvent(
NetLog::TYPE_HOST_RESOLVER_IMPL,
- new NetLogSourceParameter("source_dependency", request_net_log.source()));
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", request_net_log.source())));
request_net_log.BeginEvent(
NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
- new RequestInfoParameters(info, source_net_log.source()));
+ make_scoped_refptr(new RequestInfoParameters(
+ info, source_net_log.source())));
// Notify the observers of the start.
if (!observers_.empty()) {
@@ -1384,7 +1398,7 @@ void HostResolverImpl::ProcessQueuedRequests() {
if (!top_req)
return;
- scoped_refptr<Job> job = CreateAndStartJob(top_req);
+ scoped_refptr<Job> job(CreateAndStartJob(top_req));
// Search for any other pending request which can piggy-back off this job.
for (size_t pool_i = 0; pool_i < POOL_COUNT; ++pool_i) {
@@ -1414,8 +1428,8 @@ HostResolverImpl::Job* HostResolverImpl::CreateAndStartJob(Request* req) {
req->request_net_log().AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB,
NULL);
- scoped_refptr<Job> job = new Job(next_job_id_++, this, key,
- req->request_net_log(), net_log_);
+ scoped_refptr<Job> job(new Job(next_job_id_++, this, key,
+ req->request_net_log(), net_log_));
job->AddRequest(req);
AddOutstandingJob(job);
job->Start();
diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index 07e00bf..f3bdb74 100644
--- a/net/base/host_resolver_impl_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -259,8 +259,8 @@ TEST_F(HostResolverImplTest, SynchronousLookup) {
AddressList addrlist;
const int kPortnum = 80;
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AddRule("just.testing", "192.168.1.42");
scoped_ptr<HostResolver> host_resolver(
@@ -291,8 +291,8 @@ TEST_F(HostResolverImplTest, AsynchronousLookup) {
AddressList addrlist;
const int kPortnum = 80;
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AddRule("just.testing", "192.168.1.42");
scoped_ptr<HostResolver> host_resolver(
@@ -328,8 +328,8 @@ TEST_F(HostResolverImplTest, AsynchronousLookup) {
}
TEST_F(HostResolverImplTest, CanceledAsynchronousLookup) {
- scoped_refptr<WaitingHostResolverProc> resolver_proc =
- new WaitingHostResolverProc(NULL);
+ scoped_refptr<WaitingHostResolverProc> resolver_proc(
+ new WaitingHostResolverProc(NULL));
CapturingNetLog net_log(CapturingNetLog::kUnbounded);
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -390,8 +390,8 @@ TEST_F(HostResolverImplTest, CanceledAsynchronousLookup) {
TEST_F(HostResolverImplTest, NumericIPv4Address) {
// Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in.
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AllowDirectLookup("*");
scoped_ptr<HostResolver> host_resolver(
@@ -413,8 +413,8 @@ TEST_F(HostResolverImplTest, NumericIPv4Address) {
}
TEST_F(HostResolverImplTest, NumericIPv6Address) {
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AllowDirectLookup("*");
// Resolve a plain IPv6 address. Don't worry about [brackets], because
@@ -445,8 +445,8 @@ TEST_F(HostResolverImplTest, NumericIPv6Address) {
}
TEST_F(HostResolverImplTest, EmptyHost) {
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AllowDirectLookup("*");
scoped_ptr<HostResolver> host_resolver(
@@ -459,8 +459,8 @@ TEST_F(HostResolverImplTest, EmptyHost) {
}
TEST_F(HostResolverImplTest, LongHost) {
- scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc(
+ new RuleBasedHostResolverProc(NULL));
resolver_proc->AllowDirectLookup("*");
scoped_ptr<HostResolver> host_resolver(
@@ -523,8 +523,8 @@ class DeDupeRequestsVerifier : public ResolveRequest::Delegate {
TEST_F(HostResolverImplTest, DeDupeRequests) {
// Use a capturing resolver_proc, since the verifier needs to know what calls
// reached Resolve(). Also, the capturing resolver_proc is initially blocked.
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
scoped_ptr<HostResolver> host_resolver(
CreateHostResolverImpl(resolver_proc));
@@ -574,8 +574,8 @@ TEST_F(HostResolverImplTest, CancelMultipleRequests) {
// Use a capturing resolver_proc, since the verifier needs to know what calls
// reached Resolver(). Also, the capturing resolver_proc is initially
// blocked.
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
scoped_ptr<HostResolver> host_resolver(
CreateHostResolverImpl(resolver_proc));
@@ -661,8 +661,8 @@ TEST_F(HostResolverImplTest, CancelWithinCallback) {
// Use a capturing resolver_proc, since the verifier needs to know what calls
// reached Resolver(). Also, the capturing resolver_proc is initially
// blocked.
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
scoped_ptr<HostResolver> host_resolver(
CreateHostResolverImpl(resolver_proc));
@@ -718,8 +718,8 @@ TEST_F(HostResolverImplTest, DeleteWithinCallback) {
// Use a capturing resolver_proc, since the verifier needs to know what calls
// reached Resolver(). Also, the capturing resolver_proc is initially
// blocked.
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened. Note that the verifier holds the
@@ -773,8 +773,8 @@ TEST_F(HostResolverImplTest, StartWithinCallback) {
// Use a capturing resolver_proc, since the verifier needs to know what calls
// reached Resolver(). Also, the capturing resolver_proc is initially
// blocked.
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
// Turn off caching for this host resolver.
scoped_ptr<HostResolver> host_resolver(
@@ -1105,8 +1105,8 @@ TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) {
// Test that IP address changes send ERR_ABORTED to pending requests.
TEST_F(HostResolverImplTest, AbortOnIPAddressChanged) {
- scoped_refptr<WaitingHostResolverProc> resolver_proc =
- new WaitingHostResolverProc(NULL);
+ scoped_refptr<WaitingHostResolverProc> resolver_proc(
+ new WaitingHostResolverProc(NULL));
HostCache* cache = CreateDefaultCache();
scoped_ptr<HostResolver> host_resolver(
new HostResolverImpl(resolver_proc, cache, kMaxJobs, NULL));
@@ -1130,8 +1130,8 @@ TEST_F(HostResolverImplTest, AbortOnIPAddressChanged) {
// Obey pool constraints after IP address has changed.
TEST_F(HostResolverImplTest, ObeyPoolConstraintsAfterIPAddressChange) {
- scoped_refptr<WaitingHostResolverProc> resolver_proc =
- new WaitingHostResolverProc(NULL);
+ scoped_refptr<WaitingHostResolverProc> resolver_proc(
+ new WaitingHostResolverProc(NULL));
scoped_ptr<MockHostResolver> host_resolver(new MockHostResolver());
host_resolver->Reset(resolver_proc);
@@ -1202,8 +1202,8 @@ class ResolveWithinCallback : public CallbackRunner< Tuple1<int> > {
};
TEST_F(HostResolverImplTest, OnlyAbortExistingRequestsOnIPAddressChange) {
- scoped_refptr<WaitingHostResolverProc> resolver_proc =
- new WaitingHostResolverProc(NULL);
+ scoped_refptr<WaitingHostResolverProc> resolver_proc(
+ new WaitingHostResolverProc(NULL));
scoped_ptr<MockHostResolver> host_resolver(new MockHostResolver());
host_resolver->Reset(resolver_proc);
@@ -1227,8 +1227,8 @@ TEST_F(HostResolverImplTest, OnlyAbortExistingRequestsOnIPAddressChange) {
// Tests that when the maximum threads is set to 1, requests are dequeued
// in order of priority.
TEST_F(HostResolverImplTest, HigherPriorityRequestsStartedFirst) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
// This HostResolverImpl will only allow 1 outstanding resolve at a time.
size_t kMaxJobs = 1u;
@@ -1312,8 +1312,8 @@ TEST_F(HostResolverImplTest, HigherPriorityRequestsStartedFirst) {
// Try cancelling a request which has not been attached to a job yet.
TEST_F(HostResolverImplTest, CancelPendingRequest) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
// This HostResolverImpl will only allow 1 outstanding resolve at a time.
const size_t kMaxJobs = 1u;
@@ -1375,8 +1375,8 @@ TEST_F(HostResolverImplTest, CancelPendingRequest) {
// Test that when too many requests are enqueued, old ones start to be aborted.
TEST_F(HostResolverImplTest, QueueOverflow) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(NULL);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(NULL));
// This HostResolverImpl will only allow 1 outstanding resolve at a time.
const size_t kMaxOutstandingJobs = 1u;
@@ -1453,8 +1453,8 @@ TEST_F(HostResolverImplTest, QueueOverflow) {
// Tests that after changing the default AddressFamily to IPV4, requests
// with UNSPECIFIED address family map to IPV4.
TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv4) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(new EchoingHostResolverProc);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(new EchoingHostResolverProc));
// This HostResolverImpl will only allow 1 outstanding resolve at a time.
const size_t kMaxOutstandingJobs = 1u;
@@ -1521,8 +1521,8 @@ TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv4) {
// of requests 0 and 1 is flipped, and the default is set to IPv6 in place of
// IPv4.
TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv6) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(new EchoingHostResolverProc);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(new EchoingHostResolverProc));
// This HostResolverImpl will only allow 1 outstanding resolve at a time.
const size_t kMaxOutstandingJobs = 1u;
@@ -1588,8 +1588,8 @@ TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv6) {
// This tests that the default address family is respected for synchronous
// resolutions.
TEST_F(HostResolverImplTest, SetDefaultAddressFamily_Synchronous) {
- scoped_refptr<CapturingHostResolverProc> resolver_proc =
- new CapturingHostResolverProc(new EchoingHostResolverProc);
+ scoped_refptr<CapturingHostResolverProc> resolver_proc(
+ new CapturingHostResolverProc(new EchoingHostResolverProc));
const size_t kMaxOutstandingJobs = 10u;
scoped_ptr<HostResolverImpl> host_resolver(new HostResolverImpl(
diff --git a/net/base/listen_socket.cc b/net/base/listen_socket.cc
index 0cb529d..c964ec9 100644
--- a/net/base/listen_socket.cc
+++ b/net/base/listen_socket.cc
@@ -121,8 +121,8 @@ SOCKET ListenSocket::Accept(SOCKET s) {
void ListenSocket::Accept() {
SOCKET conn = Accept(socket_);
if (conn != kInvalidSocket) {
- scoped_refptr<ListenSocket> sock =
- new ListenSocket(conn, socket_delegate_);
+ scoped_refptr<ListenSocket> sock(
+ new ListenSocket(conn, socket_delegate_));
// it's up to the delegate to AddRef if it wants to keep it around
#if defined(OS_POSIX)
sock->WatchSocket(WAITING_READ);
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index a580997..ddcfc4b 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -82,6 +82,7 @@ static const MimeInfo primary_mappings[] = {
{ "text/xml", "xml" },
{ "image/gif", "gif" },
{ "image/jpeg", "jpeg,jpg" },
+ { "image/webp", "webp" },
{ "image/png", "png" },
{ "video/mp4", "mp4,m4v" },
{ "audio/x-m4a", "m4a" },
@@ -192,6 +193,7 @@ static const char* const supported_image_types[] = {
"image/jpeg",
"image/pjpeg",
"image/jpg",
+ "image/webp",
"image/png",
"image/gif",
"image/bmp",
@@ -547,6 +549,7 @@ static const char* kStandardImageTypes[] = {
"image/gif",
"image/ief",
"image/jpeg",
+ "image/webp",
"image/pict",
"image/pipeg",
"image/png",
@@ -660,7 +663,6 @@ void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) {
target->at(old_target_size + i) = *iter;
}
}
-
}
void GetImageExtensions(std::vector<FilePath::StringType>* extensions) {
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc
index 9c82f93..9ee5c53 100644
--- a/net/base/mock_host_resolver.cc
+++ b/net/base/mock_host_resolver.cc
@@ -80,8 +80,8 @@ void MockHostResolverBase::Reset(HostResolverProc* interceptor) {
synchronous_mode_ = false;
// At the root of the chain, map everything to localhost.
- scoped_refptr<RuleBasedHostResolverProc> catchall =
- new RuleBasedHostResolverProc(NULL);
+ scoped_refptr<RuleBasedHostResolverProc> catchall(
+ new RuleBasedHostResolverProc(NULL));
catchall->AddRule("*", "127.0.0.1");
// Next add a rules-based layer the use controls.
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index d7ae9d1..96b19ad 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -50,7 +50,7 @@ NET_ERROR(FILE_TOO_BIG, -8)
// invalid assumption.
NET_ERROR(UNEXPECTED, -9)
-// Permission to access a resource was denied.
+// Permission to access a resource, other than the network, was denied.
NET_ERROR(ACCESS_DENIED, -10)
// The operation failed because of unimplemented functionality.
@@ -66,7 +66,7 @@ NET_ERROR(OUT_OF_MEMORY, -13)
// from the expectation.
NET_ERROR(UPLOAD_FILE_CHANGED, -14)
-// The socket is not connected
+// The socket is not connected.
NET_ERROR(SOCKET_NOT_CONNECTED, -15)
// A connection was closed (corresponding to a TCP FIN).
@@ -191,10 +191,7 @@ NET_ERROR(SSL_SNAP_START_NPN_MISPREDICTION, -131)
// give the user a helpful error message rather than have the connection hang.
NET_ERROR(ESET_ANTI_VIRUS_SSL_INTERCEPTION, -132)
-// We detected NetNanny intercepting our HTTPS connections. Since this product
-// is False Start intolerant, we return this error so that we can give the user
-// a helpful error message rather than have the connection hang.
-NET_ERROR(NETNANNY_SSL_INTERCEPTION, -133)
+// Missing -133. Feel free to reuse in the future.
// The permission to use the SSL client certificate's private key was denied.
NET_ERROR(SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED, -134)
@@ -208,6 +205,11 @@ NET_ERROR(PROXY_CERTIFICATE_INVALID, -136)
// An error occurred when trying to do a name resolution (DNS).
NET_ERROR(NAME_RESOLUTION_FAILED, -137)
+// Permission to access the network was denied. This is used to distinguish
+// errors that were most likely caused by a firewall from other access denied
+// errors. See also ERR_ACCESS_DENIED.
+NET_ERROR(NETWORK_ACCESS_DENIED, -138)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index 398f7c1..6183749 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -334,6 +334,17 @@ EVENT_TYPE(SSL_HANDSHAKE_ERROR)
EVENT_TYPE(SSL_READ_ERROR)
EVENT_TYPE(SSL_WRITE_ERROR)
+// An SSL Snap Start was attempted
+// The following parameters are attached to the event:
+// {
+// "type": <Integer code for the Snap Start result>,
+// }
+EVENT_TYPE(SSL_SNAP_START)
+
+// We found that our prediction of the server's certificates was correct and
+// we merged the verification with the SSLHostInfo.
+EVENT_TYPE(SSL_VERIFICATION_MERGED)
+
// An SSL error occurred while calling an NSS function not directly related to
// one of the above activities. Can also be used when more information than
// is provided by just an error code is needed:
diff --git a/net/base/net_test_suite.h b/net/base/net_test_suite.h
index eab3a53..00d9844 100644
--- a/net/base/net_test_suite.h
+++ b/net/base/net_test_suite.h
@@ -9,7 +9,9 @@
#include "base/message_loop.h"
#include "base/ref_counted.h"
#include "base/test/test_suite.h"
+#include "build/build_config.h"
#include "net/base/mock_host_resolver.h"
+#include "net/ocsp/nss_ocsp.h"
class NetTestSuite : public base::TestSuite {
public:
@@ -39,6 +41,10 @@ class NetTestSuite : public base::TestSuite {
}
virtual void Shutdown() {
+#if defined(OS_LINUX)
+ net::ShutdownOCSP();
+#endif // defined(OS_LINUX)
+
// We want to destroy this here before the TestSuite continues to tear down
// the environment.
message_loop_.reset();
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index c1f769e..5afba6f 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -181,7 +181,7 @@ STR GetSpecificHeaderT(const STR& headers, const STR& name) {
typename STR::const_iterator begin =
search(headers.begin(), headers.end(), match.begin(), match.end(),
- CaseInsensitiveCompareASCII<typename STR::value_type>());
+ base::CaseInsensitiveCompareASCII<typename STR::value_type>());
if (begin == headers.end())
return STR();
@@ -374,9 +374,7 @@ bool DecodeWord(const std::string& encoded_word,
// it should be Ok because we're not an email client but a
// web browser.
- // What IE6/7 does: %-escaped UTF-8. We could extend this to
- // support a rudimentary form of RFC 2231 with charset label, but
- // it'd gain us little in terms of compatibility.
+ // What IE6/7 does: %-escaped UTF-8.
tmp = UnescapeURLComponent(encoded_word, UnescapeRule::SPACES);
if (IsStringUTF8(tmp)) {
output->swap(tmp);
@@ -425,11 +423,12 @@ bool DecodeParamValue(const std::string& input,
// TODO(mpcomplete): This is a quick and dirty implementation for now. I'm
// sure this doesn't properly handle all (most?) cases.
template<typename STR>
-STR GetHeaderParamValueT(const STR& header, const STR& param_name) {
+STR GetHeaderParamValueT(const STR& header, const STR& param_name,
+ QuoteRule::Type quote_rule) {
// This assumes args are formatted exactly like "bla; arg1=value; arg2=value".
typename STR::const_iterator param_begin =
search(header.begin(), header.end(), param_name.begin(), param_name.end(),
- CaseInsensitiveCompareASCII<typename STR::value_type>());
+ base::CaseInsensitiveCompareASCII<typename STR::value_type>());
if (param_begin == header.end())
return STR();
@@ -448,7 +447,7 @@ STR GetHeaderParamValueT(const STR& header, const STR& param_name) {
return STR();
typename STR::const_iterator param_end;
- if (*param_begin == '"') {
+ if (*param_begin == '"' && quote_rule == QuoteRule::REMOVE_OUTER_QUOTES) {
param_end = find(param_begin+1, header.end(), '"');
if (param_end == header.end())
return STR(); // poorly formatted param?
@@ -1096,29 +1095,86 @@ std::string GetSpecificHeader(const std::string& headers,
return GetSpecificHeaderT(headers, name);
}
+bool DecodeCharset(const std::string& input,
+ std::string* decoded_charset,
+ std::string* value) {
+ StringTokenizer t(input, "'");
+ t.set_options(StringTokenizer::RETURN_DELIMS);
+ std::string temp_charset;
+ std::string temp_value;
+ int numDelimsSeen = 0;
+ while (t.GetNext()) {
+ if (t.token_is_delim()) {
+ ++numDelimsSeen;
+ continue;
+ } else {
+ switch (numDelimsSeen) {
+ case 0:
+ temp_charset = t.token();
+ break;
+ case 1:
+ // Language is ignored.
+ break;
+ case 2:
+ temp_value = t.token();
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+ if (numDelimsSeen != 2)
+ return false;
+ if (temp_charset.empty() || temp_value.empty())
+ return false;
+ decoded_charset->swap(temp_charset);
+ value->swap(temp_value);
+ return true;
+}
+
std::string GetFileNameFromCD(const std::string& header,
const std::string& referrer_charset) {
- std::string param_value = GetHeaderParamValue(header, "filename");
+ std::string decoded;
+ std::string param_value = GetHeaderParamValue(header, "filename*",
+ QuoteRule::KEEP_OUTER_QUOTES);
+ if (!param_value.empty()) {
+ if (param_value.find('"') == std::string::npos) {
+ std::string charset;
+ std::string value;
+ if (DecodeCharset(param_value, &charset, &value)) {
+ // RFC 5987 value should be ASCII-only.
+ if (!IsStringASCII(value))
+ return std::string();
+ std::string tmp = UnescapeURLComponent(value, UnescapeRule::SPACES);
+ if (base::ConvertToUtf8AndNormalize(tmp, charset, &decoded))
+ return decoded;
+ }
+ }
+ }
+ param_value = GetHeaderParamValue(header, "filename",
+ QuoteRule::REMOVE_OUTER_QUOTES);
if (param_value.empty()) {
// Some servers use 'name' parameter.
- param_value = GetHeaderParamValue(header, "name");
+ param_value = GetHeaderParamValue(header, "name",
+ QuoteRule::REMOVE_OUTER_QUOTES);
}
if (param_value.empty())
return std::string();
- std::string decoded;
if (DecodeParamValue(param_value, referrer_charset, &decoded))
return decoded;
return std::string();
}
std::wstring GetHeaderParamValue(const std::wstring& field,
- const std::wstring& param_name) {
- return GetHeaderParamValueT(field, param_name);
+ const std::wstring& param_name,
+ QuoteRule::Type quote_rule) {
+ return GetHeaderParamValueT(field, param_name, quote_rule);
}
std::string GetHeaderParamValue(const std::string& field,
- const std::string& param_name) {
- return GetHeaderParamValueT(field, param_name);
+ const std::string& param_name,
+ QuoteRule::Type quote_rule) {
+ return GetHeaderParamValueT(field, param_name, quote_rule);
}
// TODO(brettw) bug 734373: check the scripts for each host component and
@@ -1681,10 +1737,11 @@ void SetExplicitlyAllowedPorts(const std::string& allowed_ports) {
(allowed_ports[i] != kComma))
return;
if (i == size || allowed_ports[i] == kComma) {
- size_t length = i - last;
- if (length > 0) {
+ if (i > last) {
int port;
- base::StringToInt(allowed_ports.substr(last, length), &port);
+ base::StringToInt(allowed_ports.begin() + last,
+ allowed_ports.begin() + i,
+ &port);
ports.insert(port);
}
last = i + 1;
diff --git a/net/base/net_util.h b/net/base/net_util.h
index f5a6151..4b87c70 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -42,6 +42,18 @@ namespace net {
typedef uint32 FormatUrlType;
typedef uint32 FormatUrlTypes;
+// Used by GetHeaderParamValue to determine how to handle quotes in the value.
+class QuoteRule {
+ public:
+ enum Type {
+ KEEP_OUTER_QUOTES,
+ REMOVE_OUTER_QUOTES,
+ };
+
+ private:
+ QuoteRule();
+};
+
// Nothing is ommitted.
extern const FormatUrlType kFormatUrlOmitNothing;
@@ -124,23 +136,26 @@ std::string GetSpecificHeader(const std::string& headers,
// 'param_name'. Returns the empty string if the parameter is not found or is
// improperly formatted.
std::wstring GetHeaderParamValue(const std::wstring& field,
- const std::wstring& param_name);
+ const std::wstring& param_name,
+ QuoteRule::Type quote_rule);
std::string GetHeaderParamValue(const std::string& field,
- const std::string& param_name);
+ const std::string& param_name,
+ QuoteRule::Type quote_rule);
// Return the filename extracted from Content-Disposition header. The following
// formats are tried in order listed below:
//
-// 1. RFC 2047
-// 2. Raw-8bit-characters :
+// 1. RFC 5987
+// 2. RFC 2047
+// 3. Raw-8bit-characters :
// a. UTF-8, b. referrer_charset, c. default os codepage.
-// 3. %-escaped UTF-8.
+// 4. %-escaped UTF-8.
//
-// In step 2, if referrer_charset is empty(i.e. unknown), 2b is skipped.
-// In step 3, the fallback charsets tried in step 2 are not tried. We
+// In step 3, if referrer_charset is empty(i.e. unknown), 3b is skipped.
+// In step 4, the fallback charsets tried in step 3 are not tried. We
// can consider doing that later.
//
-// When a param value is ASCII, but is not in format #1 or format #3 above,
+// When a param value is ASCII, but is not in format #2 or format #4 above,
// it is returned as it is unless it's pretty close to two supported
// formats but not well-formed. In that case, an empty string is returned.
//
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc
index ad7ccad..77d3a00 100644
--- a/net/base/net_util_unittest.cc
+++ b/net/base/net_util_unittest.cc
@@ -711,7 +711,8 @@ TEST(NetUtilTest, GetHeaderParamValue) {
std::wstring header_value =
net::GetSpecificHeader(google_headers, tests[i].header_name);
std::wstring result =
- net::GetHeaderParamValue(header_value, tests[i].param_name);
+ net::GetHeaderParamValue(header_value, tests[i].param_name,
+ net::QuoteRule::REMOVE_OUTER_QUOTES);
EXPECT_EQ(result, tests[i].expected);
}
@@ -719,11 +720,38 @@ TEST(NetUtilTest, GetHeaderParamValue) {
std::wstring header_value =
net::GetSpecificHeader(L"", tests[i].header_name);
std::wstring result =
- net::GetHeaderParamValue(header_value, tests[i].param_name);
+ net::GetHeaderParamValue(header_value, tests[i].param_name,
+ net::QuoteRule::REMOVE_OUTER_QUOTES);
EXPECT_EQ(result, std::wstring());
}
}
+TEST(NetUtilTest, GetHeaderParamValueQuotes) {
+ struct {
+ const char* header;
+ const char* expected_with_quotes;
+ const char* expected_without_quotes;
+ } tests[] = {
+ {"filename=foo", "foo", "foo"},
+ {"filename=\"foo\"", "\"foo\"", "foo"},
+ {"filename=foo\"", "foo\"", "foo\""},
+ {"filename=fo\"o", "fo\"o", "fo\"o"},
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string actual_with_quotes =
+ net::GetHeaderParamValue(tests[i].header, "filename",
+ net::QuoteRule::KEEP_OUTER_QUOTES);
+ std::string actual_without_quotes =
+ net::GetHeaderParamValue(tests[i].header, "filename",
+ net::QuoteRule::REMOVE_OUTER_QUOTES);
+ EXPECT_EQ(tests[i].expected_with_quotes, actual_with_quotes)
+ << "Failed while processing: " << tests[i].header;
+ EXPECT_EQ(tests[i].expected_without_quotes, actual_without_quotes)
+ << "Failed while processing: " << tests[i].header;
+ }
+}
+
TEST(NetUtilTest, GetFileNameFromCD) {
const FileNameCDCase tests[] = {
// Test various forms of C-D header fields emitted by web servers.
@@ -762,7 +790,7 @@ TEST(NetUtilTest, GetFileNameFromCD) {
"_3=2Epng?=", "", L"\U00010330 3.png"},
{"Content-Disposition: inline; filename=\"=?iso88591?Q?caf=e9_=2epng?=\"",
"", L"caf\x00e9 .png"},
- // Space after an encode word should be removed.
+ // Space after an encoded word should be removed.
{"Content-Disposition: inline; filename=\"=?iso88591?Q?caf=E9_?= .png\"",
"", L"caf\x00e9 .png"},
// Two encoded words with different charsets (not very likely to be emitted
@@ -812,11 +840,92 @@ TEST(NetUtilTest, GetFileNameFromCD) {
// Two RFC 2047 encoded words in a row without a space is an error.
{"Content-Disposition: attachment; filename==?windows-1252?Q?caf=E3?="
"=?iso-8859-7?b?4eIucG5nCg==?=", "", L""},
+
+ // RFC 5987 tests with Filename* : see http://tools.ietf.org/html/rfc5987
+ {"Content-Disposition: attachment; filename*=foo.html", "", L""},
+ {"Content-Disposition: attachment; filename*=foo'.html", "", L""},
+ {"Content-Disposition: attachment; filename*=''foo'.html", "", L""},
+ {"Content-Disposition: attachment; filename*=''foo.html'", "", L""},
+ {"Content-Disposition: attachment; filename*=''f\"oo\".html'", "", L""},
+ {"Content-Disposition: attachment; filename*=bogus_charset''foo.html'",
+ "", L""},
+ {"Content-Disposition: attachment; filename*='en'foo.html'", "", L""},
+ {"Content-Disposition: attachment; filename*=iso-8859-1'en'foo.html", "",
+ L"foo.html"},
+ {"Content-Disposition: attachment; filename*=utf-8'en'foo.html", "",
+ L"foo.html"},
+ // charset cannot be omitted.
+ {"Content-Disposition: attachment; filename*='es'f\xfa.html'", "", L""},
+ // Non-ASCII bytes are not allowed.
+ {"Content-Disposition: attachment; filename*=iso-8859-1'es'f\xfa.html", "",
+ L""},
+ {"Content-Disposition: attachment; filename*=utf-8'es'f\xce\xba.html", "",
+ L""},
+ // TODO(jshin): Space should be %-encoded, but currently, we allow
+ // spaces.
+ {"Content-Disposition: inline; filename*=iso88591''cafe foo.png", "",
+ L"cafe foo.png"},
+
+ // Filename* tests converted from Q-encoded tests above.
+ {"Content-Disposition: attachment; filename*=EUC-JP''%B7%DD%BD%D13%2Epng",
+ "", L"\x82b8\x8853" L"3.png"},
+ {"Content-Disposition: attachment; filename*=utf-8''"
+ "%E8%8A%B8%E8%A1%93%203%2Epng", "", L"\x82b8\x8853 3.png"},
+ {"Content-Disposition: attachment; filename*=utf-8''%F0%90%8C%B0 3.png", "",
+ L"\U00010330 3.png"},
+ {"Content-Disposition: inline; filename*=Euc-Kr'ko'%BF%B9%BC%FA%2Epng", "",
+ L"\xc608\xc220.png"},
+ {"Content-Disposition: attachment; filename*=windows-1252''caf%E9.png", "",
+ L"caf\x00e9.png"},
+
+ // http://greenbytes.de/tech/tc2231/ filename* test cases.
+ // attwithisofn2231iso
+ {"Content-Disposition: attachment; filename*=iso-8859-1''foo-%E4.html", "",
+ L"foo-\xe4.html"},
+ // attwithfn2231utf8
+ {"Content-Disposition: attachment; filename*="
+ "UTF-8''foo-%c3%a4-%e2%82%ac.html", "", L"foo-\xe4-\x20ac.html"},
+ // attwithfn2231noc : no encoding specified but UTF-8 is used.
+ {"Content-Disposition: attachment; filename*=''foo-%c3%a4-%e2%82%ac.html",
+ "", L""},
+ // attwithfn2231utf8comp
+ {"Content-Disposition: attachment; filename*=UTF-8''foo-a%cc%88.html", "",
+ L"foo-\xe4.html"},
+#ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER
+ // This does not work because we treat ISO-8859-1 synonymous with
+ // Windows-1252 per HTML5. For HTTP, in theory, we're not
+ // supposed to.
+ // attwithfn2231utf8-bad
+ {"Content-Disposition: attachment; filename*="
+ "iso-8859-1''foo-%c3%a4-%e2%82%ac.html", "", L""},
+#endif
+ // attwithfn2231ws1
+ {"Content-Disposition: attachment; filename *=UTF-8''foo-%c3%a4.html", "",
+ L""},
+ // attwithfn2231ws2
+ {"Content-Disposition: attachment; filename*= UTF-8''foo-%c3%a4.html", "",
+ L"foo-\xe4.html"},
+ // attwithfn2231ws3
+ {"Content-Disposition: attachment; filename* =UTF-8''foo-%c3%a4.html", "",
+ L"foo-\xe4.html"},
+ // attwithfn2231quot
+ {"Content-Disposition: attachment; filename*=\"UTF-8''foo-%c3%a4.html\"",
+ "", L""},
+ // attfnboth
+ {"Content-Disposition: attachment; filename=\"foo-ae.html\"; "
+ "filename*=UTF-8''foo-%c3%a4.html", "", L"foo-\xe4.html"},
+ // attfnboth2
+ {"Content-Disposition: attachment; filename*=UTF-8''foo-%c3%a4.html; "
+ "filename=\"foo-ae.html\"", "", L"foo-\xe4.html"},
+ // attnewandfn
+ {"Content-Disposition: attachment; foobar=x; filename=\"foo.html\"", "",
+ L"foo.html"},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
EXPECT_EQ(tests[i].expected,
UTF8ToWide(net::GetFileNameFromCD(tests[i].header_field,
- tests[i].referrer_charset)));
+ tests[i].referrer_charset)))
+ << "Failed on input: " << tests[i].header_field;
}
}
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc
index 365859e..dd93067 100644
--- a/net/base/network_config_watcher_mac.cc
+++ b/net/base/network_config_watcher_mac.cc
@@ -8,12 +8,10 @@
#include <SystemConfiguration/SCSchemaDefinitions.h>
#include <algorithm>
+#include "base/compiler_specific.h"
#include "base/thread.h"
#include "base/mac/scoped_cftyperef.h"
-// We only post tasks to a child thread we own, so we don't need refcounting.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(net::NetworkConfigWatcherMac);
-
namespace net {
namespace {
@@ -27,48 +25,59 @@ void DynamicStoreCallback(SCDynamicStoreRef /* store */,
net_config_delegate->OnNetworkConfigChange(changed_keys);
}
-} // namespace
+class NetworkConfigWatcherMacThread : public base::Thread {
+ public:
+ NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate);
+ virtual ~NetworkConfigWatcherMacThread();
-NetworkConfigWatcherMac::NetworkConfigWatcherMac(
- Delegate* delegate)
- : notifier_thread_(new base::Thread("NetworkConfigWatcher")),
- delegate_(delegate) {
- // We create this notifier thread because the notification implementation
- // needs a thread with a CFRunLoop, and there's no guarantee that
- // MessageLoop::current() meets that criterion.
- base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
- notifier_thread_->StartWithOptions(thread_options);
+ protected:
+ // base::Thread
+ virtual void Init();
+ virtual void CleanUp();
+
+ private:
+ // The SystemConfiguration calls in this function can lead to contention early
+ // on, so we invoke this function later on in startup to keep it fast.
+ void InitNotifications();
+
+ base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_;
+ NetworkConfigWatcherMac::Delegate* const delegate_;
+ ScopedRunnableMethodFactory<NetworkConfigWatcherMacThread> method_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread);
+};
+
+NetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread(
+ NetworkConfigWatcherMac::Delegate* delegate)
+ : base::Thread("NetworkConfigWatcher"),
+ delegate_(delegate),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
+
+NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() {
+ Stop();
+}
+
+void NetworkConfigWatcherMacThread::Init() {
// TODO(willchan): Look to see if there's a better signal for when it's ok to
// initialize this, rather than just delaying it by a fixed time.
- const int kNotifierThreadInitializationDelayMS = 1000;
- notifier_thread_->message_loop()->PostDelayedTask(
+ const int kInitializationDelayMS = 1000;
+ message_loop()->PostDelayedTask(
FROM_HERE,
- NewRunnableMethod(this, &NetworkConfigWatcherMac::Init),
- kNotifierThreadInitializationDelayMS);
-}
-
-NetworkConfigWatcherMac::~NetworkConfigWatcherMac() {
- // We don't need to explicitly Stop(), but doing so allows us to sanity-
- // check that the notifier thread shut down properly.
- notifier_thread_->Stop();
- DCHECK(run_loop_source_ == NULL);
+ method_factory_.NewRunnableMethod(
+ &NetworkConfigWatcherMacThread::InitNotifications),
+ kInitializationDelayMS);
}
-void NetworkConfigWatcherMac::WillDestroyCurrentMessageLoop() {
- DCHECK(notifier_thread_ != NULL);
- // We can't check the notifier_thread_'s message_loop(), as it's now 0.
- // DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
+void NetworkConfigWatcherMacThread::CleanUp() {
+ if (!run_loop_source_.get())
+ return;
- DCHECK(run_loop_source_ != NULL);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(),
kCFRunLoopCommonModes);
run_loop_source_.reset();
}
-void NetworkConfigWatcherMac::Init() {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
-
+void NetworkConfigWatcherMacThread::InitNotifications() {
// Add a run loop source for a dynamic store to the current run loop.
SCDynamicStoreContext context = {
0, // Version 0.
@@ -86,8 +95,19 @@ void NetworkConfigWatcherMac::Init() {
// Set up notifications for interface and IP address changes.
delegate_->SetDynamicStoreNotificationKeys(store.get());
+}
+
+} // namespace
- MessageLoop::current()->AddDestructionObserver(this);
+NetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate)
+ : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) {
+ // We create this notifier thread because the notification implementation
+ // needs a thread with a CFRunLoop, and there's no guarantee that
+ // MessageLoop::current() meets that criterion.
+ base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
+ notifier_thread_->StartWithOptions(thread_options);
}
+NetworkConfigWatcherMac::~NetworkConfigWatcherMac() {}
+
} // namespace net
diff --git a/net/base/network_config_watcher_mac.h b/net/base/network_config_watcher_mac.h
index f9f9d36..3bd55f9 100644
--- a/net/base/network_config_watcher_mac.h
+++ b/net/base/network_config_watcher_mac.h
@@ -19,7 +19,7 @@ class Thread;
namespace net {
// Base class for watching the Mac OS system network settings.
-class NetworkConfigWatcherMac : public MessageLoop::DestructionObserver {
+class NetworkConfigWatcherMac {
public:
// NOTE: The lifetime of Delegate is expected to exceed the lifetime of
// NetworkConfigWatcherMac.
@@ -41,24 +41,11 @@ class NetworkConfigWatcherMac : public MessageLoop::DestructionObserver {
virtual ~NetworkConfigWatcherMac();
private:
- // MessageLoop::DestructionObserver:
- virtual void WillDestroyCurrentMessageLoop();
-
- // Called on the notifier thread to initialize the notification
- // implementation. The SystemConfiguration calls in this function can lead to
- // contention early on, so we invoke this function later on in startup to keep
- // it fast.
- void Init();
-
// The thread used to listen for notifications. This relays the notification
// to the registered observers without posting back to the thread the object
// was created on.
scoped_ptr<base::Thread> notifier_thread_;
- base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_;
-
- Delegate* const delegate_;
-
DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMac);
};
diff --git a/net/base/openssl_util.cc b/net/base/openssl_util.cc
index fcdc3a1..51797ac 100644
--- a/net/base/openssl_util.cc
+++ b/net/base/openssl_util.cc
@@ -59,6 +59,10 @@ OpenSSLInitSingleton* GetOpenSSLInitSingleton() {
return Singleton<OpenSSLInitSingleton>::get();
}
+void EnsureOpenSSLInit() {
+ Singleton<OpenSSLInitSingleton>::get();
+}
+
// static
void OpenSSLInitSingleton::LockingCallback(int mode,
int n,
diff --git a/net/base/openssl_util.h b/net/base/openssl_util.h
index 4218a89..d4603c6 100644
--- a/net/base/openssl_util.h
+++ b/net/base/openssl_util.h
@@ -25,7 +25,7 @@ class ScopedSSL {
};
// Singleton for initializing / cleaning up OpenSSL and holding a X509 store.
-// Access it via EnsureOpenSSLInit().
+// Access it via GetOpenSSLInitSingleton().
class OpenSSLInitSingleton {
public:
SSL_CTX* ssl_ctx() const { return ssl_ctx_.get(); }
@@ -49,5 +49,11 @@ class OpenSSLInitSingleton {
OpenSSLInitSingleton* GetOpenSSLInitSingleton();
+// Initialize OpenSSL if it isn't already initialized. This must be called
+// before any other OpenSSL functions (except GetOpenSSLInitSingleton above).
+// This function is thread-safe, and OpenSSL will only ever be initialized once.
+// OpenSSL will be properly shut down on program exit.
+void EnsureOpenSSLInit();
+
} // namespace net
diff --git a/net/base/ssl_cipher_suite_names.cc b/net/base/ssl_cipher_suite_names.cc
index 2db9a4b..39efd1c 100644
--- a/net/base/ssl_cipher_suite_names.cc
+++ b/net/base/ssl_cipher_suite_names.cc
@@ -6,6 +6,8 @@
#include <stdlib.h>
+#include "base/logging.h"
+#include "net/base/ssl_connection_status_flags.h"
// Rather than storing the names of all the ciphersuites we eliminate the
// redundancy and break each cipher suite into a key exchange method, cipher
@@ -346,4 +348,28 @@ void SSLCompressionToString(const char** name, uint8 compresssion) {
}
}
+void SSLVersionToString(const char** name, int ssl_version) {
+ switch (ssl_version) {
+ case SSL_CONNECTION_VERSION_SSL2:
+ *name = "SSL 2.0";
+ break;
+ case SSL_CONNECTION_VERSION_SSL3:
+ *name = "SSL 3.0";
+ break;
+ case SSL_CONNECTION_VERSION_TLS1:
+ *name = "TLS 1.0";
+ break;
+ case SSL_CONNECTION_VERSION_TLS1_1:
+ *name = "TLS 1.1";
+ break;
+ case SSL_CONNECTION_VERSION_TLS1_2:
+ *name = "TLS 1.2";
+ break;
+ default:
+ NOTREACHED();
+ *name = "???";
+ break;
+ }
+}
+
} // namespace net
diff --git a/net/base/ssl_cipher_suite_names.h b/net/base/ssl_cipher_suite_names.h
index cd61471..9241c1b 100644
--- a/net/base/ssl_cipher_suite_names.h
+++ b/net/base/ssl_cipher_suite_names.h
@@ -25,6 +25,12 @@ void SSLCipherSuiteToStrings(const char** key_exchange_str,
// If the algorithm is unknown, |name| is set to "???".
void SSLCompressionToString(const char** name, uint8 compression_method);
+// SSLVersionToString returns the name of the SSL protocol version
+// specified by |ssl_version|, which is defined in
+// net/base/ssl_connection_status_flags.h.
+// If the version is unknown, |name| is set to "???".
+void SSLVersionToString(const char** name, int ssl_version);
+
} // namespace net
#endif // NET_BASE_SSL_CIPHER_SUITE_NAMES_H_
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index d8ecb0b..5c38f97 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -99,6 +99,7 @@ static bool g_dnssec_enabled = false;
static bool g_false_start_enabled = true;
static bool g_mitm_proxies_allowed = false;
static bool g_snap_start_enabled = false;
+static bool g_dns_cert_provenance_checking = false;
// static
void SSLConfigService::SetSSLConfigFlags(SSLConfig* ssl_config) {
@@ -106,6 +107,8 @@ void SSLConfigService::SetSSLConfigFlags(SSLConfig* ssl_config) {
ssl_config->false_start_enabled = g_false_start_enabled;
ssl_config->mitm_proxies_allowed = g_mitm_proxies_allowed;
ssl_config->snap_start_enabled = g_snap_start_enabled;
+ ssl_config->dns_cert_provenance_checking_enabled =
+ g_dns_cert_provenance_checking;
}
// static
@@ -148,6 +151,16 @@ bool SSLConfigService::mitm_proxies_allowed() {
return g_mitm_proxies_allowed;
}
+// static
+void SSLConfigService::EnableDNSCertProvenanceChecking() {
+ g_dns_cert_provenance_checking = true;
+}
+
+// static
+bool SSLConfigService::dns_cert_provenance_checking_enabled() {
+ return g_dns_cert_provenance_checking;
+}
+
void SSLConfigService::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index 0ab88b2..be50097 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -28,6 +28,8 @@ struct SSLConfig {
bool tls1_enabled; // True if TLS 1.0 is enabled.
bool dnssec_enabled; // True if we'll accept DNSSEC chains in certificates.
bool snap_start_enabled; // True if we'll try Snap Start handshakes.
+ // True if we'll do async checks for certificate provenance using DNS.
+ bool dns_cert_provenance_checking_enabled;
// True if we allow this connection to be MITM attacked. This sounds a little
// worse than it is: large networks sometimes MITM attack all SSL connections
@@ -144,6 +146,10 @@ class SSLConfigService : public base::RefCountedThreadSafe<SSLConfigService> {
// True if we use False Start for SSL and TLS.
static bool false_start_enabled();
+ // Enables DNS side checks for certificates.
+ static void EnableDNSCertProvenanceChecking();
+ static bool dns_cert_provenance_checking_enabled();
+
// Add an observer of this service.
void AddObserver(Observer* observer);
diff --git a/net/base/ssl_config_service_win.cc b/net/base/ssl_config_service_win.cc
index 14c4d24..debea7d 100644
--- a/net/base/ssl_config_service_win.cc
+++ b/net/base/ssl_config_service_win.cc
@@ -4,6 +4,7 @@
#include "net/base/ssl_config_service_win.h"
+#include "base/thread_restrictions.h"
#include "base/win/registry.h"
using base::TimeDelta;
@@ -59,6 +60,9 @@ void SSLConfigServiceWin::GetSSLConfigAt(SSLConfig* config, TimeTicks now) {
// static
bool SSLConfigServiceWin::GetSSLConfigNow(SSLConfig* config) {
+ // This registry access goes to disk and will slow down the IO thread.
+ // http://crbug.com/61455
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
RegKey internet_settings;
if (!internet_settings.Open(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
KEY_READ))
@@ -83,6 +87,8 @@ bool SSLConfigServiceWin::GetSSLConfigNow(SSLConfig* config) {
// static
void SSLConfigServiceWin::SetRevCheckingEnabled(bool enabled) {
+ // This registry access goes to disk and will slow down the IO thread.
+ // http://crbug.com/61455
DWORD value = enabled;
RegKey internet_settings(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
KEY_WRITE);
@@ -108,6 +114,8 @@ void SSLConfigServiceWin::SetTLS1Enabled(bool enabled) {
// static
void SSLConfigServiceWin::SetSSLVersionEnabled(int version, bool enabled) {
+ // This registry access goes to disk and will slow down the IO thread.
+ // http://crbug.com/61455
RegKey internet_settings(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
KEY_READ | KEY_WRITE);
DWORD value;
diff --git a/net/base/ssl_connection_status_flags.h b/net/base/ssl_connection_status_flags.h
index 1b7640c..9596f00 100644
--- a/net/base/ssl_connection_status_flags.h
+++ b/net/base/ssl_connection_status_flags.h
@@ -27,10 +27,28 @@ enum {
// library that doesn't report it, like SChannel.)
SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION = 1 << 19,
+ // The next three bits are reserved for the SSL version.
+ SSL_CONNECTION_VERSION_SHIFT = 20,
+ SSL_CONNECTION_VERSION_MASK = 7,
+
// 1 << 31 (the sign bit) is reserved so that the SSL connection status will
// never be negative.
};
+// NOTE: the SSL version enum constants must be between 0 and
+// SSL_CONNECTION_VERSION_MASK, inclusive.
+enum {
+ SSL_CONNECTION_VERSION_UNKNOWN = 0, // Unknown SSL version.
+ SSL_CONNECTION_VERSION_SSL2 = 1,
+ SSL_CONNECTION_VERSION_SSL3 = 2,
+ SSL_CONNECTION_VERSION_TLS1 = 3,
+ SSL_CONNECTION_VERSION_TLS1_1 = 4,
+ SSL_CONNECTION_VERSION_TLS1_2 = 5,
+ SSL_CONNECTION_VERSION_MAX,
+};
+COMPILE_ASSERT(SSL_CONNECTION_VERSION_MAX - 1 <= SSL_CONNECTION_VERSION_MASK,
+ SSL_CONNECTION_VERSION_MASK_too_small);
+
inline int SSLConnectionStatusToCipherSuite(int connection_status) {
return (connection_status >> SSL_CONNECTION_CIPHERSUITE_SHIFT) &
SSL_CONNECTION_CIPHERSUITE_MASK;
@@ -41,6 +59,11 @@ inline int SSLConnectionStatusToCompression(int connection_status) {
SSL_CONNECTION_COMPRESSION_MASK;
}
+inline int SSLConnectionStatusToVersion(int connection_status) {
+ return (connection_status >> SSL_CONNECTION_VERSION_SHIFT) &
+ SSL_CONNECTION_VERSION_MASK;
+}
+
} // namespace net
#endif // NET_BASE_SSL_CONNECTION_STATUS_FLAGS_H_
diff --git a/net/base/ssl_false_start_blacklist.cc b/net/base/ssl_false_start_blacklist.cc
index 9e0f309..b57826b 100644
--- a/net/base/ssl_false_start_blacklist.cc
+++ b/net/base/ssl_false_start_blacklist.cc
@@ -12,8 +12,8 @@ bool SSLFalseStartBlacklist::IsMember(const char* host) {
if (!last_two_labels)
return false;
const unsigned bucket = Hash(last_two_labels) & (kBuckets - 1);
- const uint16 start = kHashTable[bucket];
- const uint16 end = kHashTable[bucket + 1];
+ const uint32 start = kHashTable[bucket];
+ const uint32 end = kHashTable[bucket + 1];
const size_t len = strlen(host);
for (size_t i = start; i < end;) {
diff --git a/net/base/ssl_false_start_blacklist.h b/net/base/ssl_false_start_blacklist.h
index 1d44d0a..d0b10e2 100644
--- a/net/base/ssl_false_start_blacklist.h
+++ b/net/base/ssl_false_start_blacklist.h
@@ -81,7 +81,7 @@ class SSLFalseStartBlacklist {
// kHashTable contains an offset into |kHashData| for each bucket. The
// additional element at the end contains the length of |kHashData|.
- static const uint16 kHashTable[kBuckets + 1];
+ static const uint32 kHashTable[kBuckets + 1];
// kHashData contains the contents of the hash table. |kHashTable| indexes
// into this array. Each bucket consists of zero or more, 8-bit length
// prefixed strings. Each string is a DNS name in dotted form. For a given
diff --git a/net/base/ssl_false_start_blacklist.txt b/net/base/ssl_false_start_blacklist.txt
index c718618..d782b5b 100644
--- a/net/base/ssl_false_start_blacklist.txt
+++ b/net/base/ssl_false_start_blacklist.txt
@@ -8,504 +8,4896 @@
# This is included for unit tests:
example.com
+008880.com
+1-plus.com
+111112.com
123.cht.com.tw
+123people.com
+155551.com
+233332.com
+24sevenselfstorage.com
+2ndc.dk
+2whateverittakes.com
+333332.com
+333337.com
+365days.jp
+38shop.jp
+3mfx.three.com.hk
+48pickup.com
4science.net
+4ward.asia
+50pickupnow.com
+622222.com
+6ftoverhead.com
+911twenty.com
+a-star.edu.sg
+a.eap-net.com
+a.thatsping.com
+aaa.grh.org
+aaastationreports.com
+aanmelden.bjaa.nl
+aaucm.org
+abacustech.co.jp
abangdani.wordpress.com
+abc.attendseurope.com
+abcirclenow.com
+abdr.blood.gov.au
+abeno-tennoji.jp
+ablwebmail.com
+abrocket.com
+abrocketpilates.com
+abrocketpowertrainer.com
+abtserver.com
+abtwebxpress.com
+ac-besancon.fr
+ac-caen.fr
+ac-guyane.fr
+ac-lille.fr
+ac-limoges.fr
+ac-lyon.fr
+ac-nice.fr
+ac-orleans-tours.fr
+ac-paris.fr
+ac-poitiers.fr
+ac-reims.fr
+ac-strasbourg.fr
+ac-versailles.fr
+acad1.dlit.edu.tw
+academicclub.org
+acams.dhs.gov
access.arkansas.gov
+access.coinstar.com
+access.csn.edu
+access.moric.org
+access.opco.com
+access.sullivanandassoc.com
+access.vch.ca
+access1.spokesman.com
accessgeneral.com
accessingram.com
+accesswr.bannerhealth.com
accorservicesdirect.net
+account.payclick.com.au
+accounts.jelhi.net
+accu-doc.ch
+acea.de
+acebenefitsplus.co.uk
+acheteremerycat.ca
+acheterpalmwallet.ca
+achs.org.au
+acidesign.com
+acommit.ch
+acs-inc.com
+acsi.eu
+actionpoint.ch
+activase.com
+adcenter.msn.com.sg
+adcouncil.tv
adfox.cz
+adhbcn.net
+adhdtreatmenttoday.com
+admin.centerpoint.jelecos.com
+admin.iot.dtag.de
+admin.webcast.fi
+admin2.bloosky.com
+administaffservices.com
+adoptionscentrum.se
+adox.sk
+adplacer.com.au
ads.bridgetrack.com
+adtran.com
adult.dl.rakuten.co.jp
adulthire.com
advanceautoparts.com
+advisorpracticeconsulting.com
+advocates.org.uk
+aecc.ac.uk
+aecom.com
+aemc.net
+aerosped.org
+afconsult.com
+afeyewear.com
+affinitycircles.com
+afflelou.net
+afflinkservice.com
+afflinksource.com
+afternic.com
+afterpayroll.com
+aftonxchange.com
+ag.729972.com
+ag.ibc88.com
+agencywow.com
agents.nationalsecuritygroup.com
+aggis.com.br
+agir-recouvrement.com
+agreemanager.net
+agriinfo.copa-cogeca.be
+agriinfo.copa-cogeca.eu
+agromercantil.com.gt
+ahanw.org
+ahika.com
+akabis.com
+akershus-fk.no
+aktionsplan-allergien.de
alamode.com
algoritam.hr
+algvpn.algonquincollege.com
+alinean.com
+alle-inklusive.behindertenbeauftragte.de
+allianz.hr
+alliedliquor.co.nz
+allmyaccounts.bankofamerica.com
+alltours.at
+alltours.de
+alltours.info
+almliquor.com.au
+alperton.brent.sch.uk
+alpinecapitalbank.com
alsformalwear.com
alucmo.com
+alvo.com
+alwaysillinois.org
+am.cmc.com
amail.centrum.cz
+american-summit-flood.com
+americanchia.com
+americanexpress.hu
+americanreliefcard.com
+americanreliefcard.net
+amesbank.com
amexweb.com.mx
+amf-assurances.fr
+amgusa.com
+ammail.edwards.com
+amo-20happy.com
+amo-happy-patients.com
+amo-signature.net
+amo-top.net
+ampecommerce.com
amsi.alliedgroup.net
amwaylive.com
+analytics.sonymusic.com
+animate-onlineshop.jp
+annssl01.fticonsulting.com
anntaylor.recruitmax.com
+anoka.k12.mn.us
+anpassung.net
+anshin-access.ezweb.ne.jp
+antispam.hireahit.com
+apex.utpa.edu
+api.gogrid.com
+api.rapleaf.com
+apo-vpn-02.apotex.com
+app.actre.it
+app.audit-navigator.nl
+app.elal.co.il
+applicaties.tln.nl
+appliedi.net
+applymarketforce.com
+applyshopnchek.ca
+applyshopnchek.com
+appraisalzone.lendervend.com
+apps.caa.qld.gov.au
apps.revenuecycle.com
+appsgate.com
+aproposgeschenk.de
aps2.toshiba-tro.de
apus.edu
+ara.bahamaselectricity.com
+aravo.com
+arc.org.uk
+archivedata.com
+arena.highview.org
aribabuyer.us.dell.com
ariston.es
+arizona.edu
+arkansas.gov
+arkona.com
+arnecommunity.thomsonreuters.com
+arowanacapital.com
+arts.ac.uk
+arvidsvensson.net
+asa-seattle-1.adobe.com
+asa01.svccorp.com
+asacitrix.ccgh.org
asb.dk
+aschc.com
ashgate.com
ashleymadison.com
+ashleyportal.com
+asiandating.com
+asklepios.com
+asmconnects.com
+asn.advolution.de
asp.fm-pc.com
+aspentrack.com
+aspraytshirt.com
+asthmamatters.com
+astral.com
+asugroup.com
atari.com
+athenasweb.brynmawr.edu
+atl-c1.goodrich.com
+atlas.fd.com
ats.openhire.com
+att.com
attask-ondemand.com
attask.com
+attaskbeta.com
+attendsguiden.se
+audittool.bdoasf.com
+auone.jp
+aus-vpn.amd.com
+auslandsschulwesen.de
+authentication.accorhotels.com
+autodiscover.barron.com.pe
+autodiscover.dwvsolutions.com
+autodiscover.eternalnetworx.com
+autodiscover.montco.com
+autodiscover.net
+autodiscover.nimbus.nl
+autodiscover.wrinklebrain.com
+autopalvelut.kuusakoski.fi
+autoradiostore.be
+autoradiostore.nl
+avastin.com
+avgrewards.com
+avlk.dishmail.net
+avondale.org
+avs.de
+awesomearmsnow.com
+awvn.nl
axa.co.uk
+axess.telcordia.com
+axiamail.phoenix.edu
+aza-lite.com
+azurance.com
+b-tracker.com
+b2b.aksel.com.tr
+b2b.mammut.ch
+babyfoonstore.be
+babyfoonstore.nl
+babylon.inverso.de
+backend02.d1g.com
+backup.datassur.net
+backupumbrella.net
+bafin.de
+bag-mail.de
+bahmueller.de
+bam.com.gt
+bamf.de
+bank4u.bancapopolare.it
+bank4u.volksbank.it
+bankadviser.com
banking.ing-diba.at
+bankingon.com
baptisthealth.net
+barakhosting.com
+barclaystravelinsurance.co.uk
+barelifts.tv
barkoff.tv
+barkoffspecialoffer.com
barracudaserver.com
+barrierepoker.fr
barronscatalog.com
+bartletthospital.org
+bartoncreek.com
+basco.com
+basf-farefinder.com
+baua.de
+baxter.com
bb3.utc.edu
+bboardtest.nsula.edu
+bbsihq.com
+bcbsal.org
bcbsfl.recruitmax.com
+bdmp.com
+beamercenter.be
+beamercenter.nl
+beanfun.com
+bedfordschool.org.uk
+beespace.issukraine.com
+behindertenbeauftragter.de
+bel.com.bz
+belvis.swibi.ch
+ben.billing.com.au
+bendarooscreativity.com
+bendaroosglow.com
+benderball.tv
+benefitsconnect.net
+benendenschool.net
+bennett.kent.sch.uk
bentley.edu
+berg-hansen.no
+berger-meditec.com
+berryworld.co.uk
+bestobamacoin.com
+bestpossiblequotes.com
+bestwhole.com
+beta-lighting.com
+beta.algodeal.com
+beta.ekool.eu
+betcloud.com
+betlegion.com
+bettertrades.com
+bevoelkerungsschutz-portal.de
+bevoelkerungsschutz.de
+beztakcorp.com
+bfarm.de
+bfu.ch
+bhinc.com
+bi.com
+bib-demografie.de
+bid53.com
+bidclay.com
biddingforgood.com
+bidmc.org
+bidokaloosa.com
biffalo.net
+bigcityslider.com
+biglobe.ne.jp
+bigwintracking.com
bilder.buecher.de
+billing.ntt-east.co.jp
+billonline.com
+biloxiregional.net
+biooncology.com
+biozid-portal.de
+biprod01.mfsasp.com
bishops.org.za
+bisp-sportpsychologie.de
bitfang.com
+bitlasso.com
+biz.portlandgeneral.com
+bizneslink.pl
+bizoubazart.com
+blackmarble.co.uk
+ble.de
+blinkbox.com
+blog.mudy.info
+blog.neosec.dk
blogger.huffingtonpost.com
+blooads.com
+bluearea.net
+bluefinsolutions.com
+blurayspelershop.be
+blurayspelershop.nl
+bmelv.de
+bmwi-unternehmensportal.de
+boaregistret.se
+bockelman.org
+bodycareshop.nl
+bokuvpn.boku.ac.at
+bonfils.org
+book.lowestairfares.com
+bookeo.org
+bookitnow.mirabeauparkhotel.com
+boormachinestore.be
+boormachinestore.nl
+bopowa.elcabop.org
+born.ch
+borsen.klasselotteriet.dk
+bos.stidelivers.com
+bosch-savingsystem.com
+bottletops.tv
+bowldvd.com
+boxmedia.bredband.net
+bp-platinum.com
+brabantwater.nl
+bradfordcollege.ac.uk
+brainforce.nl
+braintumorconnections.com
+branders.com
+brandon.ca
+brcc.edu
+brcn.edu
+breastcancerconnections.com
+brest-metropole-oceane.fr
+bridgetrack.com
+brighton.ac.uk
+brightonsc.vic.edu.au
brinksinc.com
+britishmusicexperience.com
+broadoak.n-somerset.sch.uk
+broker.healthcompare.com
+brookfield.hants.sch.uk
+brookfieldservices.com
+brookshealth.org
+broomwellhealthwatch.com
+brotheroffers.com
+bs24.jp
+bsal.com.au
+bsi-fuer-buerger.de
bsi.de
+bskytracking.com
+bsnparentnet.nl
+bsnstaffnet.nl
+bsp.bradfieldcollege.org.uk
+bsprivat.de
+btlaw.com
+btracker.com
+buckinghamhotel.com
+budget.bmas.de
buecher.de
+bui.co.za
buildings.com
bund.de
+bundesfinanzministerium.de
+bundesgerichtshof.de
+bundesgesundheitsministerium.de
+bundespolizei.de
+bundesrat.de
+bundesversicherungsamt.de
+burtsbeesacne.com
+businessassetmanager.com
+businessverifications.com
+businessware.com
+businesszone.quester.at
bux.ee
+buxtonbag.com
+buxtoncartera.com
+buxtonmicro.com
+buxtonpalmwallet.com
+buxtonwallet.com
+buy1948pickup.com
+buy1957caddy.com
+buy33caddy.com
+buy41flatbed.com
+buy50pickupnow.com
+buy57caddy.com
+buyaquaglobes.tv
+buyaspray.com
+buybanoodle.com
+buybeautifulworshipcd.com
+buybenderballca.com
+buybionicwrenchonline.com
+buyblueplanet.com
+buybombachop.com
+buybumpit.tv
+buychiaseedsnow.com
+buycollegesuggies.com
+buycucumbervine.com
+buydesignersnuggie.com
+buydomains.com
+buyeasyreach.com
+buyemagrece.com
+buyfiftydollargold.com
+buyflatbedfireset.com
+buyflirtygirlfit.net
+buyflirtygirlfit.tv
+buyforemaneverydayandmore.com
+buyfountainofyouthnow.com
+buyfranklinmint.com
+buygetitgreen.com
+buygrandpa.com
+buygrillglovetv.com
+buygyrobowl.com
+buygyrobowlset.com
+buyhandyvalet.com
+buyhangingstrawberry.com
+buyhdvisionreaderssite.com
+buyhdvisionultra.com
+buyheeltastic.tv
+buyhydroheel.com
+buyidooffer.com
+buylastmorgans.com
+buymagicjacknow.com
+buymagictarptv.com
+buymagnetrim.com
+buymightyfixit.com
+buymightyputtynow.com
+buymightyshine.com
+buymightysuperpack.com
+buymilitaryflatbed.com
+buyminimaxnow.com
+buymonstersteamjet.com
+buymorgansilver.com
+buymushroomkit.com
+buymusiccristianaespanol.com
+buymyarmyset.com
+buymygianttomatoes.com
+buymyhairblock.com
+buymysportelec.com
+buyoptic1050.com
+buyoptic1050tv.com
+buyoverthedoor.com
+buypedegg.tv
+buypedipaws.ca
+buypedipistol.tv
+buypestfree.tv
+buypetmd.com
+buyphilsdvdsnow.com
+buypowerjuicerpro.com
+buypowershaper.com
+buyprofitfromrealestatenow.net
+buyptpro.com
+buypumpitfresh.com
+buyquicklawnseed.com
+buyrainbowpeppersnow.com
+buyrazordock.com
+buysamowraiblade.com
+buysecretsolution.com
buyshakeweightformen.com
+buyshakeweightforwomen.com
+buyshamwownow.com
+buysideshowskillettv.com
+buyslimmettes.com
+buysnuggie.tv
+buysnuggieforkids.tv
+buysoftpullleash.com
+buysongs4soldiers.com
+buysteamjetnow.com
+buystonenow.com
+buyteddyspridesite.com
+buytexastail.com
+buythecrazycritters.com
+buythecuttermouse.com
+buythekingcoin.com
+buythelittleredchef.com
+buythemousechaser.com
+buytheoptic1050.com
+buytheperfectbutton.com
+buythesnuggie.com
+buythesteambuddy.com
+buythinspin.com
+buyticklemeplant.com
+buytidytable.com
+buytimelifeespanol.com
+buytomatofactory.com
+buytomatofactorynow.com
+buytoolbandit.com
+buytopsytree.com
+buytopsyturvy.com
+buytvhatnow.com
+buyultimatetable.com
+buyupsydaisytv.com
+buywidgetlight.com
+buywindshieldwonder.tv
+buywonderhanger.com
+buyzipdo.com
+buzzcity.com
+byebye.de
+bzgs.ch
+bzi-interlaken.ch
+bzport.net
+ca.gov
+cachezone.cache.org.uk
+cadizretail.co.za
+cadizwealth.co.za
cagreatamerica.com
+caisse-epargne.fr
+cal-x.net
+calchoice.com
+calchoiceplus.com
+caldicott.com
+call2.nl
+callbe.com
+callingcards.at
+calvijn.nl
+cambriancollege.ca
+camelvpn.conncoll.edu
+campasol.com
+campus.himeji-du.ac.jp
+campus.norquest.ca
+campusharvest.org
+canadaswonderland.com
+canadianbenefits.com
+cancer-test.com
+cancerchampionprogram.org
candydirect.com
+caowa.altara.com
+cap.dyntek.com
+capellfarmfinance.com
+capeplc.com.au
+capgemini.com
+capitalonedealsdone.com
+capvpn.capilanou.ca
+carcraft.co.uk
+cardlabconnect.com
cardsdirect.com
+career.cdtechno.com
+careers.hphood.com
+careers.nicta.com.au
+careers1.flagstar.com
+careport.carilion.com
+careylink.com.au
+caridianbct.com
+carilionlabs.com
caringbridge.org
+carintreggelandgroep.nl
+carisbrookehighschool.net
+carlislermc.com
+carrinho.casashow.com.br
+cas.freud.com
+cas.grey.com
cash.netmarble.net
+cashexpress.com
+cashpoint.com
+catalog.synthes.com
+cathflo.com
+catholic.edu.au
+catie.ac.cr
+cave-kit.com
+cbcag.edu
+cbfive.com
+cbsmail.constangy.com
+ccisd.us
ccmail.cc.gatech.edu
+ccpb-basse-normandie.fr
+ccpvpn.ccpdocs.com
+cdcpoint.it
+cdfbooks.com
+cdmwsa.com
+cdp.moduspec.com
+cduvpn.cdu.edu.au
+ce.byu.edu
+cedardoc-cm.com
+cedardoc-demo.com
+cedardoc-dev.com
+cei253e.com
celebrateyourfaith.com
+celebritysweatnelly.com
+celtipharm.net
+cemex.com
+centralmississippimedicalcenter.com
centralr.com
+centrum.cz
+centuriondirect.com
+ceramicreview.com
certs.zurich.co.uk
+cespmi.org
+ceuherning.dk
+cfai-centre.net
+cfliving.com
+cfw.org
+cgi.mbs.jp
+ch.cutler-hammer.com
champions-online.com
+channeladvisor.com
+chapmantripp.com
+charlotteregional.com
+charltonschool.net
+chasslvpn.ecommunity.com
+checkoutblog.com
+cheizoo-sp.online-documents.net
+chester.ac.uk
+chesterregional.com
+chevrolet-leadengine.de
+chiaobama.ca
+chiaobama.tv
+chiba.jp
+chill-n-go.com
+chinookhosting.com
+chinooknetworks.com
+chl-peq.co.uk
chnla.com
+chocolatefactorytv.com
+choicebuilder.com
+churchill.n-somerset.sch.uk
chw.recruitmax.com
ciaoitalia.com
+cic-valencia.org.ve
+cifex.ethz.ch
cinema.warnermycal.com
circlesofwisdom.com
+cisco.com
cisr-ssl-vpn2.univ-lyon1.fr
citi.bridgetrack.com
+citicards.com
+citiforward.com
+citixcard.co.jp
citizensfla.com
+citonline.com
+citynet.net
+ckbmail.me
+clarity.com
claritycon.com
+clarksoncollege.edu
+claroline.lakato.net
classbauth.austin.hp.com
+classicsoftrock.com
+classifiedventures.com
+clayko.com.au
+click.showcase-tv.jp
+clickanalyzer.jp
+client.neftex.com
+client.uniastrum.ru
+clients.mdmatic.com
+clineavestudy.com
+cloroxspss.com
+cloud-mail.co.uk
+cloud.carthagecsd.org
+cloud.mvctc.com
+cloud.santeesd.net
+cloudconnectsd.net
+cloudhoist.com
+cloudmail.trustcld.com
+cloudonestorage.peer1.com
+cloudspeaker.fm
+cloudworks.com
+cm.commercehub.com
+cmithun.dojiggy.com
+cms.whereilive.com.au
+cnw.albertaequestrian.com
+cnw.hcbc.ca
+codarts.nl
+coddy.com
cofunds.co.uk
+cohowa.houstontx.gov
+collaborate.sandia.gov
+colorectalcancerconnections.com
combattesting.com
+commandaware.com
+commentor.dk
+commissies.ser.nl
+commonwealth.int
+communitylakes.com
+compass.emmanuelschools.net
+compass.oxiana.com.au
compaxtrade.com
-confirmit.suw.corp.google.com
+compellent.com
+complete180degree.com
+comporium.com
+comprabuxton.com
+comprariddexpulse.com
+comprasnuggie.com
+compratastiwave.com
+compreabrocket.com
+compupaypartner.com
+compus.de
+computerstore.be
+computerstore.nl
+coms.industrialcontrolrepair.com
+concat.de
+concur.csmc.edu
+conduxio.com
+config.tplpbx.de
+confluence.mediaspectrum.net
+connect.bangor.ac.uk
+connect.clearpointe.com
+connect.coventry.ac.uk
+connect.dpem.tas.gov.au
+connect.plan-b-gmbh.com
+connect.studygroup.com
+connecta.se
+consoleshop.be
+consoleshop.nl
+construction-ec.com
+contitiremanagement.com
+controlpanel.ch
+coolblue.nl
+coop-kobe.net
coopervisionrebates.com
+coorscup.com
+copeskoal.com
corporate.bpn.pt
+corpset.com
+correctionalbillingservices.com
+correio.fdc.org.br
+correio.ina.pt
+correo.entelpcs.com
+correo.orizonia.com
+correo.psl.com.co
+correo.tec.ac.cr
correo.uft.cl
+cortesoft.com
+costco.com.mx
+couplesnuggie.com
+courriel.jlp.ca
+courriel.journalmtl.com
+courriel.lepisc.com
+covlecremote.org
+covnet.covenantretirement.org
+coyoteportal.wc.edu
+cozi.com
+cp.billing.ru
+cp.it2all.eu
+cpas.cz
+cportal.sechan.com
+cprmc.com
+cpsb.org
+cpse.dundee.ac.uk
+cranbrook.kent.sch.uk
+crci.org.uk
credinamico.programapar.com.br
creditcards.citicards.com
+creditunionon.com
+creuna.dk
+crew.transavia.com
+criny.com
+crmpartners.crmpartners.org
+crnbc.ca
+croc.ru
+crossgatesriveroaks.com
+cryptolab.org
+crystalfunds.com
+crystaltools.com
+csaa.com
+cscinfo.com
+csp.cvut.cz
+csst.qc.ca
+ctasanywhere.centraltas.co.nz
+ctdhe.org
cts.vresp.com
+cu.edu
+cuatrecasas.com
+cubewano.com
cubizone.com
+customer.comcast.com
+customer.dgrefining.com
+customer.gbs-consult.com
customer.precash.com
+customer.unicaresys.com
+customerconnect.scholasticbookfairs.com
+cusys.edu
+cv.occstrategy.com
cvintranet.classifiedventures.com
+cwa.astra-honda.com
+cwa.avanade.com
+cwa.fandr.com
+cwa.telecomputing.no
+cwt.no
+cwtnordic.com
+cybershoppersonline.com
+d-ikt.no
+d-starjob.com
+d115.de
+d15email2010.d15.us
d49.org
+daidalos.nl
+daiwa-bs.co.jp
+dalinis.net
+dallasregionalmedicalcenter.com
+danks.com.au
+daphne.gfk.com
+dasa-dortmund.de
+data.eglia.com
+dataformas.com
+dataliberation.com
+datasettlement.com
+datatel.com
+davidson.edu
+davisregional.com
+dbpn.com
+dc.myflorida.com
+dc110.4shared.com
+dcess.dallascounty.org
+dcvpn.cov.com
+de-mail.de
+deadliestdvd.com
+decc.gov.uk
+dehaagsescholen.nl
+deklimboom.nl
+deloitte.com
+deloitteresources.com
+delorentz.nl
+deltek.forceprotection.net
+demo.crm4destinations.at
+dentalxchange.com
depo.ru
+deshaw.com
+design.cscape.com
+design.nzzdomizil.ch
+designersnuggie.com
destinationlighting.com
+deutsche-islam-konferenz.de
+developer.smartapp.tw
+development-school.jp
+device.fancast.com
+dexia.be
+dexter.ansaldo-sts.us
+df.co.kr
+dfc.inovestor.com
+dhhnet.dhh.louisiana.gov
+dhs.edu.sa
+diamail.diadubai.com
+dice.com
+dienstleistungszentrum.de
+digi.mobilethink.net
+digicamshop.be
+digicamshop.nl
+direct.msn.com
+direct2wholesale.com
+directv.com
+disc.co.jp
+discomp.cz
+discovertotal.com
+discovwww.waterford.k12.mi.us
+dishnetwork.com
+disneydigitalshare.com
+dist113.org
+district205.net
djmmusic.com
+dl.com
dl.rakuten.co.jp
dmgov.org
+dmz.rgcweb.org
+docmesa.com
docstoc.com
+docufide.com
docuware.com
+dodgeprojects.construction.com
+doe.gov
dokeos.ehb.be
+dolandesigns.com
+domain.amta.com
+dosco.com.tw
+dpwn-airlinesourcing.com
+dr.rachisholm.com
drammen.skole.d-ikt.no
+drimanagement.com
+drlists.com
+drm.nl
+droppstv.com
+drs-digital.com
drsha.com
+drudeans.com
dskdirect.bg
+dsl-art.org
+dsoguild.com
+dtvce.com
+dualforceaccessories.com
+dualsaw.com
+dualsawcanada.ca
+dualsawspanish.com
+dunamare.nl
+dupnet.org
+durham.ca
+durringtonhigh.w-sussex.sch.uk
+duvak.nl
+dvlottery.state.gov
dwarest.disc.co.jp
+dws.com.au
+dynamicscrm.asia
+dynetics.com
+e-billing.econgas.it
+e-cap.fr
+e-denpo.net
+e-healthnet.mhlw.go.jp
e-lotto.be
+e-mechatronics.com
+e-mergedata.net
+e-quilibrium.net
+e-state.co.jp
+e-state.ne.jp
+e-trade-center.com
+e-usluge.rijeka.hr
+e-valuer.com
+e-zoa.com
+earlybird.ae
+earlyedcloud.net
+earnplaza.com
+earthclassmail.com
+eastgate1.frontiercorp.com
+eastgeorgiaregional.com
+easv.dk
+easweb.thecdmgroup.com
easybillindia.in
+easyhome.com.tw
+easymovewithfios.com
+easyreachoffer.com
+easyreachtv.com
easyswitch.nl
+eaton.com
+eazifleet.com
ebb.ubb.bg
+ebencom.com
ebit.com.br
+ec.broadom.net
+ecafe.lahey.org
+ecare.proctor.org
echo.com
+echostar.com
echotrak.com
+eclipse.molagers.org
+ecom.peoples-bank.com
+ecommerce.colsubsidio.com
econda-monitor.de
+ecwid.com
edaccents.com
+edenbrook.co.uk
+edinet.cenet.ws
+edu.on.ca
+education.vic.gov.au
edumail.tokem.fi
+edumail.vic.gov.au
eduportal.pl
+eduweb.vic.gov.au
+edziekanat.wsf.edu.pl
+efo.adplan-tg.com
+ehb.be
+ehs.dk
+ehub.dsionline.com
+eiffel.nl
+einfach-teilhaben.de
+eisweb.enterinfo.com
+eku.edu
+elibrary.asdealernet.com
+elibrary.comfortsite.com
+elliottdevon.com
elm.mcmaster.ca
elmls.mcmaster.ca
+elogistic.motorola.com
+elpodercd.com
+elproman.biz
+els.cis.fukuoka-u.ac.jp
+els.streetly.walsall.sch.uk
+email-internet.pekao.com.pl
+email.arbora-ausonia.com
+email.campus.uvt.nl
+email.cosan.com.br
+email.eatoncounty.org
+email.energy-northwest.com
+email.frostburg.edu
+email.fusionsys.com.mx
+email.greatershepparton.com.au
+email.hermos-vhm.de
+email.jyu.fi
email.manutouch.com.hk
+email.masku.com
+email.medianewsgroup.com
+email.mycontact.co.nz
+email.ndm.edu
+email.phillynews.com
+email.piraeusbank.gr
+email.sjb.com.au
+email.sjbcommunity.ca
+email.starair.dk
+email.stpeters.qld.edu.au
+email.stpeters.sa.edu.au
+email.svcfs.org
+email.uk.betfair.com
+email.unity.net.nz
+email.usiu.ac.ke
+email.wallawalla.edu
+email.whgardiner.com
email.wsd1.org
email.yorksj.ac.uk
+email2010.smu.edu.sg
+emanet.com
+embeddedwebserver.net
+emea.archive.messaging.microsoft.com
+emeamail.corp.salesforce.com
+emedic.jp
+emergenow.com
+emericalinksite.com
+emersonhosp.org
+emerycat.ca
+emerycat.com
+emerycatrefill.ca
+emerycatspecialoffer.com
+emi.eu
+emi.hu
+emploi.sitq.com
+employee.coastmountainbus.com
employee.translink.bc.ca
+empresas.bancobcr.com
+enav.it
+endlager-asse.de
+endlager-konrad.de
+endtoendsourcing.com
+enhancedservices.paetec.com
+enrol.ie
ent.enteduc.fr
+ent95.valdoise.fr
enterprise.channeladvisor.com
+envisionitsolutions.net
+eod.teamcolts.net
+eoir.com
+eom.performance.gr
+epaveiro.edu.pt
+epistrofi-eurobank.gr
epk.tv
+eplus.jp
+epm.com.co
+eportal.fleetwoodhs.org.uk
+eportal.shelfieldcommunityacademy.co.uk
+epost.ha.kommune.no
+epost.luftnett.com
+epost.skola.ljungby.se
+epost.uddevalla.se
+epost.visma.no
epoti.abanka.si
+epsb.ca
equippers.com
+equitydriver.com
+ercasharepoint.com
+ereaderstore.be
+ereaderstore.nl
+erecruit.thechildrenshospital.org
+ereg.biz
+ergo.ergonomidesign.com
+ergonet.pl
+erhgroup.com
+ericom.com
+erivpn.eisai.com
+eroom.arvato-systems.de
+esabilgisayar.com.tr
+esales.master.ca
+esdlife.com
+eshbelhost.com
+eshbelsaas.co.il
+eshbelsaas.com
+esher.ac.uk
+eskilstuna.se
+esloo.nl
+espaicambrabcn.org
+especificacoes.com
+esportivaparana.com.br
+espprofitlink.com
+estore.hpfairfield.com
+estrellamountain.edu
+etk.fi
+etrack.teletrack.com
+ettu.nl
eumail.nov.com
eurobank.pl
+europ-assistance.pt
+europa.eu
+europass.cz
+europlan.ru
+eurotax.at
+events.sainc.com
+evergabe-online.info
+evoline.net
+evoraoralcaresite.com
+evpn.techteam.com
+ex.uni-paderborn.de
+exadmin.rcs-mail.com
+excels.org
+exch-hub.cancer.dk
+exch.naaco.ru
+exchange.berden.nl
exchange.chc.be
+exchange.clarkslegal.com
+exchange.clearwaterpaper.com
+exchange.cs-soreltracy.qc.ca
+exchange.datacom.com.au
+exchange.dcpud.net
+exchange.gilacountyaz.gov
exchange.hostnet.nl
+exchange.intranet.neumanpools.com
+exchange.keyhie.org
+exchange.khlim.be
+exchange.knpc.net
+exchange.mit.ie
+exchange.netbit.ch
+exchange.public.eibs.co.uk
+exchange.raakict.nl
+exchange.roteskreuz-tirol.at
exchange.selco.info
+exchange.tinozplace.com
+exchange.uetcl.com
+exchange.uniserver.nl
+exchange.unitek.com
+exchange4u.cz
+existenzgruender.de
+exmail.businesslinksoutheast.co.uk
+exmail.med.uni-magdeburg.de
+expesite.com
+ext01.lifesouth.org
+extclt.isatech.fr
+extern.balslev.dk
+external.piggott.wokingham.sch.uk
external1.collaboration.hp.com
extra.chrysler.de
+extranet.4ward.it
+extranet.calvis.com
+extranet.cbr.nl
extranet.cchmc.org
+extranet.cec.org
+extranet.chaco.com.bo
+extranet.dialoggroup.biz
+extranet.hbj-gw.com
+extranet.infoproject.fr
+extranet.jbdelasalle.com
+extranet.lackverband.de
+extranet.metabolomicscentre.nl
+extranet.ministryofsound.com
+extranet.mm-software.com
+extranet.pandasoftware.com
+extranet.portalsolutions.net
+extranet.sysmex.com
+extranet.transpondertech.com
+extranet.ubgonline.net
+extranet.winchester.com
+eyelovelytv.com
+eyeonamd.com
+eyeonamd2.com
+f-seneca.org
+faberwebshop.nl
+faimai.hcri.net
+falcontrading.ro
+falmouth.cornwall.sch.uk
+fanclub.tokyodisneyresort.co.jp
+fanniemae.com
+farefinder.de
+farsigeotech.com
+fastmvr.com
+fastsearch.com
faxbetter.com
+fcaamd.com
fdc.org.br
+fe-bud.mag-news.it
+fedintel.net
+feitest.com
+felixlive.com
+fema.gov
+fenwalinc.com
+ffis.es
+fhvasa01.flhosp.org
+filexchange.accarda.com
financialengines.com
+finansnet.dk
+finn.no
+fiosfriends.com
+fire.tas.gov.au
+firma.pcs.cz
+firmaface.com
firstam.net
+firstassistinsurance.co.uk
+firstassistinsurance.com
+fish4.co.uk
+fishermenshospital.com
+fit.ba
+fiu.edu
+fiztrade.com
+fjarvinna.grund.is
+fleetwoodsc.org.uk
+flhsmv.gov
+flirtygirlfitca.com
+floodlands.com
+floodonline.com
+floodplus.com
+floodplus.net
+flowerpowercds.com
+flowersbelgium.hostbasket.com
flydenver.com
+fmglobal.com
+fmpro.cati.com
+fokusanalys.se
+folkestonegirls.kent.sch.uk
+footnote.com
+footnotelibrary.com
+ford.com
+form-gic.altran.net
+formassist.jp
+forms.lasikmd.com
+forms.techdata.net
forums.champions-online.com
forums.startrekonline.com
+fossport.com
+foto.mitlejerbo.dk
+foxtix.com.au
+fpcu.org
+fr.powerjuicerpro.ca
+frankfurt-oder.de
+frankfurter-bankgesellschaft.ch
+franklinregionalmedicalctr.com
+freebioven.com
+freegrillglovetv.com
+freehandycaddy.com
+freerejuvenateautotv.com
+freerejuvenateca.com
+freerejuvenatetv.com
+freo.ne.jp
+fridgelockertv.com
+fs-efo.jp
+ftp.cambridge-design.co.uk
+ftp.lim.com
+ftp.maedapat.co.jp
+ftsportal.forensicsandediscovery.com
+fubar.com
fucam.ac.be
+fuchs-datentechnik.de
+fueldoctorcanada.ca
+fueldoctorfd47.com
+fueru.jp
+fuji-ie.com
fullseat.com
+fultonschools.org
+fusdaz.org
futuretrails.com
+fv-group.net
+fw01.monheim.de
+fx.sovereignbank.com
+fxedge.trader.integral.net
+fxinside.net
+fye.com
+g4s.se
+gakushuin.ac.jp
+gamania.com
ganymede.chester.ac.uk
+garconet.garco.com
+garmin.com
+gate.we-learn.org.uk
+gatech.edu
+gatekeeper2.aspectsecurity.com
gateway.madisoncity.k12.al.us
+gateway.sagemontchurch.org
+gbssg.ch
+gcc.edu
+gcportal.guycarp.com
+gda-portal.de
+geicocard.com
+geicocreditcardapplication.com
+gemini-apx.com
+gene.com
+genentechaccesssolutions.com
+genentechmm.com
+geniusreport.com
genuineonlinebank.com
+geomant.com
+geometrik.golder.se
+geonosis.itsso.gc.ca
+georgefox.edu
+gepartsrebates.com
+germfree.org
+get1931roadster.com
+get1933caddy.com
+get2instantcover.com
+get31roadster.com
+get6weekbodymakeover.com
+get911twentynow.com
+getair-o-sage.com
+getbendaroostv.com
+getbestline.com
+getboomaringnow.com
+getcablecapture.com
+getcan-air.com
+getchefandgo.com
+getclassicfriarsroast.com
+getclassicsforrelaxation.com
+getcomfortfurnace.com
+getcozycolors.com
+getdigitalbiblenow.com
+geteasyreach.com
+getefx.com
+geteggiestv.com
+getesiobev.com
+geteyetality.com
+getflexibrite.com
+getflipperremote.com
+getgianttomato.com
+getglowbeam.com
+getgreenbags.tv
+getgyrobowl.com
+gethandyvalet.com
+gethealthsupplies.com
+gethightenz.com
+geticanonlyimaginecd.com
+getiknowkey.com
+getionpod.com
+getirenewnow.com
+getjupiterjack.com
+getkuddles.com
+getlesko1995.com
+getmatthewleskoquickstart.com
+getmightyputtynow.com
+getmiracleplunger.com
+getmonstersteamjet.com
+getmorgans.com
+getmpgreennow.com
+getmy.com
+getmybedsidetable.com
+getmydreamtable.com
+getmyt4.com
+getmytaxform.com
+getmyw2.com
+getmyyobaby.com
+getnazidvds.com
+getnuwaveovennow.com
+getopeneyesofmyheart.com
+getoprydvd.com
+getpalmwallet.ca
+getparkbillstv.com
+getpetmdnow.com
+getpopmemories.com
+getpuplight.com
+getrejuvenate.com
+getrejuvenateautotv.com
+getrejuvenateca.com
+getromancingthe70scds.com
+getsanistep.com
+getscrubglove.com
+getseatwedgy.com
+getsecretsolutiontv.com
+getshakeweight.com
+getshakeweightnow.com
+getshockitclean.com
+getslimts.com
getslimtsnow.com
+getswirlyclip.com
+gettheemerycat.com
+gettheturbosnakenow.com
+getthewonderhanger.com
+getultimaterockballadscds.com
+geturinegone.com
+getvibrobelt.com
+getvietnamwardvds.com
+getwiperwizardnow.com
+getworkout180.com
+getworldatwar.com
+getworldatwarespanol.com
+getworldofreading.com
+getyourpajamajeans.com
+getzasshu.com
+getzerogerm.com
+getznowonline.com
+gezeb.cmpd.org
+gfk-repinsight.com
+gfkdaphne.com
+ggu.edu
+ggusd.us
+ggy.com
+gilmorehealth.com
global2.mtsallstream.com
+glove.mizunoballpark.com
+glowinghealth.com.au
+glueckkanja.net
+gmb.org.uk
+gmxy.org
go.enbw.net
+go.post.de
goamp.com
+gogamer.com
+golan.wisela.org
+goldflux.com
+golfdo.com
+golfersland.net
gomopa.net
+goodfellowbros.com
+goodyear.com
+goquickstart.com
goredsea.com
+gorm.tauron-pe.pl
+got-root.ch
gotobelfast.com
+gotomypc.rareeditions.com
+gov.on.ca
+gpsshop.be
+gpsshop.nl
+gpz.it
+gr-espel.com
+graceselah.com
+gradwellintra.net
+graniteschools.org
+greatsankey.org
greenpower24.com
+grillingadget.com
+gripperglovestv.com
+gristedes.com
+grizridge.com
+grmetrieve.com
+grmorc.com
+groenewelle.nl
+grotiuscollege.nl
+gruenderpreis-nominierung.de
+grupalotos.pl
+gsmstore.be
+gu.se
+guardiant.com
+guardiantauto.com
+guhsdaz.org
+gw.alumni.iae.edu.ar
gw2.fli.bund.de
+gw2.vincentz.de
+gynspecialistsorlando.com
+gzb.info
+ha.jmpextra.net
+hadar.fr
+hades.tens.pl
haken.mynavi.jp
+hakwr-neustadt.ac.at
+halton.ca
+hammerofgod.com
+hancockbank.hb2go.mobi
+hancockfabrics.com
+handelwandel.com
+handydryer.com
+handyvalettv.com
hangikredi.com
+hapimag.com
+happyoz.com
+harborwholesale.com
+harbottleonpremise.com.au
+hardandheavycds.com
+hardpoint.eu
+harrisdseries.com
+harrisvle.org.uk
+hartonmedicalcenter.com
+hartslagmetercenter.be
+hartslagmetercenter.nl
+harvard.edu
+harvestbible.org
hastingsdirect.com
+hastingsessential.com
+hatchearlychildhood.com
+hcc-tripod.hoffmancorp.com
+hccanet.org
+hclab.jp
+hcmysteryshop.com
+headsetshop.be
+headsetshop.nl
+healthinsurance.org.au
+healthportdirect.com
hearablog.com
+heartofflorida.com
+heartoflancaster.com
heavens-above.com
+heeltasticpedeggpromo.com
+heelusa.com
+helinium.nl
helpdesk.clear2pay.com
+helpdesk.sarnt.co.uk
+helpdesk.v-h.nl
+helpdesk.yhc.edu
helwanbb.com
+henleycol.ac.uk
+hensongroup.com
+her2genes.com
+herceptin.com
hercle.com
+herconnection.com
+herculiteondemand.com
+hesse-lignal.de
+hetassink.nl
+hhc.acerebates.com
+highlandsregional.com
+hillgatetravel.com
+hillsgradprogram.com
+hipcomputer.de
+hire.acxiominsight.com
+historybeat.com
hivanet.hitachi-ies.co.jp
+hj2.hjemmekontor.nhn.no
+hma.com
+hmc.it-ernity.nl
+hmc.vdx.nl
+hnvpn.hostnordic.com
+hoganas.se
+hoken-clinic.com
hoken-clinic.info
+hollywoodhobobagaccessories.com
+hollywoodhobobagtv.com
+home.ceadvisors.com
homedepotrebates.com
+homespot.dk
honeybakedonline.com
+honeywellusersgroup.com
hood.com
+hoodhomedelivery.com
+hoodneighborhood.com
+hoofdtelefoonstore.be
+hoofdtelefoonstore.nl
+hopline.net
hostedjobs.openhire.com
+hosting.privatehost.nl
+hostpoint.ch
+hosttraxx.com
+hotelleriesuisse.ch
+householdshop.nl
+housingservices.com
+houstonisd.org
howtowritearesume.net
+hox.biz
+hq.eisenhowerlaw.com
+hq.nimvpn.com
+hq.totalengineering.biz
+hqaccess.acs.org
+hro-gate.aida.de
+hrwow.com
+hs.ct-net.nl
+hsacalifornia.com
+hubpen.biz
+hull.ac.uk
humana.recruitmax.com
+humanadental.com
+hurleymc.com
hurmail01.hurriyet.com.tr
+huronconsultinggroup.com
+huttonhotel.com
+hva.nl
+hwinet.org
hydra.cusys.edu
+hypecits.com.au
hz.nl
+i-95alternatives.com
+i-ecnet.co.il
+i-teamroom.com
+i485project.com
+iata.invoiceworks.net
+ibank.mpbsecure.com
+ibank.sabank.hr
+ibank.snoras.com
+ibc123.com
+ibc168.com
+ibc4u.com
+ibc818.com
+ibc888.com
+ibcbet.com
+ibet888.net
+ibqonline.com
+ibweb.alphabank.ro
+icc-cpi.int
+icecream-money.com
+iconnect4.interiorhealth.ca
+ict.gov.qa
+id.telecom.pt
+identity.ppdi.com
+identitymine.com
+idrettsmail.no
+ie.com
+ifa.ch
+ifraudalert.org
+ifs.thaeles.nl
+igaseguros.com.br
+igc.infragard.org
+igeinfo.com
+igniterealestatesite.com
+igweb.meridiana.it
+ihale.gov.tr
+iiarc.net
il.systemb2b.com
il2l.com
+ilsole24ore.com
+im-sc.com
+im.its.iastate.edu
+images.bdotickets.com.au
+imageworksdisplay.com
+imail.healtheast.org
+imakenews.com
+imediador.com
+img.mspub1.com
+imgroup.com
+imgssl.shinsegae.com
+imperva.com
+ims.esdcar.org
+imsbackyardfightclub.com
+imsbi.com
+imsbuyezcombs.tv
+imsbuyquicklawn.com
+imsbuyshoesunder.tv
+imschools.org
+imscleverclips.com
+imsdualforce.com
+imsfiftydollargold.com
+imsfridgegenie.com
+imsfueldoctor.com
+imslappertrays.com
+imsmightybite.com
+imsmightybitetv.com
+imspalmwallet.com
+incircle.alphaomicronpi.org
+incircle.alumni.american.edu
+incircle.artcenter.edu
+incircle.ato.org
+incircle.cmualum.com
+incircle.drexel.edu
+incircle.lagrange.edu
+incircle.mainealumni.com
+incircle.sae.net
+incircle.tridelta.org
+incircle.umalumni.com
+incircle.usfalumni.org
+incircle.westwood.edu
+incircle.wiu.edu
+incirclepro.com
+incolink.org.au
indraweb.indra.es
+indstate.edu
+inetportals.com
ineways.com
+ineways.eu
+inewayscanada.com
+infineon-farefinder.com
+info.broadsoft.com
info.enet-japan.com
+info.oebv.com
+infobear.bridgew.edu
infonet.hz.nl
+infosupport.com
+inframan.nl
+ing-diba.at
+ing-hipotecaria.mx
+ingramentertainment.com
+inlogin.com
+innmarinsecure.com
+inos.nl
+inria.fr
+insattningsgarantin.se
+inscodico.com
+inside.cod.edu
+inside.consona.net
inside.nhl.com
+inside.santamariaworld.com
insight.smartdm.com
+insite.henrich.de
+instantfisherman.com
+instantintelligence.com
+insurancebis.com
integrishealth.recruitmax.com
+intellilink.visa.com
+intellium.co.nz
+interact2.ird.govt.nz
+interconnect.be
+interhosting.interfree.it
interiorsandsources.com
+interlaken-congress.gosecure.ch
+intern.abm-energie.de
+intern.abm-service.de
+intern.goebel.de
+intern.med-bz.de
+intern.svk.no
internal.imaginets.com
+internal.ppww.org
+internal.razimports.com
+internap.com
+intersourcing.com
+intex.com
+intra.2at.net
intra.billing.ru
+intra.motion10.com
+intra.nordfyns-gym.dk
+intra.svendborg-gym.dk
+intra.unbonn.org
+intranet.1-first.com
+intranet.2nsb.org.au
+intranet.a3is.com
+intranet.abesse.hu
+intranet.bexleygs.co.uk
+intranet.bhtc.sandwell.sch.uk
+intranet.britishscienceassociation.org
+intranet.carrel.fr
+intranet.ceff.ch
+intranet.chilcote.bham.sch.uk
+intranet.espria.nl
+intranet.frederikssund.dk
+intranet.grupocopisa.com
+intranet.hallwilcox.com.au
+intranet.ipi-gmbh.com
+intranet.itsduero.es
+intranet.majedie.com
+intranet.mhc.cc
intranet.peckham.org
+intranet.scriptum-site.nl
+intranet.stanville.bham.sch.uk
+intranet.uck.nl
intranet.ucol.ac.nz
+intranet.xperta.se
+intuit.com
+intuitrebates.com
inverhills.edu
+investissementsdavenir.agencerecherche.fr
+inzicht.dfa.nl
+ioffer.com
iol.pt
+iowaworkforce.org
+ip.clubcorp.com
+ipayables.net
+ipi-interactive.com
+ippo.net
+iqmetrix.com
iqsystem.irrc.co.jp
+iraniansinglesconnection.com
+iris.colum.edu
+irrc.co.jp
+ish-bridge.com
+ishbs.com
+isi-net.com
+isic.hu
+isstct.cz
+issuemanager.myriad-it.com
+istoreit.net
+isupplier.americanlafrance.com
+it-consult.net
+itgroovehosting.com
ito.org.tr
+itoncloud.com
+itrackit.net
itrade.fhtrust.com.tw
+itsfogo.com
+itsyourview.com
+itunescards.co.za
+iva.de
+ivoo.certiris.be
+iwcc.edu
iweb.thebankersbank.com
+iyummy.com
j-union.com
+jac.go.jp
+jamestownregional.com
+japanpost.jp
jasaga.or.jp
+jasmenterprises.com
+jazanu.edu.sa
+jeddah.zfp.com
+jennisondryden.com
+jerseymanagedhosting.com
+jerusalem.muni.il
+jetblue.com
+jgh.com.sg
+jhop.jp
+jmlexaktsaw.com
+jmlfastfit.com
+jmlmagiccarpet.com
+jmlscratchremover.com
+jmlsmoothit.com
+jmltwisteze.com
+jmsapps.jmsmucker.net
jnet.agsys.sompo-japan.co.jp
+joagift.com
job.disc.co.jp
job.nikkei.co.jp
jobmgr.disc.co.jp
+jobs.1800contacts.com
+jobs.carlsonhotelsasiapacific.com
+jobs.cas.org
+jobs.sourcefire.com
+jockjam.nl
+joeys.org
+journie.net
+jr.com.au
+jrfh.tsacorporation.com
+js.joomlaservices.ca
+js.metalinq.com
+jsps.go.jp
+jta.jtafla.com
+jtasoutheast.com
+jumbomortgage.citimortgage.com
+juneau.billeo.com
+juronghealth.com.sg
+k12.al.us
+k12.ks.us
+k12.mo.us
+k12.mt.us
+k12.nm.us
+k12.pa.us
+k12.sc.us
+k12.wa.us
+k12.wi.us
+k9glowguardtv.com
+kabeldeutschland.com
+kabukiza-kabu.com
kahosl.be
+kalender.nakskov-gym.dk
+kanagawa.jp
+kanjam.com
+kaosmos.jp
+karierasro.cz
+katlehotrust.co.za
+kawacki.com.br
+kb.mbms.com
+kbacmportal.net
+kcc.com
+kcn.jp
+kddi.ne.jp
keas.com
+keitaipost.jp
+kemi.se
+kenkou-design.com
+keybankdeveloper.com
+kfz-versicherung.faz.net
+kgh.on.ca
+kicho.shoko-shimane.or.jp
+kidneycancerconnections.com
kimberlyclark.myvurv.com
+kindenonderwijsrotterdam.nl
king-invest.net
kingsdominion.com
+kingsize-bottle.com
+kingsmail3.kings-ely.cambs.sch.uk
kingsroadmerch.com
+kingston-college.ac.uk
+kinsou.com
+kintetsu-bs.co.jp
+kintetsu-hoken.co.jp
+kipp.org
+kirenet.com
+kit.ac.jp
+kkcom.co.jp
+klc-ondemand.com
+klerx.biz
+klikbca.com
+klive.kellogg.edu
+klz.org.uk
+kme.ch
+knox.nsw.edu.au
+koffiecenter.be
+koffiecenter.nl
+kohlaborate.com
+kontor.polytec.no
+kordia.net.nz
+korowa.vic.edu.au
+kpchoicesolution.com
+kpos.melsc.co.jp
+kramesondemand.com
+kredinor.no
+krungsricashlink.com
+krungsrifileserver.com
+krungsrimobile.com
+ks.gov
+ktr.com
+ku.dk
+kuanywhere.ku.edu
+kuk-networks.de
+kulturgutschutz-deutschland.de
kwiktrip.com
+kwv.nl
+kyfb.com
+kymweb.tokoha-jc.ac.jp
+kymweb.tokoha-u.ac.jp
+labs.arubanetworks.com
+ladyphoneshop.be
+ladyphoneshop.nl
+lakecomm.com
+lambertconsulting.ch
+lamda.org.uk
+lancasterregional.com
+lancer.webhosting.uk.com
+laprevisionmallorquina.com
+laptoporder.wab.edu
+laptopshop.be
+laptopshop.nl
+larix.cevak.cz
+las.perkinelmer.ca
+las.perkinelmer.co.uk
+las.perkinelmer.com
+latax.lacity.org
+lavprisfly.no
+lbiclaim.com
+lbschools.net
+lc.leics.sch.uk
+lcgs.tas.edu.au
+lead.rotary.nl
+leadintelligence.co.uk
+leadrouter.com
+leap.neustar.biz
+learningseat.com
+learningseat.com.au
+learnsheffield.com
+leben-hat-gewicht.de
leerlingmail.niftarlake.nl
+legacy.lcpharma.com
+legacy.medietilsynet.no
legalconnection.com
+legalease.jmls.edu
+lehighregional.com
+lendingpit.com
+lendingtreeautos.com
+leopards-den.us
+leshamwowoffre.com
+level.mol.hu
+lexor.lsp.at
+lexsan.vestingonline.nl
+lh.k12.ar.us
+library.failteireland.ie
+liemerscollege.nl
+lifeaction.net
+lifeio.com
+lifenetems.org
+liftmonitoring.nl
+liftnfix.com
lightstone.co.za
+limewire.com
+lincoln-obama.com
+linkmanager.shalink.com
+linkservicepro.com
+linkzeal.com
+lion.wild.net
+lipa.ac.uk
+lisa.lpshp.fi
+listech.com
+lit.edu
+liu.se
+livegrades.com
+livingwithcll.com
+livingwithlymphoma.com
+ljbc.wa.edu.au
+lkmc.com
+lks.jackhenry.com
+lmmis.com
+lms.kansaigaidai.ac.jp
+lnrmc.com
+loanet.net
+loans.citifinancial.ca
+loans.citifinancial.com
+loanstowomen.com
+localret.cat
+lodge.maishima.co.jp
+logica.com
+logicnet.pc-ware.org
login-pos.eurobank.pl
login-raty.eurobank.pl
+login.aderantpm.com
+login.bcferries.com
+login.bild.de
+login.clientaccess.net
+login.danskerhverv.dk
+login.dtl.eu
+login.skwich.com
+login.smmj.com
+login.visionalist.com
+logixs.com
+logowanie.osemka.pl
+london.edu
+loro.ch
+loterie.ch
+loucoll.ac.uk
+louisianaappliancerebate.com
+lpb.dueri.net
+lsu.edu
+lucentis.com
+lucky-pantry.net
+luckybuy.com.tw
+ludus.greve-gym.dk
+ludus.grindsted-gym.dk
+ludus.maribo-gym.dk
+ludus.midtfyns-gym.dk
+ludus.roskilde.dk
+ludus.vuc-vsn.dk
+ludusweb.akat.dk
+ludusweb.frberg-gym.dk
+ludusweb.fredericia-gym.dk
+ludusweb.herninghfogvuc.dk
+ludusweb.horsenshfogvuc.dk
+ludusweb.middelfart-gym.dk
+ludusweb.roende-gym.dk
+ludusweb.toender-gym.dk
+ludusweb.tornbjerg-gym.dk
+ludusweb.vejle.dk
+ludusweb.vucaarhus.dk
+ludusweb.vucfyn.dk
+ludusweb.vucha.dk
+ludusweb.vuckolding.dk
+ludusweb.vucroskilde.dk
+ludusweb.vucstor.dk
+ludusweb.vuctm.dk
+ludusweb.vucvest.dk
+lukeassoc.net
+lumalamps.com
+lungcancerconnections.com
+lusitania-cs.pt
+luxoft.com
+lvmpd.com
+lvs1.com
lxr.com
+m.aafes.com
+m.stackmedia.net
+maandag.nl
maartenluther.calvijn.nl
+maastrichtuniversity.nl
+macaw.nl
+macihotline.com
+maconomy.com
+madisonregionalmedicalcenter.com
magelo.com
magtek.com
+mail.abz.ch
+mail.accretivehealth.com
+mail.achap.org
+mail.acousticalspecialties.com
+mail.activision.co.uk
+mail.aeat.co.uk
+mail.albany.k12.ny.us
+mail.albil.com.tr
+mail.alexdejong.com
+mail.almajles.gov.ae
+mail.amrita-parus.ru
+mail.anbank.com
+mail.aocterra.nl
+mail.aps.k12.co.us
+mail.arcelormittal.kz
+mail.asapnet.nl
+mail.asascience.com
+mail.asmnet.com
+mail.auscampus.net
+mail.avalonhealthcare.com
+mail.avanquestusa.com
+mail.axemusic.com
+mail.axens.net
+mail.banquemisr.com
+mail.baptisthealth.net
+mail.bb.softbank.co.jp
+mail.bbms.no
+mail.bedeck.co.uk
+mail.behr.ch
+mail.beveric.com
+mail.bfds.com
+mail.bfw-mainz.de
+mail.bigfishgames.com
+mail.bilia.net
+mail.borgmanschool.nl
+mail.bornholmstrafikken.dk
+mail.bpsd.mb.ca
+mail.burohappold.com
+mail.cafuamanagement.com
+mail.cardinalhume.com
+mail.cba.edu.sa
+mail.ccina.ro
+mail.ccsmgr.com
+mail.cdh.com
+mail.ceat.in
mail.centrum.cz
+mail.chargoon.com
+mail.charlton.greenwich.sch.uk
+mail.charltonschool.com
+mail.chenderit.northants.sch.uk
+mail.childrens.com
+mail.citizensmn.com
+mail.citp.nl
+mail.cm-sobral.pt
+mail.cmalliance.org
+mail.cmpunjab.gov.pk
+mail.colegiodorosario.pt
+mail.collab.uni.edu
+mail.comeup-soft.de
+mail.compuworx.hu
+mail.configura.com
+mail.congreso.gob.hn
+mail.connectivityit.com.au
+mail.cookcountyil.gov
+mail.coopdefrance.coop
+mail.cpnpr.org
+mail.crestron.com
+mail.cssaz.org
+mail.cta.org
+mail.cvd.nl
+mail.cws.biz
+mail.datagroup.de
+mail.dearborncountyhospital.org
+mail.depend.se
+mail.desancta.nl
+mail.dioceseofgreensburg.org
+mail.doe.k12.de.us
+mail.dollardcollege.nl
+mail.dqc-hosting.net
+mail.drivetime.com
+mail.du.ae
+mail.e-farmcredit.com
+mail.eatough.net
+mail.ebsi.com
+mail.edwards-ind.com
+mail.emailonline.net.br
+mail.energy.gov.ab.ca
+mail.escrotrans.com
+mail.exchpro.dk
+mail.expertsystems.net
mail.extranet.hp.com
+mail.ezeit.co.uk
+mail.fachisthers.com
+mail.faf.cuni.cz
+mail.federalequipment.com
+mail.fhconsulting.com.br
+mail.footballaustralia.com.au
+mail.fozzy.ua
+mail.g4s.no
+mail.gallowglass.co.uk
+mail.gama.com.tr
+mail.geninf.com
+mail.ggi-sa.com
+mail.ggs.vic.edu.au
+mail.globeteam.com
+mail.gmrgroup.in
+mail.govwentworth.k12.nh.us
+mail.gpworldwide.com
+mail.grafil.com
+mail.groupegt.ca
+mail.gruppocredem.it
+mail.gruppoveritas.it
mail.gtri.gatech.edu
+mail.guideone.com
+mail.guidewire.com
+mail.guk.org.uk
mail.gunnebo.com
+mail.haderslev-gym.dk
+mail.hallrender.com
+mail.hamptoncollege.org.uk
+mail.harbourmsp.com
+mail.harvestnaperville.org
+mail.havantacademy.co.uk
+mail.hemofarm.com
+mail.hgs.n-yorks.sch.uk
+mail.hib.no
+mail.hoegh.com
mail.hoover.k12.al.us
+mail.horizonsd.org
+mail.houdijk.com
+mail.hsd153.org
+mail.hsventures.org
mail.hzeeland.nl
+mail.iac.com.tw
+mail.icepronav.ro
mail.idera.com
+mail.iimc.kyoto-u.ac.jp
mail.ilsole24ore.com
+mail.indiska.se
+mail.insanity-inc.org
+mail.ipswichschool.net
+mail.isnsolutions.co.uk
+mail.itc.mb.ca
+mail.itc.net.sa
+mail.itcs.com.ge
+mail.iteam.se
+mail.itgsolutions.com
+mail.itility.us
+mail.itu.queensu.ca
+mail.janaf.hr
+mail.jardboranir.is
+mail.jarfalla.se
mail.jetblue.com
+mail.jjuc.no
+mail.jordanhospital.org
+mail.jus.cz
+mail.justinho.com
+mail.kairos-it.com
+mail.karlsson.se
+mail.kces.de
+mail.kerners.com
+mail.kidneyfund.org
+mail.kik.gov.tr
+mail.kingscollegeguildford.com
+mail.kit.ae
+mail.kks.se
+mail.klingenberg.com
+mail.kolektor.com
+mail.kubota-kma.com
+mail.kvanum.com
+mail.labranche.net
+mail.lancercatering.com
+mail.lfhi.com
+mail.lochem.nl
+mail.loreto.nsw.edu.au
+mail.lpbs.org.uk
+mail.mandersconsulting.com
+mail.maristcollege.school.nz
+mail.mariuspedersen.cz
+mail.marnixcollege.nl
+mail.mauser-cabs.at
+mail.mbsds.com
+mail.mbvm.org
+mail.mciblues.net
+mail.mcx.pl
+mail.mcycd.gov.ae
+mail.meau.com
+mail.metito.com
+mail.metrostav.cz
+mail.metrotrains.com.au
+mail.meyernetconsulting.com
+mail.mf.dk
+mail.micronav.co.uk
+mail.midco.net
+mail.middevon.gov.uk
+mail.midental.org
+mail.mihs.org
+mail.milesplatts.co.uk
+mail.minsterlaw.co.uk
+mail.mlhslancers.com
+mail.moe.gov.my
+mail.momatos.com
+mail.moorsidehigh.com
+mail.mosa.gov.qa
+mail.mrcc.aast.edu
+mail.msa-oost.nl
+mail.mulhouse.fr
+mail.mvsd.ca
+mail.mygcx.org
+mail.myrtuemedical.org
+mail.mysterynet.mb.ca
+mail.namwater.com.na
+mail.nap.gsic.titech.ac.jp
+mail.navitasworld.com
+mail.neway.co.il
+mail.nicor.com
+mail.nkadd.org
+mail.nli.no
+mail.normandale.edu
+mail.norsar.no
+mail.notionsolutions.com
+mail.npaid.org
+mail.nty.m86security.com
+mail.oakley.kent.sch.uk
+mail.ocusd.net
mail.officebroker.com
+mail.ofg.lv
mail.oma.nl
+mail.omanair.aero
+mail.optimum.bm
+mail.oshochem.com
+mail.ouc.ac.cy
+mail.paratek.com
+mail.pdb.se
+mail.petranso.com
+mail.petrex.com.pe
+mail.pewsey-vale.wilts.sch.uk
+mail.pflag.org
+mail.pgesco.com
+mail.pinecreeksd.mb.ca
+mail.plainconcepts.com
+mail.plpsd.mb.ca
+mail.pmc-sierra.com
+mail.polycom.co.il
+mail.primevision.net
+mail.prsdmb.ca
+mail.pukzh.ch
+mail.qataridiar.com
+mail.ravenstone.co.uk
mail.rawlinscollege.org.uk
+mail.rca.gov.om
mail.rcsdk12.org
+mail.red-red.ru
+mail.reiv.com.au
+mail.rewar.com.br
+mail.rexel.nl
+mail.ribblesdale.org
+mail.richardhicks.com
+mail.ridgian.co.uk
+mail.rittal.be
+mail.rkbs-de-vlinder.nl
+mail.rmc.com.au
+mail.ruudlighting.com
+mail.sage.com
+mail.saic-dc.com
+mail.sarasamerica.com
+mail.savininsurance.com
+mail.sd206.org
+mail.seekeducation.org
+mail.serralves.pt
+mail.sigtuna.se
mail.silmu.fi
mail.sinclair.edu
mail.skmc.gov.ae
+mail.skov.com
+mail.skp.com
+mail.sli.com
+mail.slt.com.lk
+mail.smart3group.com
+mail.smiddy.co.uk
+mail.softlinesolutions.com.au
+mail.spotlight.co.za
+mail.ssb.eu
+mail.ssi.com.vn
+mail.stadsmissionen.se
+mail.stallionoilfield.com
+mail.stccs.ca
+mail.stcg.net
+mail.steel-line.com.au
+mail.storstockholm.brand.se
+mail.stuwebportal.net
+mail.styletronix.net
+mail.sv-com.de
+mail.svsd.ca
+mail.swmed.edu
+mail.tegola.ru
+mail.texasent.com
+mail.tgn.com
mail.the-ascott.com
+mail.thomassabo.com
+mail.tommoz.co.nz
+mail.townsquaremedia.com
mail.tox-us.com
+mail.transunion.com
+mail.tri-center.k12.ia.us
+mail.tridenttech.edu
+mail.trinco.de
+mail.tunisiana.com
+mail.tvfr.com
+mail.ufonegsm.net
mail.ugs.com
+mail.um.sopot.pl
+mail.umfmpookies.info
+mail.unitil.com
mail.uottawa.ca
+mail.usd450.net
+mail.ustboniface.mb.ca
+mail.uvh.nl
+mail.vakko.com.tr
+mail.valdichienti.net
+mail.vasallen.se
+mail.vejlehs.dk
+mail.versicherungsforen.net
+mail.vertigo.com
+mail.vestconsult.dk
+mail.vicore.se
+mail.viettel.com.vn
+mail.vmkfb.se
+mail.wasbol.nl
+mail.wasserstudios.com
+mail.wbd.ru
+mail.wcc.vic.edu.au
+mail.wellsway.bathnes.sch.uk
+mail.wienholding.at
+mail.wipfli.com
+mail.wsdmi.org
mail.yvc.ac.il
+mail.zoloto585.ru
+mail01.nct.ac.uk
+mail1.asfourcrystal.com
+mail1.sog.ga.gov
mail2.law.stetson.edu
+mail2.lisluanda.com
+mail2.marqnet.com
+mail2.nonlinear.ca
mail2.skanetrafiken.se
+mail3.gibsondunn.com
+mailer.kuehnel-web.org
+mailfilter.bowdoin.edu
mailhub1.cpsb.org
mailhub2.cpsb.org
+maillab.state.nm.us
+mailsrv.angelantoni.it
+mailsrv.artax.cz
+mailstation.ch
+maisoku.co.jp
+mall123.com.tw
+mallorca.co.uk
+manabo.chukyo-u.ac.jp
+manchester.ac.uk
+mandat24.de
+mangawebstore.com
+manifest5.craig-is.com
+manmail.nice.org.uk
+manmaruyoyaku2.jp
+manukinvest.com
+mapmfc.com
+marathonfoto.com
+maringeneral.org
+maritimetacticalsecurity.com
+marketforceshopper.com
+mars.micex.ru
marshallsonline.com
+maruetsu.net
+marymount.qld.edu.au
+massdor.com
massport.com
+matgenie.com
+matmut.fr
+matricis.com
+matsuzakaya.co.jp
+mattel.com
+mayvillestate.edu
+mbanking.ncrwebhost.mobi
+mbdvd.com
+mc0.multimap.com
+mc4me.mccd.edu
+mc4u-ext.mcdonalds.fr
+mch.io
+mchscares.org
+mchvpn01.midcoasthealth.com
+mcostaff.com
+md-whistleblower.com
+meadsd.net
+meagpower.org
+meathvec.ie
+medewerker.jouwregardz.nl
+media.filas.pl
+media.martignetti.com
+media.wschiro.edu
+media3.ignitemedia.com
mediabistro.com
+mediacentershop.be
+mediacentershop.nl
+mediafire.com
+mediamaxonline.com
+mediazp.cz
+medicalcannabismanager.com
+medicalert.co.nz
+mediclinic.co.za
+meinkonto.orf-gis.at
+meltitofftv.com
+member.marmar.com.tw
member.yong-online.com.tw
+memberadviser.com
+members.bsrservices.biz
+memory-express.co.uk
+memoryshop.be
+memoryshop.nl
+memphis.edu
+merchantcart.net
merchantonlineapp.com
+mercyhousing.org
+meriden.nsw.edu.au
+merlin.ca
merrickbank.com
+messaging.macmahon.com.au
metalinq.com
+metrogr.org
+metrostarsystems.com
+mexicancupid.com
+mf-web.d2c.ne.jp
+mg.afimilk.co.il
+mhhitws.cahwnet.gov
+mhric.org
+mhs1.3f.dk
+mhsecure.dmcontact.com
+michelsville.com
+midfloridacardiology.com
+midnightcharm.com
+midwayautosupply.com
+midwestregional.com
miele.co.uk
+migdataengine.cms.hhs.gov
+mightyblasttv.com
+mightyfixit.com
+mightymendittv.com
+mightythirstynow.com
+mightythirstytv.com
+mijnrijnijssel.nl
+milkmandelivers.com
+mill-hillcollege.nl
+milldtrack.com
miller.co.jp
+milsoftssl.com
+mindbusiness.org
+mingorp.hr
+misd.net
mishlohim.co.il
+misim.gov.il
+mitserv.com
+mizuho-int.com
+mizuno.co.jp
+mizuno.jp
+mizunonetorder.com
mizunoshop.net
+mmint.org
+mmrpatientview.com
+mmrpersonalhealthrecords.com
+mnscu.edu
+mobil.alfru.net
+mobile.animate-shop.jp
+mobile.xjt.com
+mobilebankcardservices.co.uk
+mochiads.com
mochibot.com
mochigames.com
mochimedia.com
+mochimedia.net
+mochipass.com
+mod.yodobashi.com
+moe.gov.ae
+mof.go.jp
+mohawkeriesharepoint.com
+molinosmodernos.com
+monash.edu
+monbureau.sophiaconseil.fr
+monreglement.fr
+monserviceconciergerie.com
+montebello.ridgevineyards.net
+montetrader.com
+montiplaza.nl
+montroseaccess.org.au
+mopera.net
+morainevalley.edu
+moralesfamily.net
+moreheadstate.edu
+morganschaffer.net
+mosalira.nl
+moshtix.com
moss.esher.ac.uk
+moss.ise.de
+moundsparkacademy.org
+mp01.canon.jp
+mp3shop.be
+mp3shop.nl
+mrc-ws.mrceweb.com
+mrclaurentides.qc.ca
+mrmrshandycaddy.com
+mrus.co.uk
+msauth.mainstreet.fiserv.net
+msbmyndigheten.se
+mscw.vic.edu.au
msexchange.lyon.edu
+msg.gov.hu
+msimmunology.com
msishopper.net
+msmail.mvnu.edu
+msu.edu
+msvpn.wusm.wustl.edu
+mtimail.metal-technologies.com
+mtnpeaktrail.com
mtsexchange.mtsn.org.uk
+mtvninvoices.com
mudy.info
+mule.co.kr
+musc.edu
+mustangps.org
+mwd.incontech.co.uk
+mwn.de
+mws.acculynk.net
+mx.ahmadiyya.de
+mx.twfp.com
+mxs.at
+mxs.deff.ru
+my-aime.net
+my-hammer.at
+my-hammer.de
+my-office.ro
my.bentley.edu
my.berkeleycollege.edu
+my.bluebunny.com
+my.ccu.edu
+my.colby-sawyer.edu
+my.comprehensivesleep.com
+my.cpscorp.com
+my.dhlglobalmail.com
my.dover.edu
my.ecwid.com
+my.hillsdale.edu
+my.ju.edu
+my.proactiv.com.ph
+my.sandi.net
+my.siematic.de
+my.snhu.edu
+my.tfl.gov.uk
+my.unifiedbrands.net
my.wcupa.edu
+myabakus.net
+myaero.org
+myameda.com
+myapps.skiffmed.com
+mybenetech.com
+mybethanyranchhome.org
+mybfffishfood.com
+mybffnow.com
+mybigcommerce.com
+mybuxtonwallet.com
+mycardprinter.com
+mychart.carilionclinic.org
+myclinicallogic.com
mycls.cls.ch
+mycoldfire.com
+mycollaboration.sug.com
+mycundus.com
+myemail.com.sg
+myemail.sg
+myesafedepositbox.com
+myevolver.com
+myexterran.com
+myfauquierhealth.org
+myfldocs.com
+myfloodonline.com
+myfluvaccine.com
+mygetmighytighty.com
+mygiftregistry.co.za
+myhdwraparoundstv.com
+myholtca.com
+mymail.brueggers.com
+mymail.warnerconnect.com
+mymccc.mc3.edu
+mymcso.com
+mymdc.mo.gov
+mymedicallocker.com
+mymedicalrecordsmd.com
+mynavi.jp
+mynha.com
+mynhatest.com
myoffice.eu.goodyear.com
myoffice.na.goodyear.com
myparceldelivery.com
+myparkbillstv.com
+mypoint.com
+myportal.vhschicago.com
+myr00t.com
+myriad.com
+myriddexpulse.com
+myservices.suffolk.ac.uk
+myshakeweight.com
+mysheridan.shcr.com
+mystarcentral.com
+mystatebillstv.com
+mysteryworldnet.com
+mystorage.cloudleverage.com
+mystudentsquare.com
+mysullystore.com
+mytdriver.com
+mytravelersflood.com
+myvpn.mdavisinc.com
+myvpn.ubc.ca
+mywagnercat.com
+mze.cz
+n-fukushi.ac.jp
na.ntrsupport.com
+naehmaschinen-welt.de
+nagasaki.lg.jp
+namg1.ipsos.com
+nan.kujalleq.gl
+napster.com
naramail.nara.gov
+nas.gov.ua
+nasadvd.com
+nat.tribalddb.net
+natchezcommunityhospital.com
+national-preferred.com
+nationalparkbillstv.com
+nationalsecuritygroup.com
+natlloyds-flood.com
+navicast.jp
+navysealsfund.org
+nbch.com.ar
+nbrc.org
+nbst.org.uk
+nccrimecontrol.org
+ncm-c.org
+ncmpay.com
+ncmstl.com
+ncst.com
+ndcconsultants.co.uk
+ndl.qc.ca
+ndr.nu
+nebraska.gov
+nectarwallet.com
+nelson.azdamiaan.be
neospeech.com
+net4.saga-ja.jp
+netcafe.ft.dk
+netdocuments.com
+netleasing.ersteleasing.hu
+netmail.nmh.org
+netmailing.liderexpress.hr
+netnfu.ne.jp
+netorder.sogo-seibu.co.jp
+netpractice.com.au
+netstorm.no
+nettkirken.no
nettkontoret.kredinor.no
+nettobank.ch
+netview.nu
+network.directrelief.org
+networkrail.rapport-online.com
+nevada.edu
+never-was.com
+new2u.us
neways.com
newaysonline.com
+newcollege.ac.uk
+newmarket.com
+news.nzzexecutive.ch
newvistalive.com
+nexusos.net
+nfipservices.com
+ngenx.net
+nhc.ac.uk
+nhk-ep.com
+nhs.uk
+nhselearning.co.uk
+nhtv.nl
+nicovideo.jp
+niftarlake.nl
+nightingaleconant.co.uk
+nihon-u.ac.jp
+nikkei.co.jp
+niktec.com
+nimbus.peru.edu
+nintex.com
+njreflood.com
+nmsmp.alsok.co.jp
+noc.touchnoc.com
nochex.com
+nomade.etu.univ-nantes.fr
noridian.totalonboarding.com
+nortcoll.ac.uk
+norwich-union.com
+notebookbuffer.com
+notes.parliament.qld.gov.au
noticiastelemicro.com
+notleyhigh.com
+nousinfo.com
+novabase.pt
+novocorreio.ultra.com.br
+nowa.ntelos.com
nr.edu
+nraesafe.com
+nrwbank.com
+ns002.toshiba-sol.co.jp
+ns11mm.sept11mm.org
+nsw.gov.au
+nswmentors.com
+ntdira.com
+ntstaxonline.com
+ntx.at
+nubod.com
+nuii.com
+nuskin.com
+nutropin.com
+nuungolf.com
nuwaveoven.com
+nuwaveovennow.com
+nwhc.ac.uk
+nyvpn.conifersecurities.com
+nzmail.deloitte.co.nz
+nzz.ch
+oasen.nl
+oasiswebvpn.net
+oasystems.co.nz
+obdp.org
+obsmail.com
+ocean.ac-toulouse.fr
+odlmarkets.com
+odlsecurities.com
+offertool.galenos.ch
+office.mls.lib.il.us
+office.occ.on.ca
+office.rooscs.nl
+office.tatemono.com
+office.wacom.de
+officemd.net
+ogdenbancshares.com
+oha.com
+oit.ac.jp
+olchs.org
+ollusa.edu
+olmsted.mn.us
+oma.nl
+omnidualsaw.ca
+on-linepojisteni.cz
+on-nets.com
+one-info.net
+onecoin.tayoreru.com
+onee.se
+onefmcremote.com
+onesies.com.au
+onestop.gsi.go.jp
+oneuso.org
+onforce.com
+online-processingcenter.com
+online.alpha-web.jp
+online.alphabank.com.cy
+online.americanbus.com
+online.clalcredit.co.il
online.eurobank.pl
+online.julbo-rx.com
+online.mycontoso.de
+online.shamir.es
+online.shamir.fr
+online.shamirlens.co.uk
+online.steens.dk
+onlinebanking.bankofalbuquerque.com
+onlinebanking.bankofarizona.com
+onlinebanking.bankofarkansas.com
+onlinebanking.bankofkansascity.com
+onlinebanking.bankofoklahoma.com
+onlinebanking.bankoftexas.com
+onlinebanking.csbt.com
+onlinebill.fl1.li
+onlinebt.de
+onlineclient.nyscorporate.com
+onlinelibrary.wiley.com
+onlineticket.jp
+onmail.dk
+onmyo.com
+ontarioinsco.com
+ontimeweb.itfocus.co.nz
onyxinv.com
+opel-leadengine.de
+openhire.com
+operations.nvmp.nl
+oppassessment.eu.com
+oppenheimerfunds.com
+oppy.com
+opsource.net
+oralchirurgie-ehingen.de
+orchardworld.co.uk
+ordemenfermeiros.pt
+order.fujifilm.com
+order.pvpl.com
+orderdiscoabs.com
+ordermonster1200.com
+orderoxyclinical.com
+orderpacecoach.com
+orderpopmemories.com
+orders.airculinaireinternational.com
+orders.caterlinkworldwide.com
+ordina.nl
+oreckvac.ca
orix-sumai.jp
+orixliving.jp
+osaki-eweb.com
+oscar.gov.au
+oss.schuster-gmbh.de
+osuvpn.okstate.edu
osvinc.com
+otodok.com
otpbank.hu
+otpcafeteria.hu
+otppenztarak.hu
+otsuka-shokai.co.jp
+outdoorchristmaslighting.co.uk
+outlook.belam.lv
+outlook.bolthouse.com
+outlook.bosleyconsulting.com
+outlook.cgw.com.au
+outlook.delichtenvoorde.nl
+outlook.effix.be
+outlook.fritzhansen.net
+outlook.haarlem.nl
+outlook.hfwu.de
+outlook.hillcrest.vic.edu.au
+outlook.it-service-schwadorf.de
+outlook.kennedykrieger.org
+outlook.probil.com.tr
+outlook.t-online.de
+outlook.wcsr.com
+outlook.y-tech.co.il
+outlook1.wilshire.com
+outlookonline.nl
+outlookpremium.com
+outside.cmworks.com
+outspark.com
+overblick.se
+overthedoor.com
+ovo-zaanstad.nl
+owa.aas.ru
+owa.acbl.net
+owa.addon.de
+owa.afridata.net
+owa.asp.ruf.ch
+owa.belnet.de
+owa.bushbros.com
+owa.byui.edu
+owa.cancom.de
+owa.caritas.at
+owa.cimt-ag.de
+owa.cms-hs.com
+owa.consilium-uk.com
+owa.consortioservices.com
+owa.dannenbaum.com
+owa.db-international.de
+owa.dbr.com
+owa.dish.com
owa.dist113.org
+owa.dunnhumby.com
+owa.dyrbergkern.com
+owa.edipresse.ch
+owa.electric-house.com
+owa.eneco.eu
+owa.esn.at
+owa.eucnordvest.dk
+owa.exe.it
+owa.executrain.com
+owa.fh-jena.de
+owa.gfe.com
+owa.gft.com
+owa.gtlaw.com.au
+owa.hcuge.ch
+owa.helsingborg.se
+owa.iadt.ie
+owa.ic3.gov
+owa.isl-automotive.com
+owa.itsindy.com
+owa.iwco.com
+owa.jabirumetals.com.au
+owa.jacksonkelly.com
+owa.jetstar.com
owa.kajak.fi
owa.kan.se
+owa.kromannreumert.com
+owa.kwfdn.org
+owa.lamy-lexel.com
+owa.lfb.fr
+owa.lrgs.org.uk
+owa.mainroads.wa.gov.au
+owa.matrix.co.il
+owa.mdx.ac.uk
+owa.midroc.se
+owa.namfg.com
+owa.narsaq.gl
+owa.nd.edu.au
owa.nordakademie.de
+owa.orangecoastcollege.net
+owa.oranim.ac.il
+owa.otani.ac.jp
+owa.ouc.com
+owa.palama.gov.za
+owa.parlement.nl
+owa.peak-it.nl
+owa.perceptis.com
+owa.pinklotusbreastcenter.com
+owa.prgparking.com
+owa.prinbox.com
+owa.priorsfieldschool.com
+owa.qaqortoq.gl
+owa.qortex.com
+owa.rbs1.com
+owa.rcha.net
+owa.rochesterathleticclub.com
+owa.roeverbroenner.de
+owa.rrpub.com
+owa.rtc-mailing.de
+owa.rtix.com
+owa.sirc.co.il
+owa.sktf.se
+owa.slagelse.dk
+owa.smh.ca
+owa.spservicing.com
+owa.st-benetbiscop.org.uk
owa.tecnicasreunidas.es
+owa.terremark.com
+owa.uni.lu
+owa.uniten.edu.my
+owa.vetmeduni.ac.at
+owa.wdm-ia.com
+owa.westoncolorado.com
+owa.windmobile.ca
+owa.witstor.de
+owa2.earthfare.com
owa2k3.bhw.de
+owamail.calu.edu
+owenscorning.com
+oztravel.com
+p2pia.com
+pagos.uveritas.ac.cr
+pagport.jp
+painel.mtv.com.br
+painel.onlinesol.com.br
+pajamajeans.com
+pamperedchefconsultantcardapplication.com
+pandorahost.net
+paperlessemployee.com
parfumdreams.de
+parkbillstv.com
+parkcity.org
+parking.bristolairport.co.uk
+parrishmed.com
+partille.se
partner.buzzcity.com
+partnerhosted.com
+partners.carnegieam.dk
partners.conocophillipsalaska.com
+partners.org
+partners.sitesense-oo.com
+partners.smartname.com
+pascoregionalmc.com
pastel.co.za
+pastelincheck.co.za
+pasts.lattelecom.lv
+pasts.riga.lv
+pathfinder.woolworths.co.za
+pathrocket.com
+patsiprod.upr.edu
+pay.cimbal.com
+paybacktime.com
+payment.soulultimatenation.com.tw
+payments.abm.com
+paymyassociation.com
+pbhrmc.com
+pc-one.net
+pc-soft.info
+pcpobr.nl
+pct.edu
+pdashop.be
+pdashop.nl
+pdgm.com
+peacecorps.gov
+peaceriverregional.com
+peckham.org
+pedirefills.ca
+pedvd.com
+peelpolice.ca
+penncommons.com
+pent-valley.kent.sch.uk
+perfectbrownie.tv
perfectmoney.com
+perimeter.eiu.edu
+perkinelmergenetics.com
+perse.co.uk
+personalausweisportal.de
+perspectica.telmetrics.com
+perspektive-it.de
+pest.griffsoft.hu
+pestfreetv.com
+petfinder.com
+pethairpicksytv.com
+petshed.com
+pfizerpro.jp
+pgcwl.com
+pgfl.org.uk
+pgi105.pacifica.edu
+ph.book.airbypleasant.com
+phfewic.org
+photomask.com
+phwebvpn.org
+phwebvpn2.org
+physiciansregional.net
picnik.com
+pictureitpostage.com
+pieseautoaccesorii.com
+pim.hypoport.de
pimkie.de
pimkie.es
pimkie.fr
pimkie.it
pineconeresearch.com
+piratenpartei-nrw.de
+pittsborotransportationplan.com
+piwik.healthplan.com
+pixgate.fokus.fraunhofer.de
+pizzutitrac.com
+pl-fax.com
+pl.wikidot.com
+planapps.org
planet-tachyon.com
+plasmacool.ca
+plasmacool.com
+plasmaquebec.com
+platform-one.suffolkone.org
+playlsi.com
playneverwinter.com
+playnextlevel.com
+plusuk01.smartsgroup.com
+pluto.fipotex.com
+plweb.evenflo.com
+pmat3.com
+pmptech.biz
+pobal.ie
pocket.matsui.co.jp
+pocketchair.com
+pocketu.jp
+pocklingtonschool.com
+poczta.adamed.com
+poczta.barlinek.com.pl
+poczta.km-net.pl
+poczta.umwm.pl
+pocztam.pap.pl
+pods.thinkorswim.com
pokervt.com
+polautomatisering.nl
+pooledmoneyinvestmentboard.com
poolzconnect.singaporepools.com.sg
+poplarbluffregional.com
popularglasses.com
portaal.nh1816.nl
+portaal.steenbok.com
+portaal.veenendaal.nl
+portail.bienetrealacarte.com
+portail.croix-rouge.fr
+portail.ensai.fr
+portail.mairie-blagnac.fr
portail.mont-notre-dame.qc.ca
+portal-dynamics.com
+portal.aasa.ac.jp
+portal.algoe-it.nl
+portal.aquon.nl
+portal.asms.sa.edu.au
+portal.bisd.com
+portal.brescia.co.za
+portal.campverde.az.gov
+portal.capital-tour.ru
+portal.cmocpa.com
+portal.coastalrange.ca
+portal.collaborative.com
+portal.colonialsd.org
+portal.core.gb.com
+portal.covenantsolutions.org
+portal.crh-corp.net
+portal.crtx.com
portal.eduweb.vic.gov.au
portal.eiffel.nl
+portal.estridge.net
+portal.flaglerschools.com
+portal.gov.cz
+portal.gses.l-3com.com
+portal.halcyonit.com
+portal.hallco.org
+portal.hc-vlc.nl
+portal.heel.com
portal.hello.ch
+portal.hpisd.org
+portal.hud.de
+portal.human-skills.com
+portal.hutto.txed.net
+portal.ijsselcollege.nl
+portal.klinikum-niederlausitz.de
portal.klz.org.uk
portal.langara.bc.ca
+portal.marchesschool.net
portal.mariestad.se
+portal.maryhare.org.uk
+portal.mez.nl
+portal.mhyork.org
+portal.myabc.no
+portal.netcuras.com
+portal.nordavia.ru
+portal.orlandoheart.com
+portal.pascack.k12.nj.us
portal.peckham.org
portal.perse.co.uk
+portal.riskrighter.com
+portal.s1.com
+portal.sangart.com
+portal.sierrasystems.com
+portal.sigmax.nl
+portal.skbo.nl
+portal.skitsap.wednet.edu
+portal.stjansdal.nl
+portal.svms.net
+portal.tape-llc.com
+portal.telefonbuchverlag-sutter.de
portal.tku.ac.jp
+portal.toreboda.se
+portal.usgjuristen.nl
+portal.yourithost.com
+portal.zeidlerpartnership.com
+portal2.znb.nl
+portale.ervet.it
+portam.jp
+porthuronstclairsharepoint.com
post.norwegian.no
+post.simple.ru
+post.socialrdg.dk
+post.stortinget.no
+post.time.kommune.no
+post.wastecare.co.uk
+posta.copma.it
posta.dsi.gov.tr
+posta.kolektor.si
+posta.nuk.uni-lj.si
+posti.hippos.fi
+posti.pirko.fi
+postkodlotteriet.se
+postur.borgun.is
+postur.hve.is
powerschool.ccsdut.net
+powerschool.com
powerschool.lawrence.k12.ma.us
+powershiftfastcash.com
+powertoolshop.be
+powertoolshop.nl
+pph.peres-center.org
+practika.ru
+pragma-group.biz
+precash.com
+preferredhomecare.com
+preishelden.de
+premierinc.com
+premiodestaque.com
+primehhs.com
+princeportal.com
+princeton.edu
+printershop.be
+printershop.nl
+private.stelizabeth.com
+pro.mothers-auction.net
+procapita.gfbs.se
+procoder.aviacode.com
+proexam.org
profil.centrum.cz
+profilecenter.ru
+profitbuilderenroll.com
+profitweb.afasgroep.nl
projectinsight.cbre.com
+projectserve.disti.com
+promail.ru
+proposalsystem.seic.com
+provident.com
+providentfunding.com
+provider.dchpkids.com
providers.tufts-health.com
+prox-c.com
ps.dvusd.org
ps.glenbard.org
ps.liberty.k12.mo.us
+ps.meridianschools.org
+psiwebmail.com
psyquel.com
+ptcube.de
+ptstaxonline.com
+ptw.qp.com.qa
+public.myfwc.com
+pufferfish.de
+pulmozyme.com
+puripo.jp
+puser.centrum.sk
pushentertainment.com
+pvhs.org
q8car.com
+qbranch.se
+qeliz.ac.uk
+qenos.com
+qenterprises.com
+qeportal.co.uk
+qewebmail.co.uk
qisweb2-verw.uni-hohenheim.de
+qmgs.walsall.sch.uk
+qqweb.jp
+qsquirrel.com
+qt.sat.gob.mx
+quickreg.ci.irvine.ca.us
+quintogest.com
+quon.asia
quotien.onlinebank.com
+qvc.jp
+qvcliquidation.com
+qwazy.net
+r1.techpuls.hr
+r4.musicstationonline.com
+ra.budco.com
+ra.hntb.com
+ra.libertymgt.com
+ra.pega.com
+raasnet.com
+raciborz.edu.pl
+rahorizons.com
+raildata.orr.gov.uk
rainforest-alliance.org
rakuraku-market.com
+rakuten.co.jp
+rampvpn.tessituranetwork.com
+raona.com
+raptiva.com
+rasowa.ramairservices.com
rbc.bridgetrack.com
+rbsiseast.org.uk
rc.kotoha.co.jp
+rcssalem.com
+rcxasa.watson.ibm.com
+rd.rlcdn.com
+rds.ilc.gov.au
+reach-clp-helpdesk.de
+reaktor.no
+realsuperpass1.smartsubs.net
+redbullcontentpool.com
+redhawk.golfcart.com
+region-view.com
+register.daum.net
+register.lynctrial.com
+registration.gov.gg
+regmurcia.com
+rehabcare.com
+rejuvenateautocanada.com
+relaxtrade.com
+releaseyourpotential.net
+rem.clow.net.nz
+remedy.justice.gov.za
+remote.4tw.dk
+remote.aa.net.nz
+remote.aacl.com.au
+remote.ap.asm.com
+remote.bdmtexas.com
+remote.capita.co.uk
+remote.cftc.gov
+remote.clickconsult.com
+remote.clovertowing.com
remote.cushingco.com
+remote.daugherty.com
+remote.dumasmining.com
+remote.fhn.org
+remote.fnh.no
+remote.frog.se
+remote.frontier-si.com
+remote.fumcallen.org
+remote.gndlaw.com
+remote.graduateleverage.com
+remote.hbcs.org
+remote.hillvue.com
+remote.hrjconsulting.com
+remote.hselaw.com
+remote.ilergroup.com
+remote.inshuckch.com
+remote.ipmotion.de
+remote.keyorganics.net
+remote.maybourne.com
+remote.neighborimpact.org
+remote.nexant.com
+remote.nlogic.com
+remote.nmcfd.com
+remote.noyes-hospital.org
+remote.opensolutions.com
+remote.penton.com
+remote.progpl.com
+remote.queens.org
+remote.reefdiver.de
+remote.renouf-family.com
+remote.rttg.co.uk
+remote.sb-groep.nl
+remote.senhoc.com
+remote.sgsep.com.au
+remote.shetland.gov.uk
+remote.slalomdemo.com
+remote.slfa.com
+remote.starofhope.us
+remote.sticares.org
+remote.thechurchofgod.org
+remote.unicorr.com
+remote.unitedspinal.org
+remote.utsystem.edu
+remoteaccess.skaggs.net
+remoteaccess.starkstate.net
+remotecall.jp
+remoteoutlook.webjet.com.au
+remoteportal.nasonhospital.com
+remotingcoders.com
+rencap.com
+reporthawk.com
+reporting.accesshma.com
+reporting.accessrga.com
+reportingportal.com
reprofinance.com
+republiconline.republictt.com
+resalesmart.com
+resealandsave.com
+research.majesticsteel.com
+researchapoptosis.com
+researcharchive.wintec.ac.nz
+researchherpathways.com
+researchvegf.com
+reservations.encorelasvegas.com
+reservations.wynnlasvegas.com
+resource-ctr.com
+ressu.ficora.fi
restaurantwedding.jp
+resurskontoret.se
+retailer.gfkms.com
+retention.nextpage.com
+retina.org
+revlonrunwalk.com
+revonix.com
+rewardgateway.co.uk
+rewardplus.co.uk
+rezitech.net
+rgdata.com.ua
+rgiexchange.net
+rgiimail.com
+rhwebmail.com
+ricoh-usa.com
+riddexcanada.com
+riddexpulse.com
+riddexpulsenow.com
+rightathomehomestay.com
+riksgalden.se
+rileyhosp.com
rio.edu
+risesupport.com
+risk-buster.com
+rismail.rafflesis.com
+ristken.com
+rituxan.com
+riverartsfestmemphis.org
+riveroakshosp.com
+riverviewregional.com
+rk.sjdc.co.jp
rlcdn.com
+rlh-gmuend.at
+rma.sensus.com
rmg.i-grasp.com
+rms.unlv.edu
+rochester.edu
+rockettesdvd.com
+rocmondriaan.net
+rodekruis.nl
+rodino.ro
+rome.faber.co.uk
+rosalie.ciad.ch
rosevalleyindia.com
+rosey.ch
+ross.fs.fed.us
rotaban.ru
+routercenter.be
+routercenter.nl
rozodoniy.com
rpv.fbn.ca
rr.com
+rreporter.nl
+rs.gov.br
+rsasurveys.co.uk
+rsg-nc.rsgsystems.com
+rsmn.reschini.com
+rsmoss.rsmedical.com
+rsracing.com
+rsu.lv
+rt.rtoaster.jp
+rtstr.netbk.co.jp
+rumail.rockefeller.edu
run.auone.jp
runnet.jp
+runraceresults.com
+rush.edu
+ryujus-netsuper.com
+s-immobilien.de
s-yoyaku.city.sagamihara.kanagawa.jp
s-yoyaku.city.urayasu.chiba.jp
+s.ixiaa.com
+s.ncp.imrworldwide.com
+s1defense.com
+saab-leadengine.de
+saas.dynamate.eu
+saas.it-telcom.nl
+saas.nines.nl
safelinkwireless.com
+safestream.com
+safetekusa.com
sail.iwcc.edu
+saintvincenthealth.com
+saksincorporated.com
+salaris.acera-online.nl
+sales.skipark.com
+salvador-dali.org
+sam.lst.se
+sam.sesameworkshop.org
samba.huji.ac.il
samsami2u.wordpress.com
+samsclub.com
samstores.com
+samworthenterpriseacademy.org
+sandalsuperstore.com
+sandingglovestv.com
+sandiskdealpal.com
+sandwellschools.org.uk
+sanpasqualunion.net
+santa-clarita.com
sap.kenexa.com
saratogaschools.org
+sas.com
+satalyst.com
+satis.tcdd.gov.tr
+savpn.sysadm.suny.edu
+sbdc.uga.edu
+sbiapps.sitesell.com
+sbobet.com
+sbr.shooti.jp
+sbsgroupusa.com
+sby.co.il
+scad.edu
+scarboroughcollege.co.uk
+scartreatmentnow.com
+scb.flysas.com
+scca.com
+sch.uk
+schedulemyshot.vaxamerica.com
+schicktech.com
+schoolwebpages.com
+schulstatistik-thueringen.de
+scientia.sk
scottsliquidgold.com
+scu-vpn.scu.edu.au
+sd68.bc.ca
+sdt.tntpost.nl
+sdx-ag.de
+seanet.sbexp.com
search.boox.jp
search.petfinder.com
+secep.net
+secondmarket.com
+secservizi.it
+sectorzero.pt
+secure-access.cne-siar.gov.uk
+secure.3creditreportsinstantly.com
+secure.aceinsurance.com.au
+secure.anzmoneymanager.com
+secure.asce.org
+secure.astepsdiv.com
+secure.atriacom.com
+secure.atv.com
+secure.bybox.com
secure.cambrianc.on.ca
+secure.citizenlink.com
+secure.click2callu.com
secure.court.gov.il
+secure.cst.org
+secure.cygnusresources.com
secure.discountadvances.com
secure.earthclassmail.com
+secure.eastbayfellowship.org
+secure.elcofduval.org
+secure.frenell.com
+secure.globalstar.com
+secure.gway.org
+secure.igliving.com
+secure.keuzenkamp.eu
+secure.makinglifebetter.com
+secure.mbsbillingsolutions.com
+secure.mcpa4you.org
+secure.mdrc.org
+secure.mededcoventry.com
secure.merchantcart.net
+secure.molapo.co.za
+secure.motorcycle.com
+secure.mrcad.co.uk
+secure.my3creditreportsinstantly.com
+secure.mybybox.com
secure.mycashnow.com
+secure.nicoga.jp
secure.nochex.com
+secure.nufactor.com
+secure.passport.mnginteractive.com
+secure.payconnect.net
secure.paydaymax.com
+secure.personalwatercraft.com
+secure.pompvanhetvolk.be
+secure.reboot.ca
+secure.rfi-walmart.com
+secure.rhodesfs.com
+secure.sandhillsregional.com
+secure.sbmonline.com
+secure.sjpharmacal.com
+secure.snowmobile.com
+secure.softwarepursuits.com
+secure.stuartelvish.com
+secure.tempus-rex.com
+secure.vivemejor.com
+secure.www.contracostatimes.com
+secure.www.dailybreeze.com
+secure.www.dailybulletin.com
+secure.www.dailynews.com
secure.www.denverpost.com
+secure.www.la.com
secure.www.mercurynews.com
+secure.www.montereyherald.com
+secure.www.pasadenastarnews.com
+secure.www.presstelegram.com
+secure.www.redlandsdailyfacts.com
+secure.www.santacruzsentinel.com
+secure.www.sbsun.com
+secure.www.sgvtribune.com
+secure.www.siliconvalley.com
secure.www.twincities.com
+secure.www.whittierdailynews.com
+secure.wzhi.net
+secure.your3creditreportsinstantly.com
secure.zeelandnet.nl
secure.zoominfo.com
secureaccess.cacu.com
+secureconnect.shawgrp.com
+secureconnect.uis.edu
+secured.erdbeerli.ch
+securedatacollection.com
securedlogons.humanadental.com
+securefeed.co.uk
+securepayment.newapproachmarketing.co.za
+securetrack.rebatetrack.com
+securevtp.com
+securible.com
+securities.com
+sedgemoor.gov.uk
+seearprewards.com
+sefinenlinea.jalisco.gob.mx
seha.ae
+seibu.jp
+seibubus-gt.jp
+seisentopbin.com
+seizetheday.com
selfcare.rr.com
+selfservice.smartree.com
+selfservice.vsource.com
+semanticweb.com
+sen-farefinder.com
+send.group.com
+senvpnen.senate.gov
+sercel.com
+serifrebates.com
+serv.webhostnr1.com
+server.alsautomotive.com
+serveraccess.practice-it.co.uk
+service.deutschepost.de
+service.hkn.de
+service.itatbusiness.de
+servicebund.com
+servicedesk.geoeye.com
+servicelinkproonline.com
+servicemagic.com
+serviceportal.telekom.at
services.bag-mail.de
+services.canadoil.com
+services.esc-pau.fr
+services.gyc.ac.uk
+servicingconnect.com
+servizi.allianzbank.it
+servizi.atime.it
+sesameconnection.org
+setnlift.com
+sf-vpn01.embark.com
+sfoon.com
+sfsj.se
+sftsrc.com
+sgw.ngxo.trinity.ebay.co.uk
+sgw.ngxo.trinity.ebay.com
+sgw.ngxo.trinity.ebay.it
shakeweight.com
+shakeweight4men.com
+shakeweighttimer.com
+shaklee.com
+shamir.pt
+shamwowca.com
+share.epeerless.com
+sharepoint.centurionmp.com
+sharepoint.convergys.com
+sharepoint.exiis.net
+sharepoint.rosasconstrutores.pt
+sharepoint.smartit.ch
+sharepoint.xformity.com
+sharepointgermany.cinram.com
+sharepointgurus.net
+sharepointiichiprojects.iichi.org
+sharkweekdvd.com
+sharpmail.sharpamericas.com
+shavematetv.com
+shavershop.be
+shavershop.nl
+sheabuild.com
shiki.gr.jp
+shiki.jp
+shinsei.kyoukaikenpo.or.jp
+shochiku-kabu.com
+shop.benningtonmuseum.org
+shop.fatboy.co.uk
+shop.fatboy.com
+shop.fatboy.de
+shop.fatboy.fr
+shop.fatboy.nl
+shop.foxxfoe.com
+shop.ftv.com.tw
+shop.kgcheck.com.tw
+shop.lindora.com
+shop.rcn.com
+shop.whatsinyourcity.net
+shop123.com.tw
+shop4.vcomshop.com
+shopbase.finetunes.net
+shopnchekshopper.ca
+shopnchekshopper.com
+shopoutdoornebraska.ne.gov
+shoptotalpillow.com
+shortinsights.com
+shortside.com
showcase-tv.com
+shr.ro
+shsmail.swedish.org
shsremote.solarishs.org
+shutdown.cfs.iupui.edu
sierranevada.com
+sigmakudos.com
+signup.cloudprofile.com
+sildelaget.no
+silkcloudservices.microfocus.com
+silkroad.com
+silverjoes.com
+simonizfixittv.com
+simonlyshop.nl
+simplewebmanagement.com
+sims.tanfieldschool.co.uk
+sinergiefinancial.net
+singtel.com
+sip.ttcg.net
+siriusxmrewards.com
+sis.ais-r.edu.sa
sis.ggusd.us
+sis.gpc.edu
sisense.com
+sistema.giannetti.com.br
+sjomannskirken.no
+sjpremote.com
+sjsualumninetwork.com
+skills.luovi.fi
+skivehs.dk
+sklep.vitapertutti.com
+skmm.gov.my
+skogforsk.se
+skyliner.ec.keisei.co.jp
+slg.schools.nottscc.gov.uk
+slinkprovider.com
+slowemdownbowl.com
smart.otpbanka.hr
+smartdrv.com
+smartmoptv.com
+smartphoneshop.be
+smartphoneshop.nl
+smes.org
+smoothawaysite.com
+smtp.ikic.co.jp
+smtp.ngatawa.school.nz
+snuggie.ca
+snuggiefordogs.com
+snuggieforkids.com
+snuggietv.com
+snuggievarsity.com
sobexinvest.com
socketstore.co.uk
+socrambanque.fr
+sodexhovpn.com
+sodexovpn.com
+softsupercoolertv.com
+sog.nl
+sogo-gogo.com
+sols.org
+solutionsbiz.com
+solvethatdebt.com
+son.stellatravel.com.au
+sonicwall.com
+sonymusicd2c.com
+soquij.qc.ca
soundvision.com
+southernwine.com
+southlakecarroll.edu
+sp.cti-w.com
+sp.edu.sg
+sp.hanoverva.gov
+sp.se
+sp1.zvw.uni-goettingen.de
spalding.edu
+sparinvest.dk
+sparkasse.de
+sparrapid.se
+speedy2k3.viglen.co.uk
+speedyspark.com
+spilldaddy.com
+spkgroup.com
+spkhome.net
+spknet.com
+splogin.se
+sports-nakama.com
+sportundshop.de
+spragueenergy.com
+springer-sbm.com
+springhillregional.net
+springisd.org
+sprint.com
+sprint.net
sprintrebates.com
+sprooms.swiss.com
+spss-asp.com
squareup.com
+sr-owa.walter.net.au
+sra.com
+src.sk.ca
+srigold.com
+srmcfl.com
ss3.e-state.co.jp
+ssl-vpn.multifa.com
+ssl-vpn1.aau.dk
ssl.arcsoft.com
+ssl.clinique-pasteur.com
+ssl.coig.pl
+ssl.cpmc.columbia.edu
+ssl.ksd.ch
+ssl.levinglobal.com
+ssl.siih5962.fr
+ssl.walsworth.com
+ssl.weniger-verbrauch.de
+ssl.whoajack.com
+ssl2.americanprogressaction.org
+ssl3.costar.com
+sslclient.runshaw.ac.uk
+sslgw.emis-electrics.de
+sslvpn.accent.nl
+sslvpn.bentonpud.org
sslvpn.broadcom.com
+sslvpn.curtin.edu.au
+sslvpn.emerson.com
+sslvpn.mid.org
+sslvpn.nyp.org
+sslvpn.roedl.pl
sslvpn.savannah.chatham.k12.ga.us
+sslvpn.thrivent.com
+sso.agglo-royan.fr
+sso.collegeboard.com
+sso.utilityservice.com
+st.ig.com.au
+stadspoort.asp4all.nl
+staff.ftc.health-partners.org
+staff1.f-i-f.co.uk
staffmail.brighton.ac.uk
+staffmail.ja.net
+staffordschools.org
staffportal.bne.catholic.edu.au
+stage.sparksecure.com
stapleseasyrebates.com
+stapleseasyway.com
+start.spro.no
startnextweek.com.au
+startrack.gfkrt.com
startrekonline.com
+starwoodresidenceclub.com
+starwoodvacationownership.com
+state.fl.us
+state.ks.us
+state.wy.us
+static.brandsclub.com.br
+static.collegeprowler.com
+static.gebrauchtwagen.de
+static.limewirestore.com
+statistik.msb.se
+statlerhotel.cornell.edu
+stc.ac.uk
+stcloudregional.com
ste-exch1.nhc.ac.uk
+steeleye.com
+steelhorsecomputers.com
+stemcellskintherapytv.com
+stetson.edu
+stichtingwillemvanoranje.nl
+stihl.de
+stilltracking.com
+stlawrencecollege.ca
+stleonards.vic.edu.au
+stlogic.com
+stofzuigerstore.be
+stofzuigerstore.nl
+stone-ware.com
+stoneware.cloverdale.k12.in.us
+store.homeheartbeat.com
+store.sun.com
+store.toto-dream.com
stores.channeladvisor.com
+stories.citi.com
+stormgenius.com
+stpats.vic.edu.au
+straitservice.com
+strapperfect.com
+strapperfect.tv
+stratfordhigh.org.uk
strideeveryday.com
+strijkijzerstore.be
+strijkijzerstore.nl
+stringfellowmemorial.com
studentdata.warwick.ac.uk
+studentinfo.trinityhigh.com
+studmagic.com
studynet.dem.hva.nl
+stylio.jp
subjectivemetrics.com
+sug-spirit.net
+suitespot.mynextsuite.com
+summitmedicalcenter.net
+summitshack.com
+summitstrategies.com
+sundahus.se
+sunriseearthdvd.com
+superhub.hk
+support.ataretail.com
+support.bsc-ideas.com
+support.cryptas.com
+support.dridefault.com
+support.goshen.bluestarpro.com
+support.landsteinar.nl
+support.mcigb.com
+support.orgmanager.de
+support.rosebudtech.com
+supportlink.net
survey5.spss-asp.com
surveys.itsyourview.com
suvana.com
+svc.aegmis.de
svelvik.skole.d-ikt.no
+sw.nvusd.k12.ca.us
+sw.quirinale.it
+sw4men.com
+sw4menespanol.com
+swartdev.net
+sweden.icw.se
+sweettracking.com
+swiss-rx-login.ch
+switch2verizonfios.com
+swivelwonderhanger.com
+swuhealth.org
+sykehuspartner.no
syllabus.doshisha.ac.jp
+symetra.com
+synergy.nma-ict.nl
+synergy.workarea.nl
sys.ins-uni.co.jp
+syspro.com
+system.cord.osaka-geidai.ac.jp
+systemb2b.com
+t-mobile.nl
+taerobicsdvds.com
+tahomasd.us
+tai.com.tr
+tamiflu.com
+tandenborstelstore.be
+tandenborstelstore.nl
taocan777.com
+tapapp.com
+tarceva.com
+tas-japan.com
+tasgroup.cl
+tasmanliquor.co.nz
+tasmantest.sdc-online.net
+tastiwave.ca
+tastiwave.com
+tastiwavepan.com
+tatertornadotv.com
+taxport.convey.com
+taxslayer.com
+taxslayerbooks.com
+taxslayerpro.com
+taxstatusnow.com
+taxtes.com
+tc4men.com
+tco.cfbt-inspections.com
+tcspost.thomassen.com
+tdj.ac.jp
+teachingpersonnel.com
+teambrandon.ca
+tecdlr.com
+technology-security-associates.com
+technologyandstrategy.com
+techscaler.com
+tecplot.com
teetimesusa.com
+teetroit.com
+telaris.wlu.ca
+telefoonshop.nl
+teleplan.no
+telifhaklari.gov.tr
+tellabs.com
+temptationscanada.com
terrabanking.romexterra.ro
+testdrivereward.com
testdriveunlimited2.com
+tewkesburyschool.org
+tge.cl
tgn.co.jp
tgw.com
+the-house.com
+the-k-factor.com
+theadspot.tv
+thealabamacollegesnuggie.com
+thealbany.biz
+thebarkoff.com
+thecarletonsheetscoachnetwork.com
+thecharacter-classics.com
thecinema.in
+thecomfortfurnace.com
thediamondstore.co.uk
+thedownsschool.org
+theezstringer.com
+thefushigi.com
+theglobalfund.org
+thegreenspider.com
+thehandyvalet.com
+thehexlightsite.com
+theknowledgeexchange.info
+themicrowallet.com
+themightysuperstore.com
+theorphan.com
+thepalmwallet.com
+thepancakepuff.com
+therockradionetwork.secure.myhosting.net
+thesecuraoven.com
+theshedd.org
+thesource.freemanco.com
+thesuperjuicer.com
+thetotalcore.com
+thewire.wynnresorts.com
thor.movistar.com.co
+threepalms.com
+threescompany.com
+thueringen.de
+thuis.ckxs.com
+thw.de
thymes.com
+thymesnet.com
+ticket-web-shochiku.com
+ticket.fast.no
+ticketfly.com
+tickets.carowinds.com
+tickets.dorneypark.com
+tickets.spoorwegmuseum.nl
+tickets.valleyfair.com
+tickets.worldsoffun.com
+tidytweet.com
+tieup.demae-can.com
+tightboards.com
+tigmail.tigdistributing.com
+time.staffme.net
+timken.com
+timtrac.ca
+tirerebatestatus.com
+tis.co.jp
+tis.jp
+tixforkids.org
+tjmaxx.com
+tku.ac.jp
tlfw01.fhsg.ch
+tmgowa.pointsharp.net
+tmsanalytics.com
+tmsnervecenter.com
+tnkase.com
+tohmatsu.co.jp
+toho-u.ac.jp
+tokem.fi
+token.vpn.mim.dk
+tokyo.jp
+toltestworld.com
+tomategigantetv.com
+tomwatsondvdtv.com
+tondeusestore.be
+tondeusestore.nl
tools.med.nyu.edu
+topearnmoney.com
topfox.co.uk
+toppenishhospital.com
+topsytomatotree.com
+topsytree.com
+topsytreetv.com
+toptvstuff.com
+toranoana.jp
+toranomon-ichiba.com
+tosti-asia.com
totalcore.com
+touchnbrush.tv
+toutatice.fr
+tpmail.transplace.com
tracs.txstate.edu
+tradecollege.com.au
+traderssupersummit.com
+trans-cosmos.co.jp
+transat.com
+transmontaigne.com
+transportationtomorrow.on.ca
+travelersflood.com
+travelerssaves.com
+travelindochina.co.nz
+travelindochina.co.uk
+travelindochina.com
+travelindochina.com.au
+travelmoneynow.com
+trebesin.cz
+trendsource.com
trialpay.com
+tribune.com
+tricarsales.com
+tritium.ch
+trusted.com
+tryabcircle.com
+tryabrocket.com
+tryabrocket.tv
+tryabrocketflexmaster.com
+trycrunchlessabs.com
+tryeasyfeet.com
+tryeasyreach.com
+tryeyemagic.com
+tryfastfit.com
+tryfreegrillglovetv.com
+tryfreerejuvenate.com
+trygianttomato.com
+tryhealthinitiative.com
+trymybffnow.com
+trymytomatofactory.com
+trypetmd.com
tryshakeweight.com
+tryshakeweightespanol.com
+trysidesleeperpro.com
+tryslimmersilhouette.com
+tryslimtsnow.com
+trytomatofactorynow.com
trytotalpillow.com
+ts.cadritech.com.br
+ts.k14.net
+ts.transsoft.dk
+tsn.dataresolution.net
+tss-j.co.jp
+tsubuyaki.fx.dmm.com
+tsuweb.pilgrimsoftware.com
+tu-chemnitz.de
+tu-dortmund.de
+tuev-nord.de
+tufts-health.com
+tui.rewardgateway.ie
+tulane.wisenbaker.com
+tum.de
+tunnel.ltu.edu
+tunnel.services.wisc.edu
+tutornet.com.br
+tuvakademie.it
+tuwien.ac.at
tvspy.com
tw.event.gamania.com
+twinriversregional.com
+twoa.ac.nz
+twyford.ealing.sch.uk
+twynhamschool.com
+tx.maxim-ic.com
+tylerisd.org
+u-tokyo.ac.jp
+uab.edu
+uatoa.americanexpress.com
+ube-ind.co.jp
+ubi.pt
+ucf.edu
+uci.edu
+uckac.edu
ucol.ac.nz
+ucr.edu
+ucsd.edu
+udsis.com
+uemail.unitedelec.com
+ufl.edu
+ugyfelkapu.mindigtvextra.hu
+uhk.cz
+uillinois.edu
ukblelite01.emea.aza-lite.com
ukblelite02.emea.aza-lite.com
+ukwebmail.markit.com
+ultrapos.net
+umea.se
+umons.ac.be
+umpcshop.nl
+umsamofund.com
+umweltbundesamt.at
+umweltrat.de
+un.org
+unc.edu
+uncg.edu
+undercovermags.com
+uni-career.jp
+uni-hamburg.de
uni-hohenheim.de
+unibas.ch
+unifymoffice.com
+unionvpn.union.edu
+unisanta.br
+unitron.no
+univ-lyon1.fr
+universalfloodpr.com
+universitymedicalcenter.com
+unixnotes.wordpress.com
+unlimity.biz
+uno.edu
+unr.edu
+unv.org
+uottawa.ca
+update.com
+upenn.edu
+upgradeserver.coremobility.com
+upstatecarolina.net
+urclickthru.com
+urlinkthru.com
+uruanna.com
+us.connect.newegg.net
+us17action.com
+us36managedlanetrafficandrevenue.com
+usa800.net
+usacapitol.com
+usc.edu
+uscg.gov
+user.atlas.sk
user.centrum.cz
+userapp.waubonsee.edu
+usfinancialsource.com
usuwazavpn04.americas.aza-lite.com
+uta.edu
+utah.gov
+uws.edu
+v-da-001.dp-itsolutions.de
+va.gov
+vaderstad.com
+valenciaport.com
+valtech.se
+vanfcog.org
+vangent.com
+vasttrafik.se
+vaxjo.se
+vbgov.com
+vci.de
+vcommerce.com
vcsportal.viasyscs.com
+vdvexchange.com
+veluwsescholengroepcvo.nl
+ven.softec.sk
+veniceregional.com
+venners.co.uk
+verifiering.se
+verint.com
+versicherungsvergleich.payback.de
+verticalresponse.com
+vervoerzcn.nl
+verwaltung-innovativ.de
+vestedanet.com
+vestedapartners.com
+vetsfirstchoice.com
+vfwsturgis.org
+vhspoint.lt
+vi.macromill.com
+viacord.com
+vic33.win.kennesaw.edu
+video.actadvantage.org
+videocamerashop.be
+videocamerashop.nl
+villeesch.lu
+virtualexchange.nl
+virtuall.nl
+visualvault.com
+vitalberry.eu
+vivaldi.ru
+vivid-trade.com
+vivus.se
vle.guilsborough.northants.sch.uk
+vle.marling.gloucs.sch.uk
+vle.saddleworthschool.org
+vocalocity.com
+vodamail.hu
+voicerecordershop.be
+voicerecordershop.nl
voogd.com
+vosdemarches.saintgermainenlaye.fr
+vpdn.dlr.de
vpn-01.houstonisd.org
vpn-03.houstonisd.org
vpn-04.houstonisd.org
+vpn-ap2.infor.com
+vpn-gw1.unbc.ca
+vpn-indy.exacttarget.com
+vpn-server.rrzn.uni-hannover.de
+vpn-stud-ssl.hogent.be
+vpn-testbetrieb.rus.uni-stuttgart.de
+vpn-us-ssl.lionbridge.com
+vpn-wv.mentorg.com
+vpn.4j.lane.edu
+vpn.agnesirwin.org
+vpn.ahss.org
+vpn.anl.gov
+vpn.ats.edu
+vpn.ausrad.com
+vpn.barry.edu
+vpn.bchydro.com
+vpn.bonitahealthcenter.com
+vpn.caltech.edu
+vpn.cclswi.com
+vpn.challenger.wa.edu.au
+vpn.claas.com
+vpn.cmu.edu
+vpn.coasolutions.com
+vpn.coffey.com.au
+vpn.concur.com
+vpn.dearborn.pcgcampbell.com
+vpn.del-valle.k12.tx.us
+vpn.diebold.com
+vpn.doncaster.gov.uk
+vpn.douglasesd.k12.or.us
+vpn.ehu.es
+vpn.eurecom.fr
+vpn.fhi-berlin.mpg.de
+vpn.gribskov.dk
+vpn.gsorad.com
+vpn.hbstubbs.com
+vpn.hobokenumc.com
+vpn.hppartners.com
+vpn.ins-lua.com
+vpn.interseco.nl
+vpn.iridium.com
+vpn.kleinandhoffman.com
+vpn.kmcnetwork.org
+vpn.l3stratis.com
+vpn.lafayette.edu
+vpn.lan.kth.se
+vpn.liberty.edu
+vpn.libertyregional.org
+vpn.llproducts.eu
+vpn.lrdc.com
+vpn.mcgrathnicol.com
+vpn.memorialsb.org
+vpn.mercer.edu
+vpn.minecofin.gov.rw
+vpn.mobilearmor.com
+vpn.msmc.la.edu
+vpn.nbeavers.com
+vpn.netprivateer.com
+vpn.newpaltz.edu
+vpn.pace.edu
+vpn.pasadenaisd.org
+vpn.pih.net
+vpn.pxi.com
+vpn.redbarchetta.com
+vpn.reliablesprinkler.com
+vpn.reykjavik.is
+vpn.rmc.ca
+vpn.rz.tu-clausthal.de
+vpn.sausd.us
+vpn.stadsdeel-osdorp.nl
+vpn.stb.eu
vpn.tarumanagara.com
+vpn.tesd.net
+vpn.tfh-wildau.de
+vpn.ud-medien.ch
+vpn.uiowa.edu
+vpn.uni-giessen.de
+vpn.univ-lr.fr
+vpn.unizar.es
+vpn.uoguelph.ca
+vpn.uow.edu.au
+vpn.utexas.edu
+vpn.uwhealth.org
+vpn.virteva.com
+vpn.wrij.nl
+vpn01.us-support.com
+vpn02.nucomm.net
+vpn1.dot.state.ga.us
+vpn1.prvlimburg.nl
+vpn1.sandyspringbank.com
+vpn1.security-finance.com
+vpn2.bakbone.com
+vpn2.qualys.com
+vpnaccess.sales-service.com
+vpngate.tu-bs.de
+vpngate.uni-koeln.de
+vpngw.uni-wuerzburg.de
+vpnssl.nwths.biz
+vpnuk.oup.com
vr.is
+vresp.com
+vrg.se
+vserver.de
+vtc.edu.hk
vtrade.vincomsc.com.vn
+vucvejle.dk
+vyvxinview.com
+vzw.getyourscores.com
+wa.gov
+wa.infrontsports.com
+waffenamt.it
+wakeside.com
+walbeekgroep.com
+walmartfaces.com
+walmarthowwedoit.com
+walmartstores.com
+walsallcollege.ac.uk
warranty.akeryards.as
+warwick.ac.uk
+was.org
+wastis-eu.st.com
+wcupa.edu
+wcvpn.wartburg.edu
+wdpartnersonline.com
web-opas.osakaya.co.jp
+web-pl.daikin.co.jp
+web-vpn.hefr.ch
+web.rbc.com
+web.storen.ch
+web.uc.atosorigin.com
+web.vpn.finanzit.net
+web01.de.amadee.net
webaccess.7p-group.com
+webaccess.atkearney.com
webaccess.pvhs.org
+webapp.dpd.nl
+webapp.meredith.com
+webapps.hudsonisd.org
+webbdaf.com
+webbmail.ssg.se
webbt.banque-tahiti.pf
+webcenc.com
+webchat.unt.edu
+webcomputer.nl
+webdagbog.kvuc.dk
+webdirect.jp
+webenroll.accesstpa.com
webforensics.co.uk
+webgate.no
+webinfra.nl
+webmail.5sqc.com
+webmail.aap.com.au
+webmail.accentonline.com
+webmail.action-inter.com
+webmail.administaff.com
+webmail.aguiabranca.com.br
+webmail.ahs.ae
+webmail.ak-normal.school.nz
+webmail.akd.nl
+webmail.akl.whk.co.nz
+webmail.albertadoctors.org
+webmail.alere.co.uk
+webmail.alexmann.com
+webmail.alturkigroup.net
+webmail.ampvisualtv.tv
+webmail.anacom.pt
+webmail.apotex.ca
+webmail.arbella.com
+webmail.aritzia.com
+webmail.arthurterry.bham.sch.uk
webmail.asb.dk
+webmail.asparis.fr
+webmail.assembly.ab.ca
+webmail.attendshealthcare.com
+webmail.audencia.com
webmail.austmus.gov.au
+webmail.aventus.nl
+webmail.awsg.at
+webmail.azmedien.ch
+webmail.barnet.ac.uk
+webmail.bayamonpr.org
+webmail.bg.fnv.nl
+webmail.bggs.qld.edu.au
+webmail.bie.edu
+webmail.bife.ie
+webmail.bluepointsolutions.com
webmail.bne.catholic.edu.au
webmail.bose.com
+webmail.bravilor.com
+webmail.bridgercapital.com
+webmail.brigantine.atlnet.org
+webmail.brinkgroep.nl
+webmail.bwfc.co.uk
+webmail.c-e.com
+webmail.capacent.is
+webmail.cardonald.ac.uk
+webmail.carmelcollegesalland.nl
+webmail.casgen.com
+webmail.cavanvec.ie
+webmail.cet.ac.il
+webmail.cg68.fr
+webmail.chmca.org
webmail.choa.org
+webmail.cineplex.com
+webmail.citationair.com
+webmail.cityofvancouver.us
+webmail.cmslegal.at
+webmail.corenet.se
+webmail.corptax.com
+webmail.cosmopolitanlasvegas.com
+webmail.crchealth.com
+webmail.creuna.com
+webmail.croklaan.com
+webmail.crow.nl
webmail.csaa.com
+webmail.dabs.com
+webmail.davenportdiocese.org
+webmail.debaak.nl
+webmail.deckers.com
+webmail.dibrosi.be
+webmail.dongemondcollege.nl
+webmail.donlen.com
+webmail.dpsg.com
+webmail.dwango.co.jp
+webmail.e-boticario.com.br
+webmail.ea.aku.edu
+webmail.ecerdc.com.my
+webmail.ecosystem.ca
+webmail.edinburghacademy.org.uk
+webmail.edita.se
+webmail.ekero.se
+webmail.emmahuis.nl
+webmail.energimidt.dk
+webmail.energyfutureholdings.com
+webmail.enex-om.com.br
+webmail.engevix.com.br
+webmail.escortinc.com
+webmail.etch.com
+webmail.euroatlantic.pt
+webmail.excanto.com
+webmail.fdm.dk
+webmail.ferroeste.com.br
+webmail.finning.co.uk
webmail.firstam.net
+webmail.flydubai.com
+webmail.francetv.fr
+webmail.frederikshavn.dk
+webmail.furuboda.se
+webmail.gazprom-mt.com
+webmail.gebalis.pt
+webmail.genphysics.com
+webmail.globalcloudservices.nl
+webmail.gmh.edu
+webmail.gorinchem.nl
+webmail.guido.nl
+webmail.haaga-helia.fi
+webmail.hanno.dk
+webmail.henrico.k12.va.us
+webmail.hostedoutlook.be
+webmail.howerter.org
webmail.hrblock.com
+webmail.icare.nl
+webmail.icr-inc.net
+webmail.ikno.nl
webmail.ingbank.com.tr
+webmail.insight-onsite.us
+webmail.integrationsfonds.at
+webmail.interwetten.com
+webmail.intrinsec.com
+webmail.ipzs.it
+webmail.iqhs.nl
+webmail.irdeto.com
+webmail.isolve.co.za
+webmail.ithaca.edu
+webmail.ivoclarvivadent.com
+webmail.javelindirect.com
+webmail.jbc.nl
+webmail.jmp.co.uk
+webmail.jungfrau.ch
webmail.kapsch.net
+webmail.kentalis.nl
+webmail.keuda.fi
+webmail.kinder-stad.nl
+webmail.knauf.fr
+webmail.knighttrans.com
+webmail.knvb.nl
+webmail.komatsuforest.com
+webmail.ku.edu.tr
+webmail.lancashire.bm
+webmail.lappia.fi
+webmail.larkinhoffman.com
+webmail.lett.dk
+webmail.levillage1.be
webmail.levinglobal.com
+webmail.loginlogistica.com.br
webmail.lolland.dk
+webmail.macsstores.com
+webmail.mahouse.gov
+webmail.malvik.kommune.no
+webmail.manheim.com
+webmail.manpower.ch
+webmail.mansion.com
+webmail.marketing-asiapac.com
+webmail.mcbdds.org
+webmail.mdc.wa.edu.au
+webmail.meca.se
+webmail.med.uni-muenchen.de
+webmail.medic911.com
+webmail.menai.ac.uk
+webmail.metalor.com
+webmail.mioc.hr
+webmail.mjncomputers.co.uk
+webmail.modal.com.br
+webmail.moeller.org
+webmail.mof.gov.ae
+webmail.moh.gov.sa
+webmail.mondigroup.com
+webmail.mondipackaging.com
+webmail.monroecounty-fl.gov
+webmail.montessoricollege.nl
+webmail.monumentalsports.com
webmail.mopera.net
+webmail.morphosys.com
+webmail.mr-daten.de
webmail.mt.gov
+webmail.mutter.se
+webmail.myeasyoffice.nl
+webmail.myfloridahouse.gov
+webmail.mystructured.com
+webmail.netdesign.dk
+webmail.nettrust.ch
webmail.newlook.net
+webmail.nilu.no
+webmail.nobel.nl
+webmail.noelgroup.com
+webmail.nordoc.no
+webmail.normik.dk
+webmail.nyfors.dk
+webmail.odin-groep.nl
+webmail.oecd.org
+webmail.oem.dk
+webmail.oensmurer.dk
+webmail.offmadisonave.com
+webmail.orbitone.se
webmail.ordina.nl
+webmail.ormiston.qld.edu.au
+webmail.parametrix.com
+webmail.pdtit.be
+webmail.peacehealth.org
webmail.peelpolice.ca
+webmail.pinellascounty.org
+webmail.plenarygroup.com
+webmail.proag.com
+webmail.psd.pt
+webmail.pu-kumamoto.ac.jp
+webmail.qinvest.com
+webmail.quest.com
+webmail.raiffeisenevolution.com
+webmail.randaberg.kommune.no
+webmail.rasmussen.edu
+webmail.realtors.org
+webmail.rebild.dk
+webmail.reesmanley.com
+webmail.regentcomm.com
+webmail.renn4.nl
+webmail.rgomiddelharnis.nl
+webmail.rietlanden.nl
+webmail.rijnijssel.nl
+webmail.rodenstock.com
+webmail.roe.ac.uk
+webmail.rollins.edu
+webmail.rta.ae
+webmail.rtg.at
+webmail.rtl.hr
+webmail.rtp.pt
+webmail.saintjohn.ca
+webmail.sanoma-magazines.be
+webmail.sbl.ch
+webmail.schuleherisau.ch
+webmail.seaservers.net
+webmail.seha.ae
+webmail.semtribe.com
+webmail.shepleybulfinch.com
+webmail.sicl.co.uk
+webmail.skanderborg.dk
+webmail.skilled.com.au
+webmail.skm.gov.my
+webmail.skogu.nl
+webmail.sma.de
+webmail.socu.dk
+webmail.sotog.nl
+webmail.span.hr
webmail.springer-sbm.com
+webmail.sprm.gov.my
webmail.srhs.com
+webmail.stavanger.kommune.no
+webmail.struttandparker.com
+webmail.stsmd.dk
+webmail.stura.uni-halle.de
+webmail.swafnet.com
+webmail.swietelsky.com
+webmail.sysco.com
+webmail.t-atrium.nl
+webmail.t-systems.dk
+webmail.t26.dk
+webmail.taarnby.dk
+webmail.teaterskolen.dk
+webmail.techcampus.org
+webmail.tecnalia.com
+webmail.teknowlogic.com
+webmail.tfmc.co.za
+webmail.tisq.nl
webmail.toho-u.ac.jp
+webmail.torshavn.fo
+webmail.touricoholidays.com
webmail.transat.com
webmail.tribune.com
webmail.tuev-nord.de
+webmail.tv1.com.br
+webmail.tys.fi
+webmail.uatlantica.pt
+webmail.uc4.com
+webmail.unifiedvalve.com
+webmail.unikom.se
+webmail.unilu.ch
+webmail.univ-catholyon.fr
+webmail.unl.pt
+webmail.usek.edu.lb
+webmail.users.co.uk
webmail.valamar.com
+webmail.varnesregion.no
+webmail.veghel.nl
+webmail.vennesla.kommune.no
+webmail.verkinderen.com
+webmail.viridisit.com
+webmail.vu.nl
+webmail.washsports.com
webmail.waterman-group.co.uk
+webmail.wc.com
webmail.wcupa.edu
+webmail.whitireia.ac.nz
+webmail.windstream.net
+webmail.witc.edu
+webmail.wpod.net
+webmail.wtamu.edu
+webmail.wuerth-phoenix.com
+webmail.wuerth.at
+webmail.ymcamke.org
+webmail0.gifu-net.ed.jp
+webmail1.finansforbundet.dk
+webmail1.gmrmarketing.com
+webmail1.go2uti.com
+webmail2.ems-t.com
+webmail2.factset.com
webmaildata.rr.com
+webmaileu.elcoteq.com
+webmailwg.datacom.co.nz
+webnet.cscdgr.on.ca
+webos.bonsallusd.com
+webportal.bmw.nl
+webportal.simacict.nl
+webportal2.cfisd.net
+webprod4.hc-sc.gc.ca
+webremote.grainger.com
+webservicescitoyens.com
webshop.weijntjes.nl
+websis.unimedcuiaba.com.br
+websupport.f5.com
+webvpn.aamc.org
webvpn.au.aecom.com
webvpn.ben.edu
+webvpn.botsford.org
+webvpn.brmchealthcare.com
+webvpn.coe.int
+webvpn.colfaxcorp.com
+webvpn.dm-drogeriemarkt.com
+webvpn.doherty.co.uk
+webvpn.dpsk12.org
+webvpn.egyptianlng.com
+webvpn.eso.org
webvpn.eu.aecom.com
+webvpn.evraz.com
+webvpn.globant.com
+webvpn.greywolfcapital.com
+webvpn.ieua.org
+webvpn.jccc.edu
+webvpn.lexmed.com
+webvpn.more.net
+webvpn.ned.org
+webvpn.oceanspray.com
+webvpn.orionhealth.com
+webvpn.progress-energy.com
+webvpn.promon.com.br
+webvpn.purdue.edu
+webvpn.roosevelt.edu
+webvpn.rz.tu-harburg.de
+webvpn.scf.cc
+webvpn.sebh.org
+webvpn.steaknshake.com
+webvpn.thegoodguys.com.au
+webvpn.trademe.co.nz
+webvpn.uni-leipzig.de
webvpn.usaa.com
webvpn.usps.gov
+webvpn.vcu.edu
+webvpn.wesleyan.edu
+wecc.biz
+wein7.de
+wellspan.org
welltrix.com
+welly.sm
werecoverdata.com
+wessexlearning.org.uk
+west.skofirm.com
+westbuckland.devon.sch.uk
+westcon.no
wettstar.de
+wha-asa5520.wilmingtonhealth.com
+whataburgerfranchisees.com
+whataburgervendors.com
+whataburgerventures.com
+whatwouldmillionairedo.com
+wheelingil.gov
+whitworth.edu
+wholesale.starfinancial.com
+whoosh.hk
+whrsd.org
+widgetbox.com
+wiki.ngmoco.com
+wiki.tradeext.com
+wikipat.com
+williamsonmemorial.net
+winahome4you.com
+winebow.com
+winxnet.com
+wish.org
+wizardfinance.net
+wm.valley.ne.jp
+wms01.wimaxforum.org
+wnp.waseda.jp
+womanshospitalms.com
+woodiesdiy.com
+woodlynde.org
+wordandbrown.com
workhere.jetblue.com
+world-direct.at
+worldatwardvds.com
+worldwaronecolor.com
+wortech.ac.uk
+worthington-portal.org
wowbeez.com
+wrpinfo.org
ws.licenzji-vetturi.gov.mt
+wsaaudit.com
+wsasr520study.com
+wsbe.org.uk
+wsl.ch
+wsu.edu
+wt.gfi-informatik.de
wtc.lxr.com
+wtoutlook.wellcome.ac.uk
+ww3.metroymca.org
+www-new.epc-business.com
+www-sys2.tax.state.oh.us
www.accessgeneral.com
www.accessingram.com
www.adfox.cz
@@ -654,21 +5046,71 @@ www.zenfolio.com
www.zenryonetwork.com
www.zoominfo.com
www1.cat365.net
+www1.hop.ana.co.jp
www1.ticket-web-shochiku.com
www2.fakton.nl
+www2.hokepon.com
+www2.kenkyosai.or.jp
+www2.lcmcisd.org
www2.proexam.org
www2.secom-techno.co.jp
+www2.tagmulimta.co.il
+www2.tel-aviv.gov.il
www2.ticket-web-shochiku.com
+www2.webfactory-world.de
+www3.bs-j.co.jp
+www3.inferencedata.com
+www3.myfloridacounty.com
+www3.tv-tokyo.co.jp
www6.hsmv.state.fl.us
wwws.jp-bank.japanpost.jp
+wwwssl.isd109.org
+wwwx.oaklandcc.edu
wwy01.shiki.gr.jp
wynbilling.wyndhamworldwide.com
+wyndhamworldwide.com
wynnmacau.recruitmax.com
+wza.nl
+wzanet.nl
xbox.redeemer.ab.ca
+xchanging.com
+xchg.int.t-mobile.at
+xfinityhomesecurity.com
+xmlic.payfuse.com
+xmlrpc4.mollom.com
+xnet.woodforest.com
+xolair.com
+xolairhcp.com
+xpansions.com
+xs4all.nl
+xsightrewards.com
+xtiva.net
+xtremecardioonline.com
+yahoo-vi.co.jp
+yakimaregional.com
+yaskawa.co.jp
+yayoi-kk.co.jp
+yes123.com.tw
+ymca.net
yodlee.com
+yourownshoppingcart.com
+yourperfectweightloss.com
yourwirelessrebatecenter.com
yoyaku.city.funabashi.chiba.jp
yoyaku.city.hachioji.tokyo.jp
+yoyaku.koto-sports.net
+yoyaku.nasva.go.jp
+yoyaku.parksweb.net
+yuyu.medicarelife.com
+zain.com
zenfolio.com
+zenryonetwork.com
+zgraggen.homeserver.com
+zinio.com
+zis.ch
+zivildienst.de
+zoomienation.usafa.org
zoominfo.com
+zooomeee.com
+zuidwester.org
zumbafitness.com
diff --git a/net/base/ssl_false_start_blacklist_process.cc b/net/base/ssl_false_start_blacklist_process.cc
index 46b99af..634df6a 100644
--- a/net/base/ssl_false_start_blacklist_process.cc
+++ b/net/base/ssl_false_start_blacklist_process.cc
@@ -19,6 +19,8 @@ using net::SSLFalseStartBlacklist;
static const unsigned kBuckets = SSLFalseStartBlacklist::kBuckets;
+static bool verbose = false;
+
static int
usage(const char* argv0) {
fprintf(stderr, "Usage: %s <blacklist file> <output .c file>\n", argv0);
@@ -48,7 +50,8 @@ static void RemoveDuplicateEntries(std::vector<std::string>* hosts) {
for (std::vector<std::string>::const_iterator
i = hosts->begin(); i != hosts->end(); i++) {
if (hosts_set.count(*i)) {
- fprintf(stderr, "Removing duplicate entry for %s\n", i->c_str());
+ if (verbose)
+ fprintf(stderr, "Removing duplicate entry for %s\n", i->c_str());
continue;
}
hosts_set.insert(*i);
@@ -93,7 +96,8 @@ static void RemoveRedundantEntries(std::vector<std::string>* hosts) {
if (parent.empty()) {
ret.push_back(*i);
} else {
- fprintf(stderr, "Removing %s as redundant\n", i->c_str());
+ if (verbose)
+ fprintf(stderr, "Removing %s as redundant\n", i->c_str());
}
}
@@ -124,7 +128,7 @@ int main(int argc, char** argv) {
const char* input_file = argv[1];
const char* output_file = argv[2];
- FILE* input = fopen(input_file, "r");
+ FILE* input = fopen(input_file, "rb");
if (!input) {
perror("open");
return usage(argv[0]);
@@ -143,11 +147,16 @@ int main(int argc, char** argv) {
}
char* buffer = static_cast<char*>(malloc(input_size));
- if (fread(buffer, input_size, 1, input) != 1) {
- perror("fread");
- free(buffer);
- fclose(input);
- return 1;
+ long done = 0;
+ while (done < input_size) {
+ size_t n = fread(buffer + done, 1, input_size - done, input);
+ if (n == 0) {
+ perror("fread");
+ free(buffer);
+ fclose(input);
+ return 1;
+ }
+ done += n;
}
fclose(input);
@@ -158,8 +167,12 @@ int main(int argc, char** argv) {
bool non_whitespace_seen = false;
for (long i = 0; i <= input_size; i++) {
if (i == input_size || buffer[i] == '\n') {
- if (!is_comment && non_whitespace_seen)
- hosts.push_back(std::string(&buffer[line_start], i - line_start));
+ if (!is_comment && non_whitespace_seen) {
+ long len = i - line_start;
+ if (i > 0 && buffer[i-1] == '\r')
+ len--;
+ hosts.push_back(std::string(&buffer[line_start], len));
+ }
is_comment = false;
non_whitespace_seen = false;
line_start = i + 1;
@@ -168,7 +181,7 @@ int main(int argc, char** argv) {
if (i == line_start && buffer[i] == '#')
is_comment = true;
- if (buffer[i] != ' ' && buffer[i] != '\t')
+ if (buffer[i] != ' ' && buffer[i] != '\t' && buffer[i] != '\r')
non_whitespace_seen = true;
}
free(buffer);
@@ -185,7 +198,7 @@ int main(int argc, char** argv) {
}
fprintf(stderr, "Using %d entry hash table\n", kBuckets);
- uint16 table[kBuckets];
+ uint32 table[kBuckets];
std::vector<std::string> buckets[kBuckets];
for (std::vector<std::string>::const_iterator
@@ -199,11 +212,6 @@ int main(int argc, char** argv) {
std::string table_data;
unsigned max_bucket_size = 0;
for (unsigned i = 0; i < kBuckets; i++) {
- if (table_data.size() > 65535) {
- fprintf(stderr, "Hash table overflowed a uint16_t index\n");
- return 3;
- }
-
if (buckets[i].size() > max_bucket_size)
max_bucket_size = buckets[i].size();
@@ -231,31 +239,24 @@ int main(int argc, char** argv) {
fprintf(out, "#include \"base/basictypes.h\"\n\n");
fprintf(out, "#include \"net/base/ssl_false_start_blacklist.h\"\n\n");
fprintf(out, "namespace net {\n\n");
- fprintf(out, "const uint16 SSLFalseStartBlacklist::kHashTable[%d + 1] = {\n",
+ fprintf(out, "const uint32 SSLFalseStartBlacklist::kHashTable[%d + 1] = {\n",
kBuckets);
for (unsigned i = 0; i < kBuckets; i++) {
- fprintf(out, " %d,\n", (int) table[i]);
+ fprintf(out, " %u,\n", (unsigned) table[i]);
}
- fprintf(out, " %d,\n", (int) table_data.size());
+ fprintf(out, " %u,\n", (unsigned) table_data.size());
fprintf(out, "};\n\n");
- fprintf(out, "const char SSLFalseStartBlacklist::kHashData[] = \n");
+ fprintf(out, "const char SSLFalseStartBlacklist::kHashData[] = {\n");
for (unsigned i = 0, line_length = 0; i < table_data.size(); i++) {
if (line_length == 0)
- fprintf(out, " \"");
+ fprintf(out, " ");
uint8 c = static_cast<uint8>(table_data[i]);
- if (c < 32 || c > 127 || c == '"') {
- fprintf(out, "\\%c%c%c", '0' + ((c >> 6) & 7), '0' + ((c >> 3) & 7),
- '0' + (c & 7));
- line_length += 4;
- } else {
- fprintf(out, "%c", c);
- line_length++;
- }
+ line_length += fprintf(out, "%d, ", c);
if (i == table_data.size() - 1) {
- fprintf(out, "\";\n");
+ fprintf(out, "\n};\n");
} else if (line_length >= 70) {
- fprintf(out, "\"\n");
+ fprintf(out, "\n");
line_length = 0;
}
}
diff --git a/net/base/ssl_info.h b/net/base/ssl_info.h
index 1786b58..4c68f06 100644
--- a/net/base/ssl_info.h
+++ b/net/base/ssl_info.h
@@ -42,9 +42,8 @@ class SSLInfo {
int security_bits;
// Information about the SSL connection itself. See
- // ssl_connection_status_flags.h for values. The ciphersuite and compression
- // in use are encoded within.
- // TODO(agl): also encode the protocol version used.
+ // ssl_connection_status_flags.h for values. The protocol version,
+ // ciphersuite, and compression in use are encoded within.
int connection_status;
};
diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc
index a0d2794..3014e21 100644
--- a/net/base/transport_security_state.cc
+++ b/net/base/transport_security_state.cc
@@ -142,7 +142,9 @@ bool TransportSecurityState::ParseHeader(const std::string& value,
case AFTER_MAX_AGE_EQUALS:
if (IsAsciiWhitespace(*tokenizer.token_begin()))
continue;
- if (!base::StringToInt(tokenizer.token(), &max_age_candidate))
+ if (!base::StringToInt(tokenizer.token_begin(),
+ tokenizer.token_end(),
+ &max_age_candidate))
return false;
if (max_age_candidate < 0)
return false;
@@ -408,6 +410,7 @@ bool TransportSecurityState::IsPreloadedSTS(
{12, true, "\006jottit\003com"},
{19, true, "\015sunshinepress\003org"},
{21, false, "\003www\013noisebridge\003net"},
+ {10, false, "\004neg9\003org"},
};
static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc
index c4a173c..2a06501 100644
--- a/net/base/transport_security_state_unittest.cc
+++ b/net/base/transport_security_state_unittest.cc
@@ -342,6 +342,9 @@ TEST_F(TransportSecurityStateTest, Preloaded) {
EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "www.noisebridge.net"));
EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "noisebridge.net"));
EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "foo.noisebridge.net"));
+
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "neg9.org"));
+ EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "www.neg9.org"));
}
TEST_F(TransportSecurityStateTest, LongNames) {
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc
index e21a3bc..7bbce5c 100644
--- a/net/base/x509_certificate.cc
+++ b/net/base/x509_certificate.cc
@@ -153,6 +153,46 @@ X509Certificate* X509Certificate::CreateFromHandle(
return cert;
}
+#if defined(OS_WIN)
+static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
+ X509Certificate::OSCertHandle cert_handle = NULL;
+ BOOL ok = CertAddEncodedCertificateToStore(
+ X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(),
+ CERT_STORE_ADD_USE_EXISTING, &cert_handle);
+ return ok ? cert_handle : NULL;
+}
+#else
+static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
+ return X509Certificate::CreateOSCertHandleFromBytes(
+ const_cast<char*>(der_cert.data()), der_cert.size());
+}
+#endif
+
+// static
+X509Certificate* X509Certificate::CreateFromDERCertChain(
+ const std::vector<base::StringPiece>& der_certs) {
+ if (der_certs.size() == 0)
+ return NULL;
+
+ X509Certificate::OSCertHandles intermediate_ca_certs;
+ for (size_t i = 1; i < der_certs.size(); i++) {
+ OSCertHandle handle = CreateOSCert(der_certs[i]);
+ DCHECK(handle);
+ intermediate_ca_certs.push_back(handle);
+ }
+
+ OSCertHandle handle = CreateOSCert(der_certs[0]);
+ DCHECK(handle);
+ X509Certificate* cert =
+ CreateFromHandle(handle, SOURCE_FROM_NETWORK, intermediate_ca_certs);
+ FreeOSCertHandle(handle);
+ for (size_t i = 0; i < intermediate_ca_certs.size(); i++)
+ FreeOSCertHandle(intermediate_ca_certs[i]);
+
+ return cert;
+}
+
// static
X509Certificate* X509Certificate::CreateFromBytes(const char* data,
int length) {
@@ -249,11 +289,9 @@ X509Certificate::X509Certificate(OSCertHandle cert_handle,
const OSCertHandles& intermediates)
: cert_handle_(DupOSCertHandle(cert_handle)),
source_(source) {
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_OPENSSL)
// Copy/retain the intermediate cert handles.
for (size_t i = 0; i < intermediates.size(); ++i)
intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i]));
-#endif
// Platform-specific initialization.
Initialize();
}
@@ -276,10 +314,8 @@ X509Certificate::~X509Certificate() {
X509Certificate::Cache::GetInstance()->Remove(this);
if (cert_handle_)
FreeOSCertHandle(cert_handle_);
-#if defined(OS_MACOSX) || defined(OS_WIN)
for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
FreeOSCertHandle(intermediate_ca_certs_[i]);
-#endif
}
bool X509Certificate::HasExpired() const {
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index 577de92..68762e4 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -13,6 +13,7 @@
#include "base/gtest_prod_util.h"
#include "base/ref_counted.h"
+#include "base/string_piece.h"
#include "base/time.h"
#include "net/base/x509_cert_types.h"
@@ -107,12 +108,20 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// certificate cache prefers the handle from the network because our HTTP
// cache isn't caching the corresponding intermediate CA certificates yet
// (http://crbug.com/7065).
- // The list of intermediate certificates is ignored under NSS (i.e. Linux.)
// The returned pointer must be stored in a scoped_refptr<X509Certificate>.
static X509Certificate* CreateFromHandle(OSCertHandle cert_handle,
Source source,
const OSCertHandles& intermediates);
+ // Create an X509Certificate from a chain of DER encoded certificates. The
+ // first certificate in the chain is the end-entity certificate to which a
+ // handle is returned. The other certificates in the chain are intermediate
+ // certificates. See the comment for |CreateFromHandle| about the |source|
+ // argument.
+ // The returned pointer must be stored in a scoped_refptr<X509Certificate>.
+ static X509Certificate* CreateFromDERCertChain(
+ const std::vector<base::StringPiece>& der_certs);
+
// Create an X509Certificate from the DER-encoded representation.
// Returns NULL on failure.
//
@@ -173,14 +182,12 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// now.
bool HasExpired() const;
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_OPENSSL)
// Returns intermediate certificates added via AddIntermediateCertificate().
// Ownership follows the "get" rule: it is the caller's responsibility to
// retain the elements of the result.
const OSCertHandles& GetIntermediateCertificates() const {
return intermediate_ca_certs_;
}
-#endif
// Returns true if I already contain the given intermediate cert.
bool HasIntermediateCertificate(OSCertHandle cert);
@@ -213,6 +220,17 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
CFArrayRef CreateClientCertificateChain() const;
#endif
+#if defined(OS_WIN)
+ // Returns a handle to a global, in-memory certificate store. We use it for
+ // two purposes:
+ // 1. Import server certificates into this store so that we can verify and
+ // display the certificates using CryptoAPI.
+ // 2. Copy client certificates from the "MY" system certificate store into
+ // this store so that we can close the system store when we finish
+ // searching for client certificates.
+ static HCERTSTORE cert_store();
+#endif
+
// Verifies the certificate against the given hostname. Returns OK if
// successful or an error code upon failure.
//
@@ -268,6 +286,10 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// Common object initialization code. Called by the constructors only.
void Initialize();
+#if defined(OS_WIN)
+ bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
+ const char* policy_oid) const;
+#endif
bool VerifyEV() const;
// Calculates the SHA-1 fingerprint of the certificate. Returns an empty
@@ -292,11 +314,9 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// A handle to the certificate object in the underlying crypto library.
OSCertHandle cert_handle_;
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_OPENSSL)
// Untrusted intermediate certificates associated with this certificate
- // that may be needed for chain building. (NSS impl does not need these.)
+ // that may be needed for chain building.
OSCertHandles intermediate_ca_certs_;
-#endif
#if defined(OS_MACOSX)
// Blocks multiple threads from verifying the cert simultaneously.
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index 05fbe63..a2a0eea 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -694,6 +694,7 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
// Determine the certificate's EV status using SecTrustCopyExtendedResult(),
// which we need to look up because the function wasn't added until
// Mac OS X 10.5.7.
+ // Note: "ExtendedResult" means extended validation results.
CFBundleRef bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
if (bundle) {
@@ -872,10 +873,10 @@ bool X509Certificate::IsIssuedBy(
for (int i = 0; i < n; ++i) {
SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>(
const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle(
cert_handle,
X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
for (unsigned j = 0; j < valid_issuers.size(); j++) {
if (cert->issuer().Matches(valid_issuers[j]))
return true;
diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc
index 668fd5f..a9ad39c 100644
--- a/net/base/x509_certificate_openssl.cc
+++ b/net/base/x509_certificate_openssl.cc
@@ -20,9 +20,12 @@
#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
#include "net/base/openssl_util.h"
+#include "net/base/x509_openssl_util.h"
namespace net {
+namespace nxou = net::x509_openssl_util;
+
namespace {
void CreateOSCertHandlesFromPKCS7Bytes(
@@ -51,39 +54,13 @@ void CreateOSCertHandlesFromPKCS7Bytes(
}
}
-bool ParsePrincipalFieldInternal(X509_NAME* name,
- int index,
- std::string* field) {
- ASN1_STRING* data =
- X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
- if (!data)
- return false;
-
- unsigned char* buf = NULL;
- int len = ASN1_STRING_to_UTF8(&buf, data);
- if (len <= 0)
- return false;
-
- field->assign(reinterpret_cast<const char*>(buf), len);
- OPENSSL_free(buf);
- return true;
-}
-
-void ParsePrincipalField(X509_NAME* name, int nid, std::string* field) {
- int index = X509_NAME_get_index_by_NID(name, nid, -1);
- if (index < 0)
- return;
-
- ParsePrincipalFieldInternal(name, index, field);
-}
-
-void ParsePrincipalFields(X509_NAME* name,
+void ParsePrincipalValues(X509_NAME* name,
int nid,
std::vector<std::string>* fields) {
for (int index = -1;
(index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
std::string field;
- if (!ParsePrincipalFieldInternal(name, index, &field))
+ if (!nxou::ParsePrincipalValueByIndex(name, index, &field))
break;
fields->push_back(field);
}
@@ -95,58 +72,23 @@ void ParsePrincipal(X509Certificate::OSCertHandle cert,
if (!x509_name)
return;
- ParsePrincipalFields(x509_name, NID_streetAddress,
+ ParsePrincipalValues(x509_name, NID_streetAddress,
&principal->street_addresses);
- ParsePrincipalFields(x509_name, NID_organizationName,
+ ParsePrincipalValues(x509_name, NID_organizationName,
&principal->organization_names);
- ParsePrincipalFields(x509_name, NID_organizationalUnitName,
+ ParsePrincipalValues(x509_name, NID_organizationalUnitName,
&principal->organization_unit_names);
- ParsePrincipalFields(x509_name, NID_domainComponent,
+ ParsePrincipalValues(x509_name, NID_domainComponent,
&principal->domain_components);
- ParsePrincipalField(x509_name, NID_commonName, &principal->common_name);
- ParsePrincipalField(x509_name, NID_localityName, &principal->locality_name);
- ParsePrincipalField(x509_name, NID_stateOrProvinceName,
- &principal->state_or_province_name);
- ParsePrincipalField(x509_name, NID_countryName, &principal->country_name);
-}
-
-void ParseDate(ASN1_TIME* x509_time, base::Time* time) {
- if (!x509_time ||
- (x509_time->type != V_ASN1_UTCTIME &&
- x509_time->type != V_ASN1_GENERALIZEDTIME))
- return;
-
- std::string str_date(reinterpret_cast<char*>(x509_time->data),
- x509_time->length);
- // UTCTime: YYMMDDHHMMSSZ
- // GeneralizedTime: YYYYMMDDHHMMSSZ
- size_t year_length = x509_time->type == V_ASN1_UTCTIME ? 2 : 4;
- size_t fields_offset = x509_time->type == V_ASN1_UTCTIME ? 0 : 2;
-
- if (str_date.length() < 11 + year_length)
- return;
-
- base::Time::Exploded exploded = {0};
- bool valid = base::StringToInt(str_date.substr(0, year_length),
- &exploded.year);
- if (valid && year_length == 2)
- exploded.year += exploded.year < 50 ? 2000 : 1900;
-
- valid &= base::StringToInt(str_date.substr(2 + fields_offset, 2),
- &exploded.month);
- valid &= base::StringToInt(str_date.substr(4 + fields_offset, 2),
- &exploded.day_of_month);
- valid &= base::StringToInt(str_date.substr(6 + fields_offset, 2),
- &exploded.hour);
- valid &= base::StringToInt(str_date.substr(8 + fields_offset, 2),
- &exploded.minute);
- valid &= base::StringToInt(str_date.substr(10 + fields_offset, 2),
- &exploded.second);
-
- DCHECK(valid);
-
- *time = base::Time::FromUTCExploded(exploded);
+ nxou::ParsePrincipalValueByNID(x509_name, NID_commonName,
+ &principal->common_name);
+ nxou::ParsePrincipalValueByNID(x509_name, NID_localityName,
+ &principal->locality_name);
+ nxou::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
+ &principal->state_or_province_name);
+ nxou::ParsePrincipalValueByNID(x509_name, NID_countryName,
+ &principal->country_name);
}
void ParseSubjectAltNames(X509Certificate::OSCertHandle cert,
@@ -351,8 +293,8 @@ void X509Certificate::Initialize() {
fingerprint_ = CalculateFingerprint(cert_handle_);
ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_);
ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_);
- ParseDate(X509_get_notBefore(cert_handle_), &valid_start_);
- ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
+ nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_);
+ nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
}
SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index 9bb81cb..31173e4 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -252,9 +252,9 @@ void CheckGoogleCert(const scoped_refptr<X509Certificate>& google_cert,
}
TEST(X509CertificateTest, GoogleCertParsing) {
- scoped_refptr<X509Certificate> google_cert =
+ scoped_refptr<X509Certificate> google_cert(
X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ reinterpret_cast<const char*>(google_der), sizeof(google_der)));
CheckGoogleCert(google_cert, google_fingerprint,
1238192407, // Mar 27 22:20:07 2009 GMT
@@ -262,8 +262,8 @@ TEST(X509CertificateTest, GoogleCertParsing) {
}
TEST(X509CertificateTest, WebkitCertParsing) {
- scoped_refptr<X509Certificate> webkit_cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
+ scoped_refptr<X509Certificate> webkit_cert(X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
ASSERT_NE(static_cast<X509Certificate*>(NULL), webkit_cert);
@@ -318,8 +318,8 @@ TEST(X509CertificateTest, WebkitCertParsing) {
}
TEST(X509CertificateTest, ThawteCertParsing) {
- scoped_refptr<X509Certificate> thawte_cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
+ scoped_refptr<X509Certificate> thawte_cert(X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)));
ASSERT_NE(static_cast<X509Certificate*>(NULL), thawte_cert);
@@ -379,10 +379,10 @@ TEST(X509CertificateTest, ThawteCertParsing) {
}
TEST(X509CertificateTest, PaypalNullCertParsing) {
- scoped_refptr<X509Certificate> paypal_null_cert =
+ scoped_refptr<X509Certificate> paypal_null_cert(
X509Certificate::CreateFromBytes(
reinterpret_cast<const char*>(paypal_null_der),
- sizeof(paypal_null_der));
+ sizeof(paypal_null_der)));
ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert);
@@ -409,8 +409,8 @@ TEST(X509CertificateTest, PaypalNullCertParsing) {
// This certificate will expire on 2011-09-08.
TEST(X509CertificateTest, UnoSoftCertParsing) {
FilePath certs_dir = GetTestCertsDirectory();
- scoped_refptr<X509Certificate> unosoft_hu_cert =
- ImportCertFromFile(certs_dir, "unosoft_hu_cert.der");
+ scoped_refptr<X509Certificate> unosoft_hu_cert(
+ ImportCertFromFile(certs_dir, "unosoft_hu_cert.der"));
ASSERT_NE(static_cast<X509Certificate*>(NULL), unosoft_hu_cert);
@@ -481,18 +481,18 @@ TEST(X509CertificateTest, Cache) {
// certificate cache.
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
- scoped_refptr<X509Certificate> cert1 = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert1(X509Certificate::CreateFromHandle(
google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
X509Certificate::FreeOSCertHandle(google_cert_handle);
// Add a certificate from the same source (SOURCE_LONE_CERT_IMPORT). This
// should return the cached certificate (cert1).
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
- scoped_refptr<X509Certificate> cert2 = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert2(X509Certificate::CreateFromHandle(
google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
X509Certificate::FreeOSCertHandle(google_cert_handle);
EXPECT_EQ(cert1, cert2);
@@ -501,9 +501,9 @@ TEST(X509CertificateTest, Cache) {
// cached certificate (cert1) and return a new certificate.
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
- scoped_refptr<X509Certificate> cert3 = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert3(X509Certificate::CreateFromHandle(
google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
X509Certificate::FreeOSCertHandle(google_cert_handle);
EXPECT_NE(cert1, cert3);
@@ -512,43 +512,43 @@ TEST(X509CertificateTest, Cache) {
// certificate (cert3).
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
- scoped_refptr<X509Certificate> cert4 = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert4(X509Certificate::CreateFromHandle(
google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
X509Certificate::FreeOSCertHandle(google_cert_handle);
EXPECT_EQ(cert3, cert4);
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
- scoped_refptr<X509Certificate> cert5 = X509Certificate::CreateFromHandle(
+ scoped_refptr<X509Certificate> cert5(X509Certificate::CreateFromHandle(
google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ X509Certificate::OSCertHandles()));
X509Certificate::FreeOSCertHandle(google_cert_handle);
EXPECT_EQ(cert3, cert5);
}
TEST(X509CertificateTest, Pickle) {
- scoped_refptr<X509Certificate> cert1 = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ scoped_refptr<X509Certificate> cert1(X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(google_der), sizeof(google_der)));
Pickle pickle;
cert1->Persist(&pickle);
void* iter = NULL;
- scoped_refptr<X509Certificate> cert2 =
- X509Certificate::CreateFromPickle(pickle, &iter);
+ scoped_refptr<X509Certificate> cert2(
+ X509Certificate::CreateFromPickle(pickle, &iter));
EXPECT_EQ(cert1, cert2);
}
TEST(X509CertificateTest, Policy) {
- scoped_refptr<X509Certificate> google_cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ scoped_refptr<X509Certificate> google_cert(X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(google_der), sizeof(google_der)));
- scoped_refptr<X509Certificate> webkit_cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
+ scoped_refptr<X509Certificate> webkit_cert(X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
CertPolicy policy;
@@ -581,18 +581,18 @@ TEST(X509CertificateTest, Policy) {
#if defined(OS_MACOSX) || defined(OS_WIN)
TEST(X509CertificateTest, IntermediateCertificates) {
- scoped_refptr<X509Certificate> webkit_cert =
+ scoped_refptr<X509Certificate> webkit_cert(
X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
+ reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
- scoped_refptr<X509Certificate> thawte_cert =
+ scoped_refptr<X509Certificate> thawte_cert(
X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
+ reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)));
- scoped_refptr<X509Certificate> paypal_cert =
+ scoped_refptr<X509Certificate> paypal_cert(
X509Certificate::CreateFromBytes(
reinterpret_cast<const char*>(paypal_null_der),
- sizeof(paypal_null_der));
+ sizeof(paypal_null_der)));
X509Certificate::OSCertHandle google_handle;
// Create object with no intermediates:
@@ -645,8 +645,8 @@ TEST(X509CertificateTest, IsIssuedBy) {
FilePath certs_dir = GetTestCertsDirectory();
// Test a client certificate from MIT.
- scoped_refptr<X509Certificate> mit_davidben_cert =
- ImportCertFromFile(certs_dir, "mit.davidben.der");
+ scoped_refptr<X509Certificate> mit_davidben_cert(
+ ImportCertFromFile(certs_dir, "mit.davidben.der"));
ASSERT_NE(static_cast<X509Certificate*>(NULL), mit_davidben_cert);
CertPrincipal mit_issuer;
@@ -662,8 +662,8 @@ TEST(X509CertificateTest, IsIssuedBy) {
EXPECT_TRUE(mit_davidben_cert->IsIssuedBy(mit_issuers));
// Test a client certificate from FOAF.ME.
- scoped_refptr<X509Certificate> foaf_me_chromium_test_cert =
- ImportCertFromFile(certs_dir, "foaf.me.chromium-test-cert.der");
+ scoped_refptr<X509Certificate> foaf_me_chromium_test_cert(
+ ImportCertFromFile(certs_dir, "foaf.me.chromium-test-cert.der"));
ASSERT_NE(static_cast<X509Certificate*>(NULL), foaf_me_chromium_test_cert);
CertPrincipal foaf_issuer;
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index 380ff3c..9e018fd 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -291,48 +291,6 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
}
}
-///////////////////////////////////////////////////////////////////////////
-//
-// Functions used by X509Certificate::IsEV
-//
-///////////////////////////////////////////////////////////////////////////
-
-// Constructs a certificate chain starting from the end certificate
-// 'cert_context', matching any of the certificate policies.
-//
-// Returns the certificate chain context on success, or NULL on failure.
-// The caller is responsible for freeing the certificate chain context with
-// CertFreeCertificateChain.
-PCCERT_CHAIN_CONTEXT ConstructCertChain(
- PCCERT_CONTEXT cert_context,
- const char* const* policies,
- int num_policies) {
- CERT_CHAIN_PARA chain_para;
- memset(&chain_para, 0, sizeof(chain_para));
- chain_para.cbSize = sizeof(chain_para);
- chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
- chain_para.RequestedUsage.Usage.cUsageIdentifier = 0;
- chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR*
- chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_OR;
- chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = num_policies;
- chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
- const_cast<char**>(policies);
- PCCERT_CHAIN_CONTEXT chain_context;
- if (!CertGetCertificateChain(
- NULL, // default chain engine, HCCE_CURRENT_USER
- cert_context,
- NULL, // current system time
- cert_context->hCertStore, // search this store
- &chain_para,
- CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT |
- CERT_CHAIN_CACHE_END_CERT,
- NULL, // reserved
- &chain_context)) {
- return NULL;
- }
- return chain_context;
-}
-
// Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
// structure and stores it in *output.
void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
@@ -362,18 +320,6 @@ void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
output->reset(policies_info);
}
-// Returns true if the policy is in the array of CERT_POLICY_INFO in
-// the CERT_POLICIES_INFO structure.
-bool ContainsPolicy(const CERT_POLICIES_INFO* policies_info,
- const char* policy) {
- int num_policies = policies_info->cPolicyInfo;
- for (int i = 0; i < num_policies; i++) {
- if (!strcmp(policies_info->rgPolicyInfo[i].pszPolicyIdentifier, policy))
- return true;
- }
- return false;
-}
-
// Helper function to parse a principal from a WinInet description of that
// principal.
void ParsePrincipal(const std::string& description,
@@ -575,6 +521,33 @@ void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
dns_names->push_back(subject_.common_name);
}
+class GlobalCertStore {
+ public:
+ HCERTSTORE cert_store() {
+ return cert_store_;
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<GlobalCertStore>;
+
+ GlobalCertStore()
+ : cert_store_(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) {
+ }
+
+ ~GlobalCertStore() {
+ CertCloseStore(cert_store_, 0 /* flags */);
+ }
+
+ const HCERTSTORE cert_store_;
+
+ DISALLOW_COPY_AND_ASSIGN(GlobalCertStore);
+};
+
+// static
+HCERTSTORE X509Certificate::cert_store() {
+ return Singleton<GlobalCertStore>::get()->cert_store();
+}
+
int X509Certificate::Verify(const std::string& hostname,
int flags,
CertVerifyResult* verify_result) const {
@@ -610,6 +583,28 @@ int X509Certificate::Verify(const std::string& hostname,
// EV requires revocation checking.
flags &= ~VERIFY_EV_CERT;
}
+
+ // Get the certificatePolicies extension of the certificate.
+ scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
+ LPSTR ev_policy_oid = NULL;
+ if (flags & VERIFY_EV_CERT) {
+ GetCertPoliciesInfo(cert_handle_, &policies_info);
+ if (policies_info.get()) {
+ EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
+ for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) {
+ LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier;
+ if (metadata->IsEVPolicyOID(policy_oid)) {
+ ev_policy_oid = policy_oid;
+ chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND;
+ chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1;
+ chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
+ &ev_policy_oid;
+ break;
+ }
+ }
+ }
+ }
+
PCCERT_CHAIN_CONTEXT chain_context;
// IE passes a non-NULL pTime argument that specifies the current system
// time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
@@ -625,6 +620,24 @@ int X509Certificate::Verify(const std::string& hostname,
&chain_context)) {
return MapSecurityError(GetLastError());
}
+ if (chain_context->TrustStatus.dwErrorStatus &
+ CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
+ ev_policy_oid = NULL;
+ chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
+ chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
+ CertFreeCertificateChain(chain_context);
+ if (!CertGetCertificateChain(
+ NULL, // default chain engine, HCCE_CURRENT_USER
+ cert_handle_,
+ NULL, // current system time
+ cert_handle_->hCertStore, // search this store
+ &chain_para,
+ chain_flags,
+ NULL, // reserved
+ &chain_context)) {
+ return MapSecurityError(GetLastError());
+ }
+ }
ScopedCertChainContext scoped_chain_context(chain_context);
GetCertChainInfo(chain_context, verify_result);
@@ -729,8 +742,7 @@ int X509Certificate::Verify(const std::string& hostname,
if (IsCertStatusError(verify_result->cert_status))
return MapCertStatusToNetError(verify_result->cert_status);
- // TODO(ukai): combine regular cert verification and EV cert verification.
- if ((flags & VERIFY_EV_CERT) && VerifyEV())
+ if (ev_policy_oid && CheckEV(chain_context, ev_policy_oid))
verify_result->cert_status |= CERT_STATUS_IS_EV;
return OK;
}
@@ -741,16 +753,8 @@ int X509Certificate::Verify(const std::string& hostname,
// certificates in the certificate chain according to Section 7 (pp. 11-12)
// of the EV Certificate Guidelines Version 1.0 at
// http://cabforum.org/EV_Certificate_Guidelines.pdf.
-bool X509Certificate::VerifyEV() const {
- DCHECK(cert_handle_);
- net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance();
-
- PCCERT_CHAIN_CONTEXT chain_context = ConstructCertChain(cert_handle_,
- metadata->GetPolicyOIDs(), metadata->NumPolicyOIDs());
- if (!chain_context)
- return false;
- ScopedCertChainContext scoped_chain_context(chain_context);
-
+bool X509Certificate::CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
+ const char* policy_oid) const {
DCHECK(chain_context->cChain != 0);
// If the cert doesn't match any of the policies, the
// CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
@@ -771,19 +775,16 @@ bool X509Certificate::VerifyEV() const {
// Look up the EV policy OID of the root CA.
PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
SHA1Fingerprint fingerprint = CalculateFingerprint(root_cert);
- const char* ev_policy_oid = NULL;
- if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid))
- return false;
- DCHECK(ev_policy_oid);
-
- // Get the certificatePolicies extension of the end certificate.
- PCCERT_CONTEXT end_cert = element[0]->pCertContext;
- scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
- GetCertPoliciesInfo(end_cert, &policies_info);
- if (!policies_info.get())
- return false;
+ EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
+ return metadata->HasEVPolicyOID(fingerprint, policy_oid);
+}
- return ContainsPolicy(policies_info.get(), ev_policy_oid);
+bool X509Certificate::VerifyEV() const {
+ // We don't call this private method, but we do need to implement it because
+ // it's defined in x509_certificate.h. We perform EV checking in the
+ // Verify() above.
+ NOTREACHED();
+ return false;
}
// static
diff --git a/net/base/x509_openssl_util.cc b/net/base/x509_openssl_util.cc
new file mode 100644
index 0000000..22ab59a
--- /dev/null
+++ b/net/base/x509_openssl_util.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2006-2008 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/base/x509_openssl_util.h"
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
+#include "base/time.h"
+
+namespace net {
+
+namespace x509_openssl_util {
+
+namespace {
+
+// Helper for ParseDate. |*field| must contain at least |field_len| characters.
+// |*field| will be advanced by |field_len| on exit. |*ok| is set to false if
+// there is an error in parsing the number, but left untouched otherwise.
+// Returns the parsed integer.
+int ParseIntAndAdvance(const char** field, size_t field_len, bool* ok) {
+ int result = 0;
+ *ok &= base::StringToInt(*field, *field + field_len, &result);
+ *field += field_len;
+ return result;
+}
+
+} // namespace
+
+bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
+ int index,
+ std::string* key,
+ std::string* value) {
+ X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
+ if (!entry)
+ return false;
+
+ if (key) {
+ ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
+ key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
+ }
+
+ ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
+ if (!data)
+ return false;
+
+ unsigned char* buf = NULL;
+ int len = ASN1_STRING_to_UTF8(&buf, data);
+ if (len <= 0)
+ return false;
+
+ value->assign(reinterpret_cast<const char*>(buf), len);
+ OPENSSL_free(buf);
+ return true;
+}
+
+bool ParsePrincipalValueByIndex(X509_NAME* name,
+ int index,
+ std::string* value) {
+ return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
+}
+
+bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
+ int index = X509_NAME_get_index_by_NID(name, nid, -1);
+ if (index < 0)
+ return false;
+
+ return ParsePrincipalValueByIndex(name, index, value);
+}
+
+bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
+ if (!x509_time ||
+ (x509_time->type != V_ASN1_UTCTIME &&
+ x509_time->type != V_ASN1_GENERALIZEDTIME))
+ return false;
+
+ base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
+ x509_time->length);
+ // UTCTime: YYMMDDHHMMSSZ
+ // GeneralizedTime: YYYYMMDDHHMMSSZ
+ size_t year_length = x509_time->type == V_ASN1_UTCTIME ? 2 : 4;
+
+ if (str_date.length() < 11 + year_length)
+ return false;
+
+ const char* field = str_date.data();
+ bool valid = true;
+ base::Time::Exploded exploded = {0};
+
+ exploded.year = ParseIntAndAdvance(&field, year_length, &valid);
+ exploded.month = ParseIntAndAdvance(&field, 2, &valid);
+ exploded.day_of_month = ParseIntAndAdvance(&field, 2, &valid);
+ exploded.hour = ParseIntAndAdvance(&field, 2, &valid);
+ exploded.minute = ParseIntAndAdvance(&field, 2, &valid);
+ exploded.second = ParseIntAndAdvance(&field, 2, &valid);
+ if (valid && year_length == 2)
+ exploded.year += exploded.year < 50 ? 2000 : 1900;
+
+ valid &= exploded.HasValidValues();
+
+ if (!valid) {
+ NOTREACHED() << "can't parse x509 date " << str_date;
+ return false;
+ }
+
+ *time = base::Time::FromUTCExploded(exploded);
+ return true;
+}
+
+} // namespace x509_openssl_util
+
+} // namespace net
diff --git a/net/base/x509_openssl_util.h b/net/base/x509_openssl_util.h
new file mode 100644
index 0000000..5ac511b
--- /dev/null
+++ b/net/base/x509_openssl_util.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2006-2008 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_BASE_X509_OPENSSL_UTIL_H_
+#define NET_BASE_X509_OPENSSL_UTIL_H_
+#pragma once
+
+#include <openssl/asn1.h>
+#include <openssl/x509v3.h>
+
+#include <string>
+
+namespace base {
+class Time;
+} // namespace base
+
+namespace net {
+
+// A collection of helper functions to fetch data from OpenSSL X509 certificates
+// into more convenient std / base datatypes.
+namespace x509_openssl_util {
+
+bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
+ int index,
+ std::string* key,
+ std::string* value);
+
+bool ParsePrincipalValueByIndex(X509_NAME* name, int index, std::string* value);
+
+bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value);
+
+bool ParseDate(ASN1_TIME* x509_time, base::Time* time);
+
+} // namespace x509_openssl_util
+
+} // namespace net
+
+#endif // NET_BASE_X509_OPENSSL_UTIL_H_
diff --git a/net/data/ftp/dir-listing-ls-19 b/net/data/ftp/dir-listing-ls-19
new file mode 100644
index 0000000..c7c66fe
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-19
@@ -0,0 +1,2 @@
+drwxr-xr-x 2 0 0 4096 Mar 18 2007
+-rw-r--r-- 1 48 0 4327486 Jun 16 2006 junorelease.zip
diff --git a/net/data/ftp/dir-listing-ls-19.expected b/net/data/ftp/dir-listing-ls-19.expected
new file mode 100644
index 0000000..9f0f297
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-19.expected
@@ -0,0 +1,8 @@
+-
+junorelease.zip
+4327486
+2006
+6
+16
+0
+0
diff --git a/net/data/valgrind/DIRECTORY_MOVED b/net/data/valgrind/DIRECTORY_MOVED
new file mode 100644
index 0000000..96449fe
--- /dev/null
+++ b/net/data/valgrind/DIRECTORY_MOVED
@@ -0,0 +1,4 @@
+For those who got a merge conflict in this directory on update:
+The files from this dir has been moved to tools/valgrind/gtest_exclude
+
+TODO(timurrrr): remove this in a couple of weeks
diff --git a/net/data/valgrind/net_unittests.gtest-drmemory_win32.txt b/net/data/valgrind/net_unittests.gtest-drmemory_win32.txt
deleted file mode 100644
index 10b8617..0000000
--- a/net/data/valgrind/net_unittests.gtest-drmemory_win32.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-# See http://crbug.com/51145
-HttpNetworkTransactionTest.*
-HttpNetworkLayerTest.GET
-
-# TODO(timurrrr): investigate these
-ClientSocketPoolBaseTest.*
-SSLClientSocketTest.*
-ProxyResolverJS*
-X509CertificateTest.*
-UrlToFilenameEncoderTest.*
-DirectoryListerTest.*
-WebSocketHandshake*
-HTTPSRequestTest.*
-NetUtilTest.*
diff --git a/net/data/valgrind/net_unittests.gtest-memcheck.txt b/net/data/valgrind/net_unittests.gtest-memcheck.txt
deleted file mode 100644
index e7f42dd..0000000
--- a/net/data/valgrind/net_unittests.gtest-memcheck.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-# These tests leak data intentionally, so are inappropriate for Valgrind tests.
-# Similar list in ../purify/net_unittests.exe.gtest.txt
-# TODO(dkegel): either merge the two files or keep them in sync,
-# see http://code.google.com/p/chromium/issues/detail?id=8951
-DiskCacheBackendTest.AppCacheInvalidEntry
-DiskCacheBackendTest.AppCacheInvalidEntryRead
-DiskCacheBackendTest.AppCacheInvalidEntryWithLoad
-DiskCacheBackendTest.InvalidEntry
-DiskCacheBackendTest.InvalidEntryRead
-DiskCacheBackendTest.InvalidEntryWithLoad
-DiskCacheBackendTest.TrimInvalidEntry
-DiskCacheBackendTest.TrimInvalidEntry2
-DiskCacheBackendTest.InvalidEntryEnumeration
-DiskCacheBackendTest.NewEvictionInvalidEntry
-DiskCacheBackendTest.NewEvictionInvalidEntryRead
-DiskCacheBackendTest.NewEvictionInvalidEntryWithLoad
-DiskCacheBackendTest.NewEvictionTrimInvalidEntry
-DiskCacheBackendTest.NewEvictionTrimInvalidEntry2
-DiskCacheBackendTest.NewEvictionInvalidEntryEnumeration
diff --git a/net/data/valgrind/net_unittests.gtest-tsan.txt b/net/data/valgrind/net_unittests.gtest-tsan.txt
deleted file mode 100644
index 1ddf884..0000000
--- a/net/data/valgrind/net_unittests.gtest-tsan.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# These huge tests are flaky and sometimes crash the following tests.
-# See http://crbug.com/50346
-DiskCacheEntryTest.*HugeSparse*
-
-# SPDY tests tend to crash on both Mac and Windows.
-# See http://crbug.com/51144
-Spdy/SpdyNetworkTransactionTest.SocketWriteReturnsZero*
-# See http://crbug.com/50918
-Spdy/SpdyNetworkTransactionTest.CancelledTransactionSendRst*
-# See http://crbug.com/51087
-Spdy*
-
-# See http://crbug.com/44570
-HttpNetworkTransactionTest.StopsReading204
-# See http://crbug.com/51145
-HttpNetworkTransactionTest.Incomplete100ThenEOF
-HttpNetworkTransactionTest.UseAlternateProtocolForNpnSpdyWithExistingSpdySession
-HttpNetworkTransactionTest.KeepAliveConnectionEOF
diff --git a/net/data/valgrind/net_unittests.gtest-tsan_mac.txt b/net/data/valgrind/net_unittests.gtest-tsan_mac.txt
deleted file mode 100644
index 6359e4b..0000000
--- a/net/data/valgrind/net_unittests.gtest-tsan_mac.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# WebSocketTest tests are extraordinary slow under ThreadSanitizer,
-# (see http://crbug.com/25392)
-# TODO(glider): investigate this.
-WebSocketTest.*
-
-# Strange reports from __NSThread__main__ appeared with the new TSan binaries
-# See http://crbug.com/38926
-DirectoryLister*
diff --git a/net/data/valgrind/net_unittests.gtest-tsan_win32.txt b/net/data/valgrind/net_unittests.gtest-tsan_win32.txt
deleted file mode 100644
index b7b6e2c..0000000
--- a/net/data/valgrind/net_unittests.gtest-tsan_win32.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-# These tests fail due to unknown reasons
-# TODO(timurrrr): investigate
-CookieMonsterTest.TestLastAccess
-SpdyNetwork*Error*
-SpdyNetwork*Get*
-SpdyNetworkTransactionTest.SynReplyHeadersVary
-X509CertificateTest.UnoSoftCertParsing
-URLRequestTest.DoNotSaveCookies
-URLRequestTest.QuitTest
-
-# See http://crbug.com/46647
-DiskCacheBackendTest.*
-
-# See http://crbug.com/53304
-URLRequestTest.*
-
-# See http://crbug.com/47836
-ClientSocketPoolBaseTest.CancelPendingSocketAtSocketLimit
-
-# See http://crbug.com/51145
-HttpNetworkTransactionTest.*
-HttpNetworkLayerTest.GET
-
-# Timing out under TSan, see http://crbug.com/59642
-CookieMonsterTest.GarbageCollectionTriggers
-
-#########################################
-# These tests fail if you don't have our SSL certificate installed.
-# Please see http://dev.chromium.org/developers/testing#TOC-SSL-tests
-# if you think you want to un-comment one of the following lines.
-#SSLClientSocketTest.*
-#URLRequestTest*
-#HTTPSRequestTest.*
-#X509CertificateTest.*
-#ProxyScriptFetcherTest.*
diff --git a/net/data/valgrind/net_unittests.gtest.txt b/net/data/valgrind/net_unittests.gtest.txt
deleted file mode 100644
index 0af617c..0000000
--- a/net/data/valgrind/net_unittests.gtest.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Very slow under Valgrind.
-KeygenHandlerTest.*SmokeTest
-KeygenHandlerTest.*ConcurrencyTest
-
-# Fails Valgrind with varying stack traces. http://crbug.com/43179
-SpdyNetworkTransactionTest.PostWithEarlySynReply
diff --git a/net/data/valgrind/net_unittests.gtest_linux.txt b/net/data/valgrind/net_unittests.gtest_linux.txt
deleted file mode 100644
index 1b69eec..0000000
--- a/net/data/valgrind/net_unittests.gtest_linux.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# These tests fail due to certificate errors; see http://crbug.com/36770
-HTTPSRequestTest.HTTPSMismatchedTest
-SSLClientSocketTest.ConnectMismatched
diff --git a/net/data/valgrind/net_unittests.gtest_mac.txt b/net/data/valgrind/net_unittests.gtest_mac.txt
deleted file mode 100644
index 57f2365..0000000
--- a/net/data/valgrind/net_unittests.gtest_mac.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# Very slow under Valgrind, (see <http://crbug.com/37289>).
-KeygenHandlerTest.SmokeTest
diff --git a/net/data/valgrind/net_unittests.gtest_wine.txt b/net/data/valgrind/net_unittests.gtest_wine.txt
deleted file mode 100644
index 2492f86..0000000
--- a/net/data/valgrind/net_unittests.gtest_wine.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-# crash Crashes in Wine
-# crash-valgrind Crashes in Wine + Valgrind
-# dontcare Safe to ignore
-# dontcare-hangwin Ignore, hangs on Windows too
-# dontcare-winfail Ignore, fails on Windows too
-# dontcare-flaky Ignore, flaky test
-# dontcare-hang Ignore, hangs we don't care about
-# fail Fails, needs triaging or needs to be fixed
-# fail-valgrind Fails only under Valgrind
-# fail_wine_vmware Fails in Wine under VMware? TODO(dank) clarify
-# flaky-valgrind Flaky under Valgrind, needs investigation
-# hang Test that hangs for some reason
-# hang-valgrind Test that hangs under valgrind, or just takes too long
-
-# fail
-http://bugs.winehq.org/show_bug.cgi?id=20748
-SSLClientSocketTest.Read_Interrupted
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-HTTPSRequestTest.HTTPSExpiredTest
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-HTTPSRequestTest.HTTPSGetTest
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-HTTPSRequestTest.HTTPSMismatchedTest
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-SSLClientSocketTest.Connect
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-SSLClientSocketTest.Read
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-SSLClientSocketTest.Read_FullDuplex
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-SSLClientSocketTest.Read_SmallChunks
-
-# fail
-# https/ssl failing on the bot, bad Wine? TODO(thestig): investigate
-URLRequestTestHTTP.HTTPSToHTTPRedirectNoRefererTest
diff --git a/net/data/valgrind/suppressions.txt b/net/data/valgrind/suppressions.txt
deleted file mode 100644
index e8cc210..0000000
--- a/net/data/valgrind/suppressions.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- Test DiskCacheBackendTest.InvalidEntryEnumeration leaks.
- Memcheck:Leak
- fun:_Znwj
- fun:_ZN10disk_cache12StorageBlockINS_12RankingsNodeEE12AllocateDataEv
- fun:_ZN10disk_cache12StorageBlockINS_12RankingsNodeEE4LoadEv
- fun:_ZN10disk_cache9EntryImpl15LoadNodeAddressEv
- fun:_ZN10disk_cache11BackendImpl8NewEntryENS_4AddrEPPNS_9EntryImplEPb
- fun:_ZN10disk_cache11BackendImpl10MatchEntryERKSsjb
- fun:_ZN10disk_cache11BackendImpl9OpenEntryERKSsPPNS_5EntryE
- fun:_ZN49DiskCacheBackendTest_InvalidEntryEnumeration_Test8TestBodyEv
- fun:_ZN7testing4Test3RunEv
-}
-{
- Test DiskCacheBackendTest.InvalidEntryRead leaks.
- Memcheck:Leak
- fun:_Znwj
- fun:_ZN10disk_cache11BackendImpl8NewEntryENS_4AddrEPPNS_9EntryImplEPb
- fun:_ZN10disk_cache11BackendImpl10MatchEntryERKSsjb
- fun:_ZN10disk_cache11BackendImpl9OpenEntryERKSsPPNS_5EntryE
- fun:_ZN42DiskCacheBackendTest_InvalidEntryRead_Test8TestBodyEv
- fun:_ZN7testing4Test3RunEv
-}
-{
- Test DiskCacheBackendTest.InvalidEntryWithLoad leaks.
- Memcheck:Leak
- fun:_Znwj
- fun:_ZN10disk_cache11BackendImpl11CreateEntryERKSsPPNS_5EntryE
- fun:_ZN46DiskCacheBackendTest_InvalidEntryWithLoad_Test8TestBodyEv
- fun:_ZN7testing4Test3RunEv
-}
-{
- Test FlipNetworkTransactionTest.WriteError Bug 29004
- Memcheck:Leak
- fun:_Znw*
- ...
- fun:_ZN3net26FlipNetworkTransactionTest17TransactionHelperERKNS_15HttpRequestInfoEPNS_17DelayedSocketDataE
- fun:_ZN3net42FlipNetworkTransactionTest_WriteError_Test8TestBodyEv
-}
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc
index 0709238..6162a77 100644
--- a/net/disk_cache/backend_impl.cc
+++ b/net/disk_cache/backend_impl.cc
@@ -13,6 +13,7 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/sys_info.h"
+#include "base/thread_restrictions.h"
#include "base/time.h"
#include "base/timer.h"
#include "base/worker_pool.h"
@@ -115,6 +116,10 @@ FilePath GetTempCacheName(const FilePath& path, const std::string& name) {
// Moves the cache files to a new folder and creates a task to delete them.
bool DelayedCacheCleanup(const FilePath& full_path) {
+ // GetTempCacheName() and MoveCache() use synchronous file
+ // operations.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
FilePath current_path = full_path.StripTrailingSeparators();
FilePath path = current_path.DirName();
@@ -169,13 +174,13 @@ bool SetFieldTrialInfo(int size_group) {
// Field trials involve static objects so we have to do this only once.
first = false;
- scoped_refptr<base::FieldTrial> trial1 =
- new base::FieldTrial("CacheSize", 10);
+ scoped_refptr<base::FieldTrial> trial1(
+ new base::FieldTrial("CacheSize", 10));
std::string group1 = base::StringPrintf("CacheSizeGroup_%d", size_group);
trial1->AppendGroup(group1, base::FieldTrial::kAllRemainingProbability);
- scoped_refptr<base::FieldTrial> trial2 =
- new base::FieldTrial("CacheThrottle", 100);
+ scoped_refptr<base::FieldTrial> trial2(
+ new base::FieldTrial("CacheThrottle", 100));
int group2a = trial2->AppendGroup("CacheThrottle_On", 10); // 10 % in.
trial2->AppendGroup("CacheThrottle_Off", 10); // 10 % control.
@@ -1310,6 +1315,13 @@ int BackendImpl::RunTaskForTest(Task* task, CompletionCallback* callback) {
return net::ERR_IO_PENDING;
}
+void BackendImpl::ThrottleRequestsForTest(bool throttle) {
+ if (throttle)
+ background_queue_.StartQueingOperations();
+ else
+ background_queue_.StopQueingOperations();
+}
+
int BackendImpl::SelfCheck() {
if (!init_) {
LOG(ERROR) << "Init failed";
diff --git a/net/disk_cache/backend_impl.h b/net/disk_cache/backend_impl.h
index a8880d1..05e5016 100644
--- a/net/disk_cache/backend_impl.h
+++ b/net/disk_cache/backend_impl.h
@@ -249,6 +249,9 @@ class BackendImpl : public Backend {
// deleted after it runs.
int RunTaskForTest(Task* task, CompletionCallback* callback);
+ // Starts or stops throttling requests.
+ void ThrottleRequestsForTest(bool throttle);
+
// Peforms a simple self-check, and returns the number of dirty items
// or an error code (negative value).
int SelfCheck();
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index adfc95c..4298456 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -230,7 +230,7 @@ TEST_F(DiskCacheBackendTest, ExternalFiles) {
FilePath filename = GetCacheFilePath().AppendASCII("f_000001");
const int kSize = 50;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer1->data(), kSize, false);
ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize));
@@ -241,7 +241,7 @@ TEST_F(DiskCacheBackendTest, ExternalFiles) {
entry->Close();
// And verify that the first file is still there.
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize));
EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
}
@@ -269,7 +269,7 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO) {
ASSERT_EQ(net::OK, cb.GetResult(rv));
const int kSize = 25000;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) {
@@ -319,7 +319,7 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO2) {
ASSERT_EQ(net::OK, cb.GetResult(rv));
const int kSize = 25000;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
rv = entry->WriteData(0, 0, buffer, kSize, &cb, false);
@@ -366,7 +366,7 @@ void DiskCacheBackendTest::BackendSetSize() {
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(cache_size);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size));
memset(buffer->data(), 0, cache_size);
EXPECT_EQ(cache_size / 10, WriteData(entry, 0, 0, buffer, cache_size / 10,
false)) << "normal file";
@@ -497,7 +497,7 @@ void DiskCacheBackendTest::BackendValidEntry() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
memset(buffer1->data(), 0, kSize);
base::strlcpy(buffer1->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1, kSize, false));
@@ -506,7 +506,7 @@ void DiskCacheBackendTest::BackendValidEntry() {
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
memset(buffer2->data(), 0, kSize);
EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2, kSize));
entry->Close();
@@ -535,7 +535,7 @@ void DiskCacheBackendTest::BackendInvalidEntry() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
base::strlcpy(buffer->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
@@ -579,7 +579,7 @@ void DiskCacheBackendTest::BackendInvalidEntryRead() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
base::strlcpy(buffer->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
@@ -697,7 +697,7 @@ void DiskCacheBackendTest::BackendTrimInvalidEntry() {
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer, kSize, false));
@@ -748,7 +748,7 @@ void DiskCacheBackendTest::BackendTrimInvalidEntry2() {
SetMaxSize(kSize * 40);
InitCache();
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
disk_cache::Entry* entry;
@@ -940,7 +940,7 @@ void DiskCacheBackendTest::BackendInvalidEntryEnumeration() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
const int kSize = 50;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
memset(buffer1->data(), 0, kSize);
base::strlcpy(buffer1->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1, kSize, false));
@@ -1574,7 +1574,7 @@ void DiskCacheBackendTest::BackendDisable4() {
ASSERT_EQ(net::OK, CreateEntry(key3, &entry3));
const int kBufSize = 20000;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kBufSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize));
memset(buf->data(), 0, kBufSize);
EXPECT_EQ(100, WriteData(entry2, 0, 0, buf, 100, false));
EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf, kBufSize, false));
@@ -1840,7 +1840,7 @@ TEST_F(DiskCacheBackendTest, TotalBuffersSize1) {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 200;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, true);
for (int i = 0; i < 10; i++) {
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc
index 1f1514d..c86955f 100644
--- a/net/disk_cache/disk_cache_perftest.cc
+++ b/net/disk_cache/disk_cache_perftest.cc
@@ -44,8 +44,8 @@ const int kMaxSize = 16 * 1024 - 1;
int TimeWrite(int num_entries, disk_cache::Backend* cache,
TestEntries* entries) {
const int kSize1 = 200;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kMaxSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kMaxSize));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
CacheTestFillBuffer(buffer2->data(), kMaxSize, false);
@@ -95,8 +95,8 @@ int TimeWrite(int num_entries, disk_cache::Backend* cache,
int TimeRead(int num_entries, disk_cache::Backend* cache,
const TestEntries& entries, bool cold) {
const int kSize1 = 200;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kMaxSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kMaxSize));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
CacheTestFillBuffer(buffer2->data(), kMaxSize, false);
diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc
index 7fabbe5..ce59270 100644
--- a/net/disk_cache/entry_impl.cc
+++ b/net/disk_cache/entry_impl.cc
@@ -148,6 +148,7 @@ bool EntryImpl::UserBuffer::PreWrite(int offset, int len) {
void EntryImpl::UserBuffer::Truncate(int offset) {
DCHECK_GE(offset, 0);
DCHECK_GE(offset, offset_);
+ DVLOG(3) << "Buffer truncate at " << offset << " current " << offset_;
offset -= offset_;
if (Size() >= offset)
@@ -159,6 +160,7 @@ void EntryImpl::UserBuffer::Write(int offset, net::IOBuffer* buf, int len) {
DCHECK_GE(len, 0);
DCHECK_GE(offset + len, 0);
DCHECK_GE(offset, offset_);
+ DVLOG(3) << "Buffer write at " << offset << " current " << offset_;
if (!Size() && offset > kMaxBlockSize)
offset_ = offset;
@@ -268,6 +270,8 @@ bool EntryImpl::UserBuffer::GrowBuffer(int required, int limit) {
if (!grow_allowed_)
return false;
+ DVLOG(3) << "Buffer grow to " << required;
+
buffer_.reserve(required);
return true;
}
@@ -480,6 +484,7 @@ void EntryImpl::DoomImpl() {
int EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf,
int buf_len, CompletionCallback* callback) {
DCHECK(node_.Data()->dirty || read_only_);
+ DVLOG(2) << "Read from " << index << " at " << offset << " : " << buf_len;
if (index < 0 || index >= kNumStreams)
return net::ERR_INVALID_ARGUMENT;
@@ -500,8 +505,8 @@ int EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf,
backend_->OnEvent(Stats::READ_DATA);
backend_->OnRead(buf_len);
- // We need the current size in disk.
- int eof = entry_size - unreported_size_[index];
+ Addr address(entry_.Data()->data_addr[index]);
+ int eof = address.is_initialized() ? entry_size : 0;
if (user_buffers_[index].get() &&
user_buffers_[index]->PreRead(eof, offset, &buf_len)) {
// Complete the operation locally.
@@ -510,7 +515,7 @@ int EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf,
return buf_len;
}
- Addr address(entry_.Data()->data_addr[index]);
+ address.set_value(entry_.Data()->data_addr[index]);
DCHECK(address.is_initialized());
if (!address.is_initialized())
return net::ERR_FAILED;
@@ -548,6 +553,7 @@ int EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf,
int buf_len, CompletionCallback* callback,
bool truncate) {
DCHECK(node_.Data()->dirty || read_only_);
+ DVLOG(2) << "Write to " << index << " at " << offset << " : " << buf_len;
if (index < 0 || index >= kNumStreams)
return net::ERR_INVALID_ARGUMENT;
@@ -1142,14 +1148,20 @@ bool EntryImpl::ImportSeparateFile(int index, int new_size) {
bool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) {
DCHECK(user_buffers_[index].get());
- if (offset > user_buffers_[index]->End()) {
- // We are about to extend the buffer (with zeros), so make sure that we are
- // not overwriting anything.
+ if ((user_buffers_[index]->End() && offset > user_buffers_[index]->End()) ||
+ offset > entry_.Data()->data_size[index]) {
+ // We are about to extend the buffer or the file (with zeros), so make sure
+ // that we are not overwriting anything.
Addr address(entry_.Data()->data_addr[index]);
if (address.is_initialized() && address.is_separate_file()) {
- int eof = entry_.Data()->data_size[index];
- if (eof > user_buffers_[index]->Start() && !Flush(index, 0))
+ if (!Flush(index, 0))
return false;
+ // There is an actual file already, and we don't want to keep track of
+ // its length so we let this operation go straight to disk.
+ // The only case when a buffer is allowed to extend the file (as in fill
+ // with zeros before the start) is when there is no file yet to extend.
+ user_buffers_[index].reset();
+ return true;
}
}
@@ -1158,7 +1170,8 @@ bool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) {
return false;
// Lets try again.
- if (!user_buffers_[index]->PreWrite(offset, buf_len)) {
+ if (offset > user_buffers_[index]->End() ||
+ !user_buffers_[index]->PreWrite(offset, buf_len)) {
// We cannot complete the operation with a buffer.
DCHECK(!user_buffers_[index]->Size());
DCHECK(!user_buffers_[index]->Start());
@@ -1172,6 +1185,7 @@ bool EntryImpl::Flush(int index, int min_len) {
Addr address(entry_.Data()->data_addr[index]);
DCHECK(user_buffers_[index].get());
DCHECK(!address.is_initialized() || address.is_separate_file());
+ DVLOG(3) << "Flush";
int size = std::max(entry_.Data()->data_size[index], min_len);
if (size && !address.is_initialized() && !CreateDataBlock(index, size))
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
index c4dc705..bea940c 100644
--- a/net/disk_cache/entry_unittest.cc
+++ b/net/disk_cache/entry_unittest.cc
@@ -76,7 +76,7 @@ class InternalSyncIOTask : public SyncIOTask {
// This part of the test runs on the background thread.
void DiskCacheEntryTest::InternalSyncIOBackground(disk_cache::Entry* entry) {
const int kSize1 = 10;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
EXPECT_EQ(0, entry->ReadData(0, 0, buffer1, kSize1, NULL));
base::strlcpy(buffer1->data(), "the data", kSize1);
@@ -87,8 +87,8 @@ void DiskCacheEntryTest::InternalSyncIOBackground(disk_cache::Entry* entry) {
const int kSize2 = 5000;
const int kSize3 = 10000;
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
- scoped_refptr<net::IOBuffer> buffer3 = new net::IOBuffer(kSize3);
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
+ scoped_refptr<net::IOBuffer> buffer3(new net::IOBuffer(kSize3));
memset(buffer3->data(), 0, kSize3);
CacheTestFillBuffer(buffer2->data(), kSize2, false);
base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
@@ -179,9 +179,9 @@ void DiskCacheEntryTest::InternalAsyncIO() {
const int kSize1 = 10;
const int kSize2 = 5000;
const int kSize3 = 10000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
- scoped_refptr<net::IOBuffer> buffer3 = new net::IOBuffer(kSize3);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
+ scoped_refptr<net::IOBuffer> buffer3(new net::IOBuffer(kSize3));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
CacheTestFillBuffer(buffer2->data(), kSize2, false);
CacheTestFillBuffer(buffer3->data(), kSize3, false);
@@ -298,8 +298,8 @@ class ExternalSyncIOTask : public SyncIOTask {
void DiskCacheEntryTest::ExternalSyncIOBackground(disk_cache::Entry* entry) {
const int kSize1 = 17000;
const int kSize2 = 25000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
CacheTestFillBuffer(buffer2->data(), kSize2, false);
base::strlcpy(buffer1->data(), "the data", kSize1);
@@ -383,9 +383,9 @@ void DiskCacheEntryTest::ExternalAsyncIO() {
const int kSize1 = 17000;
const int kSize2 = 25000;
const int kSize3 = 25000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
- scoped_refptr<net::IOBuffer> buffer3 = new net::IOBuffer(kSize3);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
+ scoped_refptr<net::IOBuffer> buffer3(new net::IOBuffer(kSize3));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
CacheTestFillBuffer(buffer2->data(), kSize2, false);
CacheTestFillBuffer(buffer3->data(), kSize3, false);
@@ -475,14 +475,83 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyExternalAsyncIO) {
ExternalAsyncIO();
}
+TEST_F(DiskCacheEntryTest, RequestThrottling) {
+ SetDirectMode();
+ InitCache();
+ disk_cache::Entry* entry = NULL;
+ ASSERT_EQ(net::OK, CreateEntry("the first key", &entry));
+ ASSERT_TRUE(NULL != entry);
+
+ // Let's verify that each IO goes to the right callback object.
+ CallbackTest cb(true);
+
+ g_cache_tests_error = false;
+ g_cache_tests_received = 0;
+
+ MessageLoopHelper helper;
+
+ const int kSize = 200;
+ scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ CacheTestFillBuffer(buffer->data(), kSize, false);
+
+ int expected = 0;
+ // Start with no throttling.
+ for (; expected < 10; expected++) {
+ int ret = entry->WriteData(0, 0, buffer, kSize, &cb, false);
+ EXPECT_EQ(net::ERR_IO_PENDING, ret);
+ }
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ // And now with full throttling.
+ cache_impl_->ThrottleRequestsForTest(true);
+ for (; expected < 20; expected++) {
+ int ret = entry->WriteData(0, 0, buffer, kSize, &cb, false);
+ EXPECT_EQ(net::ERR_IO_PENDING, ret);
+ }
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ for (; expected < 30; expected++) {
+ int ret = entry->WriteData(0, 0, buffer, kSize, &cb, false);
+ EXPECT_EQ(net::ERR_IO_PENDING, ret);
+ }
+ // We have 9 queued requests, lets dispatch them all at once.
+ cache_impl_->ThrottleRequestsForTest(false);
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ cache_impl_->ThrottleRequestsForTest(true);
+ for (; expected < 40; expected++) {
+ int ret = entry->WriteData(0, 0, buffer, kSize, &cb, false);
+ EXPECT_EQ(net::ERR_IO_PENDING, ret);
+ }
+
+ // We can close the entry and keep receiving notifications.
+ entry->Close();
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ ASSERT_EQ(net::OK, OpenEntry("the first key", &entry));
+ for (; expected < 50; expected++) {
+ int ret = entry->WriteData(0, 0, buffer, kSize, &cb, false);
+ EXPECT_EQ(net::ERR_IO_PENDING, ret);
+ }
+
+ // ... and even close the cache.
+ entry->Close();
+ delete cache_impl_;
+ cache_ = cache_impl_ = NULL;
+ EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
+
+ EXPECT_FALSE(g_cache_tests_error);
+ EXPECT_EQ(expected, g_cache_tests_received);
+}
+
void DiskCacheEntryTest::StreamAccess() {
disk_cache::Entry* entry = NULL;
ASSERT_EQ(net::OK, CreateEntry("the first key", &entry));
ASSERT_TRUE(NULL != entry);
const int kBufferSize = 1024;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kBufferSize);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kBufferSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kBufferSize));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kBufferSize));
const int kNumStreams = 3;
for (int i = 0; i < kNumStreams; i++) {
@@ -579,7 +648,7 @@ void DiskCacheEntryTest::GetTimes() {
Time t3 = Time::Now();
EXPECT_TRUE(t3 > t2);
const int kSize = 200;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer, kSize));
if (type_ == net::APP_CACHE) {
EXPECT_TRUE(entry->GetLastUsed() < t2);
@@ -614,8 +683,8 @@ void DiskCacheEntryTest::GrowData() {
ASSERT_EQ(net::OK, CreateEntry(key1, &entry));
const int kSize = 20000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer1->data(), kSize, false);
memset(buffer2->data(), 0, kSize);
@@ -699,8 +768,8 @@ void DiskCacheEntryTest::TruncateData() {
const int kSize1 = 20000;
const int kSize2 = 20000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
memset(buffer2->data(), 0, kSize2);
@@ -755,11 +824,6 @@ void DiskCacheEntryTest::TruncateData() {
TEST_F(DiskCacheEntryTest, TruncateData) {
InitCache();
TruncateData();
-
- // We generate asynchronous IO that is not really tracked until completion
- // so we just wait here before running the next test.
- MessageLoopHelper helper;
- helper.WaitUntilCacheIoFinished(1);
}
TEST_F(DiskCacheEntryTest, TruncateDataNoBuffer) {
@@ -767,11 +831,6 @@ TEST_F(DiskCacheEntryTest, TruncateDataNoBuffer) {
InitCache();
cache_impl_->SetFlags(disk_cache::kNoBuffering);
TruncateData();
-
- // We generate asynchronous IO that is not really tracked until completion
- // so we just wait here before running the next test.
- MessageLoopHelper helper;
- helper.WaitUntilCacheIoFinished(1);
}
TEST_F(DiskCacheEntryTest, MemoryOnlyTruncateData) {
@@ -801,7 +860,7 @@ void DiskCacheEntryTest::ZeroLengthIO() {
// Lets verify the actual content.
const int kSize = 20;
const char zeros[kSize] = {};
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
EXPECT_EQ(kSize, ReadData(entry, 0, 500, buffer, kSize));
@@ -843,8 +902,8 @@ void DiskCacheEntryTest::Buffering() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 200;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer1->data(), kSize, true);
CacheTestFillBuffer(buffer2->data(), kSize, true);
@@ -900,6 +959,16 @@ void DiskCacheEntryTest::Buffering() {
EXPECT_EQ(100, ReadData(entry, 1, 23100, buffer2, kSize));
EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + 100, 100));
+ // Extend the file again and read before without closing the entry.
+ EXPECT_EQ(kSize, WriteData(entry, 1, 25000, buffer1, kSize, false));
+ EXPECT_EQ(kSize, WriteData(entry, 1, 45000, buffer1, kSize, false));
+ CacheTestFillBuffer(buffer2->data(), kSize, true);
+ EXPECT_EQ(kSize, ReadData(entry, 1, 25000, buffer2, kSize));
+ EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
+ CacheTestFillBuffer(buffer2->data(), kSize, true);
+ EXPECT_EQ(kSize, ReadData(entry, 1, 45000, buffer2, kSize));
+ EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
+
entry->Close();
}
@@ -924,8 +993,8 @@ void DiskCacheEntryTest::SizeChanges() {
const int kSize = 200;
const char zeros[kSize] = {};
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer1->data(), kSize, true);
CacheTestFillBuffer(buffer2->data(), kSize, true);
@@ -943,7 +1012,7 @@ void DiskCacheEntryTest::SizeChanges() {
EXPECT_TRUE(!memcmp(buffer2->data(), zeros, kSize));
// Read at the end of the old file size.
- EXPECT_EQ(35, ReadData(entry, 1, 23000 + kSize - 35, buffer2, kSize));
+ EXPECT_EQ(kSize, ReadData(entry, 1, 23000 + kSize - 35, buffer2, kSize));
EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + kSize - 35, 35));
// Read slightly before the last write.
@@ -1013,7 +1082,7 @@ void DiskCacheEntryTest::ReuseEntry(int size) {
std::string key2("the second key");
ASSERT_EQ(net::OK, CreateEntry(key2, &entry));
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size));
CacheTestFillBuffer(buffer->data(), size, false);
for (int i = 0; i < 15; i++) {
@@ -1067,9 +1136,9 @@ void DiskCacheEntryTest::InvalidData() {
const int kSize1 = 20000;
const int kSize2 = 20000;
const int kSize3 = 20000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
- scoped_refptr<net::IOBuffer> buffer3 = new net::IOBuffer(kSize3);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
+ scoped_refptr<net::IOBuffer> buffer3(new net::IOBuffer(kSize3));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
memset(buffer2->data(), 0, kSize2);
@@ -1149,7 +1218,7 @@ TEST_F(DiskCacheEntryTest, ReadWriteDestroyBuffer) {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 200;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
TestCompletionCallback cb;
@@ -1179,7 +1248,7 @@ void DiskCacheEntryTest::DoomNormalEntry() {
entry->Close();
const int kSize = 20000;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, true);
buffer->data()[19999] = '\0';
@@ -1220,8 +1289,8 @@ void DiskCacheEntryTest::DoomedEntry() {
const int kSize1 = 2000;
const int kSize2 = 2000;
- scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize1);
- scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize2);
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
memset(buffer2->data(), 0, kSize2);
@@ -1254,7 +1323,7 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyEnumerationWithSparseEntries) {
InitCache();
const int kSize = 4096;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
std::string key("the first key");
@@ -1308,7 +1377,7 @@ void VerifyContentSparseIO(disk_cache::Entry* entry, int64 offset, char* buffer,
int size) {
TestCompletionCallback cb;
- scoped_refptr<net::IOBuffer> buf_1 = new net::IOBuffer(size);
+ scoped_refptr<net::IOBuffer> buf_1(new net::IOBuffer(size));
memset(buf_1->data(), 0, size);
int ret = entry->ReadSparseData(offset, buf_1, size, &cb);
EXPECT_EQ(size, cb.GetResult(ret));
@@ -1322,8 +1391,8 @@ void DiskCacheEntryTest::BasicSparseIO() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 2048;
- scoped_refptr<net::IOBuffer> buf_1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buf_2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf_1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buf_2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf_1->data(), kSize, false);
// Write at offset 0.
@@ -1363,8 +1432,8 @@ void DiskCacheEntryTest::HugeSparseIO() {
// Write 1.2 MB so that we cover multiple entries.
const int kSize = 1200 * 1024;
- scoped_refptr<net::IOBuffer> buf_1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buf_2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf_1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buf_2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf_1->data(), kSize, false);
// Write at offset 0x20F0000 (33 MB - 64 KB).
@@ -1394,7 +1463,7 @@ void DiskCacheEntryTest::GetAvailableRange() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 16 * 1024;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
// Write at offset 0x20F0000 (33 MB - 64 KB), and 0x20F4400 (33 MB - 47 KB).
@@ -1456,7 +1525,7 @@ void DiskCacheEntryTest::CouldBeSparse() {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 16 * 1024;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
// Write at offset 0x20F0000 (33 MB - 64 KB).
@@ -1502,8 +1571,8 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedSparseIO) {
InitCache();
const int kSize = 8192;
- scoped_refptr<net::IOBuffer> buf_1 = new net::IOBuffer(kSize);
- scoped_refptr<net::IOBuffer> buf_2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf_1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buf_2(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf_1->data(), kSize, false);
std::string key("the first key");
@@ -1512,8 +1581,8 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedSparseIO) {
// This loop writes back to back starting from offset 0 and 9000.
for (int i = 0; i < kSize; i += 1024) {
- scoped_refptr<net::WrappedIOBuffer> buf_3 =
- new net::WrappedIOBuffer(buf_1->data() + i);
+ scoped_refptr<net::WrappedIOBuffer> buf_3(
+ new net::WrappedIOBuffer(buf_1->data() + i));
VerifySparseIO(entry, i, buf_3, 1024, buf_2);
VerifySparseIO(entry, 9000 + i, buf_3, 1024, buf_2);
}
@@ -1533,7 +1602,7 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedGetAvailableRange) {
InitCache();
const int kSize = 8192;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
disk_cache::Entry* entry;
@@ -1594,7 +1663,7 @@ void DiskCacheEntryTest::DoomSparseEntry() {
ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
const int kSize = 4 * 1024;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
int64 offset = 1024;
@@ -1681,7 +1750,7 @@ TEST_F(DiskCacheEntryTest, DoomSparseEntry2) {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 4 * 1024;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
int64 offset = 1024;
@@ -1711,7 +1780,7 @@ void DiskCacheEntryTest::PartialSparseEntry() {
// of a sparse entry, at least to write a big range without leaving holes.
const int kSize = 4 * 1024;
const int kSmallSize = 128;
- scoped_refptr<net::IOBuffer> buf1 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf1(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf1->data(), kSize, false);
// The first write is just to extend the entry. The third write occupies
@@ -1723,7 +1792,7 @@ void DiskCacheEntryTest::PartialSparseEntry() {
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
- scoped_refptr<net::IOBuffer> buf2 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf2(new net::IOBuffer(kSize));
memset(buf2->data(), 0, kSize);
EXPECT_EQ(0, ReadSparseData(entry, 8000, buf2, kSize));
@@ -1805,7 +1874,7 @@ TEST_F(DiskCacheEntryTest, CleanupSparseEntry) {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 4 * 1024;
- scoped_refptr<net::IOBuffer> buf1 = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf1(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf1->data(), kSize, false);
const int k1Meg = 1024 * 1024;
@@ -1856,7 +1925,7 @@ TEST_F(DiskCacheEntryTest, CancelSparseIO) {
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 40 * 1024;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
CacheTestFillBuffer(buf->data(), kSize, false);
// This will open and write two "real" entries.
diff --git a/net/disk_cache/file_posix.cc b/net/disk_cache/file_posix.cc
index 9d810c7..a8d74ae 100644
--- a/net/disk_cache/file_posix.cc
+++ b/net/disk_cache/file_posix.cc
@@ -182,9 +182,9 @@ void BackgroundIO::OnIOSignalled() {
void InFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
size_t offset, disk_cache::FileIOCallback *callback) {
- scoped_refptr<BackgroundIO> operation =
- new BackgroundIO(file, buf, buf_len, offset, callback, this);
- io_list_.insert(operation.get());
+ scoped_refptr<BackgroundIO> operation(
+ new BackgroundIO(file, buf, buf_len, offset, callback, this));
+ io_list_.insert(operation);
file->AddRef(); // Balanced on InvokeCallback()
if (!callback_thread_)
@@ -198,9 +198,9 @@ void InFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
void InFlightIO::PostWrite(disk_cache::File* file, const void* buf,
size_t buf_len, size_t offset,
disk_cache::FileIOCallback* callback) {
- scoped_refptr<BackgroundIO> operation =
- new BackgroundIO(file, buf, buf_len, offset, callback, this);
- io_list_.insert(operation.get());
+ scoped_refptr<BackgroundIO> operation(
+ new BackgroundIO(file, buf, buf_len, offset, callback, this));
+ io_list_.insert(operation);
file->AddRef(); // Balanced on InvokeCallback()
if (!callback_thread_)
@@ -241,7 +241,7 @@ void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
// Release the references acquired in PostRead / PostWrite.
operation->file()->Release();
- io_list_.erase(operation);
+ io_list_.erase(make_scoped_refptr(operation));
callback->OnFileIOComplete(bytes);
}
diff --git a/net/disk_cache/in_flight_backend_io.cc b/net/disk_cache/in_flight_backend_io.cc
index fe53829..d83bd10 100644
--- a/net/disk_cache/in_flight_backend_io.cc
+++ b/net/disk_cache/in_flight_backend_io.cc
@@ -42,8 +42,9 @@ bool BackendIO::IsEntryOperation() {
return operation_ > OP_MAX_BACKEND;
}
-void BackendIO::ReleaseEntry() {
- entry_ = NULL;
+// Runs on the background thread.
+void BackendIO::ReferenceEntry() {
+ entry_->AddRef();
}
base::TimeDelta BackendIO::ElapsedTime() const {
@@ -274,6 +275,8 @@ void BackendIO::ExecuteEntryOperation() {
NOTREACHED() << "Invalid Operation";
result_ = net::ERR_UNEXPECTED;
}
+ // We added a reference to protect the queued operation.
+ entry_->Release();
if (result_ != net::ERR_IO_PENDING)
controller_->OnIOComplete(this);
}
@@ -291,34 +294,34 @@ InFlightBackendIO::~InFlightBackendIO() {
}
void InFlightBackendIO::Init(CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->Init();
QueueOperation(operation);
}
void InFlightBackendIO::OpenEntry(const std::string& key, Entry** entry,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->OpenEntry(key, entry);
QueueOperation(operation);
}
void InFlightBackendIO::CreateEntry(const std::string& key, Entry** entry,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->CreateEntry(key, entry);
QueueOperation(operation);
}
void InFlightBackendIO::DoomEntry(const std::string& key,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->DoomEntry(key);
QueueOperation(operation);
}
void InFlightBackendIO::DoomAllEntries(CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->DoomAllEntries();
QueueOperation(operation);
}
@@ -326,58 +329,58 @@ void InFlightBackendIO::DoomAllEntries(CompletionCallback* callback) {
void InFlightBackendIO::DoomEntriesBetween(const base::Time initial_time,
const base::Time end_time,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->DoomEntriesBetween(initial_time, end_time);
QueueOperation(operation);
}
void InFlightBackendIO::DoomEntriesSince(const base::Time initial_time,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->DoomEntriesSince(initial_time);
QueueOperation(operation);
}
void InFlightBackendIO::OpenNextEntry(void** iter, Entry** next_entry,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->OpenNextEntry(iter, next_entry);
QueueOperation(operation);
}
void InFlightBackendIO::OpenPrevEntry(void** iter, Entry** prev_entry,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->OpenPrevEntry(iter, prev_entry);
QueueOperation(operation);
}
void InFlightBackendIO::EndEnumeration(void* iterator) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, NULL);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
operation->EndEnumeration(iterator);
QueueOperation(operation);
}
void InFlightBackendIO::CloseEntryImpl(EntryImpl* entry) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, NULL);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
operation->CloseEntryImpl(entry);
QueueOperation(operation);
}
void InFlightBackendIO::DoomEntryImpl(EntryImpl* entry) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, NULL);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
operation->DoomEntryImpl(entry);
QueueOperation(operation);
}
void InFlightBackendIO::FlushQueue(net::CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->FlushQueue();
QueueOperation(operation);
}
void InFlightBackendIO::RunTask(Task* task, net::CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->RunTask(task);
QueueOperation(operation);
}
@@ -385,7 +388,7 @@ void InFlightBackendIO::RunTask(Task* task, net::CompletionCallback* callback) {
void InFlightBackendIO::ReadData(EntryImpl* entry, int index, int offset,
net::IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->ReadData(entry, index, offset, buf, buf_len);
QueueOperation(operation);
}
@@ -394,7 +397,7 @@ void InFlightBackendIO::WriteData(EntryImpl* entry, int index, int offset,
net::IOBuffer* buf, int buf_len,
bool truncate,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->WriteData(entry, index, offset, buf, buf_len, truncate);
QueueOperation(operation);
}
@@ -402,7 +405,7 @@ void InFlightBackendIO::WriteData(EntryImpl* entry, int index, int offset,
void InFlightBackendIO::ReadSparseData(EntryImpl* entry, int64 offset,
net::IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->ReadSparseData(entry, offset, buf, buf_len);
QueueOperation(operation);
}
@@ -410,7 +413,7 @@ void InFlightBackendIO::ReadSparseData(EntryImpl* entry, int64 offset,
void InFlightBackendIO::WriteSparseData(EntryImpl* entry, int64 offset,
net::IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->WriteSparseData(entry, offset, buf, buf_len);
QueueOperation(operation);
}
@@ -418,28 +421,25 @@ void InFlightBackendIO::WriteSparseData(EntryImpl* entry, int64 offset,
void InFlightBackendIO::GetAvailableRange(EntryImpl* entry, int64 offset,
int len, int64* start,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->GetAvailableRange(entry, offset, len, start);
QueueOperation(operation);
}
void InFlightBackendIO::CancelSparseIO(EntryImpl* entry) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, NULL);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
operation->CancelSparseIO(entry);
QueueOperation(operation);
}
void InFlightBackendIO::ReadyForSparseIO(EntryImpl* entry,
CompletionCallback* callback) {
- scoped_refptr<BackendIO> operation = new BackendIO(this, backend_, callback);
+ scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
operation->ReadyForSparseIO(entry);
QueueOperation(operation);
}
void InFlightBackendIO::WaitForPendingIO() {
- // We clear the list first so that we don't post more operations after this
- // point.
- pending_ops_.clear();
InFlightIO::WaitForPendingIO();
}
@@ -455,45 +455,51 @@ void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
bool cancel) {
BackendIO* op = static_cast<BackendIO*>(operation);
- if (!op->IsEntryOperation() && !pending_ops_.empty()) {
- // Process the next request. Note that invoking the callback may result
- // in the backend destruction (and with it this object), so we should deal
- // with the next operation before invoking the callback.
- PostQueuedOperation(&pending_ops_);
- }
-
if (op->IsEntryOperation()) {
backend_->OnOperationCompleted(op->ElapsedTime());
- if (!pending_entry_ops_.empty()) {
- PostQueuedOperation(&pending_entry_ops_);
-
- // If we are not throttling requests anymore, dispatch the whole queue.
- if (!queue_entry_ops_) {
+ if (!pending_ops_.empty() && RemoveFirstQueuedOperation(op)) {
+ // Process the next request. Note that invoking the callback may result
+ // in the backend destruction (and with it this object), so we should deal
+ // with the next operation before invoking the callback.
+ if (queue_entry_ops_) {
+ PostQueuedOperation();
+ } else {
+ // If we are not throttling requests anymore, dispatch the whole queue.
CACHE_UMA(COUNTS_10000, "FinalQueuedOperations", 0,
- pending_entry_ops_.size());
- while (!pending_entry_ops_.empty())
- PostQueuedOperation(&pending_entry_ops_);
+ pending_ops_.size());
+ PostAllQueuedOperations();
}
}
}
if (op->callback() && (!cancel || op->IsEntryOperation()))
op->callback()->Run(op->result());
-
- if (cancel)
- op->ReleaseEntry();
}
void InFlightBackendIO::QueueOperation(BackendIO* operation) {
if (!operation->IsEntryOperation())
- return QueueOperationToList(operation, &pending_ops_);
+ return PostOperation(operation);
- if (!queue_entry_ops_)
+ // We have to protect the entry from deletion while it is on the queue.
+ // If the caller closes the entry right after writing to it, and the write is
+ // waiting on the queue, we could end up deleting the entry before the write
+ // operation is actually posted. Sending a task to reference the entry we make
+ // sure that there is an extra reference before the caller can post a task to
+ // release its reference.
+ background_thread_->PostTask(FROM_HERE,
+ NewRunnableMethod(operation, &BackendIO::ReferenceEntry));
+
+ bool empty_list = pending_ops_.empty();
+ if (!queue_entry_ops_ && empty_list)
return PostOperation(operation);
- CACHE_UMA(COUNTS_10000, "QueuedOperations", 0, pending_entry_ops_.size());
+ CACHE_UMA(COUNTS_10000, "QueuedOperations", 0, pending_ops_.size());
- QueueOperationToList(operation, &pending_entry_ops_);
+ // We keep the operation that we are executing in the list so that we know
+ // when it completes.
+ pending_ops_.push_back(operation);
+ if (empty_list)
+ PostOperation(operation);
}
void InFlightBackendIO::PostOperation(BackendIO* operation) {
@@ -502,18 +508,31 @@ void InFlightBackendIO::PostOperation(BackendIO* operation) {
OnOperationPosted(operation);
}
-void InFlightBackendIO::PostQueuedOperation(OperationList* from_list) {
- scoped_refptr<BackendIO> next_op = from_list->front();
- from_list->pop_front();
+void InFlightBackendIO::PostQueuedOperation() {
+ if (pending_ops_.empty())
+ return;
+
+ // Keep it in the list until it's done.
+ scoped_refptr<BackendIO> next_op = pending_ops_.front();
PostOperation(next_op);
}
-void InFlightBackendIO::QueueOperationToList(BackendIO* operation,
- OperationList* list) {
- if (list->empty())
- return PostOperation(operation);
+void InFlightBackendIO::PostAllQueuedOperations() {
+ for (OperationList::iterator it = pending_ops_.begin();
+ it != pending_ops_.end(); ++it) {
+ PostOperation(*it);
+ }
+ pending_ops_.clear();
+}
+
+bool InFlightBackendIO::RemoveFirstQueuedOperation(BackendIO* operation) {
+ DCHECK(!pending_ops_.empty());
+ scoped_refptr<BackendIO> next_op = pending_ops_.front();
+ if (operation != next_op)
+ return false;
- list->push_back(operation);
+ pending_ops_.pop_front();
+ return true;
}
} // namespace
diff --git a/net/disk_cache/in_flight_backend_io.h b/net/disk_cache/in_flight_backend_io.h
index 5eba131..ca239dd 100644
--- a/net/disk_cache/in_flight_backend_io.h
+++ b/net/disk_cache/in_flight_backend_io.h
@@ -37,7 +37,8 @@ class BackendIO : public BackgroundIO {
net::CompletionCallback* callback() { return callback_; }
- void ReleaseEntry();
+ // Grabs an extra reference of entry_.
+ void ReferenceEntry();
// Returns the time that has passed since the operation was created.
base::TimeDelta ElapsedTime() const;
@@ -72,12 +73,10 @@ class BackendIO : public BackgroundIO {
private:
// There are two types of operations to proxy: regular backend operations are
- // queued so that we don't have more than one operation going on at the same
- // time (for instance opening an entry and creating the same entry). On the
- // other hand, operations targeted to a given entry can be long lived and
- // support multiple simultaneous users (multiple reads or writes to the same
- // entry), so they are not queued, just posted to the worker thread as they
- // come.
+ // executed sequentially (queued by the message loop). On the other hand,
+ // operations targeted to a given entry can be long lived and support multiple
+ // simultaneous users (multiple reads or writes to the same entry), and they
+ // are subject to throttling, so we keep an explicit queue.
enum Operation {
OP_NONE = 0,
OP_INIT,
@@ -200,13 +199,13 @@ class InFlightBackendIO : public InFlightIO {
typedef std::list<scoped_refptr<BackendIO> > OperationList;
void QueueOperation(BackendIO* operation);
void PostOperation(BackendIO* operation);
- void PostQueuedOperation(OperationList* from_list);
- void QueueOperationToList(BackendIO* operation, OperationList* list);
+ void PostQueuedOperation();
+ void PostAllQueuedOperations();
+ bool RemoveFirstQueuedOperation(BackendIO* operation);
BackendImpl* backend_;
scoped_refptr<base::MessageLoopProxy> background_thread_;
- OperationList pending_ops_; // The list of operations to be posted.
- OperationList pending_entry_ops_; // Entry (async) operations to be posted.
+ OperationList pending_ops_; // Entry (async) operations to be posted.
bool queue_entry_ops_; // True if we are queuing entry (async) operations.
DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO);
diff --git a/net/disk_cache/in_flight_io.cc b/net/disk_cache/in_flight_io.cc
index 5c859af..ba24d61 100644
--- a/net/disk_cache/in_flight_io.cc
+++ b/net/disk_cache/in_flight_io.cc
@@ -74,14 +74,14 @@ void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
// Make sure that we remove the operation from the list before invoking the
// callback (so that a subsequent cancel does not invoke the callback again).
DCHECK(io_list_.find(operation) != io_list_.end());
- io_list_.erase(operation);
+ io_list_.erase(make_scoped_refptr(operation));
OnOperationComplete(operation, cancel_task);
}
// Runs on the primary thread.
void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
DCHECK(callback_thread_->BelongsToCurrentThread());
- io_list_.insert(operation);
+ io_list_.insert(make_scoped_refptr(operation));
}
} // namespace disk_cache
diff --git a/net/disk_cache/mem_entry_impl.cc b/net/disk_cache/mem_entry_impl.cc
index 8d8bb4c..a9e599c 100644
--- a/net/disk_cache/mem_entry_impl.cc
+++ b/net/disk_cache/mem_entry_impl.cc
@@ -172,8 +172,8 @@ int MemEntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
return net::ERR_INVALID_ARGUMENT;
// We will keep using this buffer and adjust the offset in this buffer.
- scoped_refptr<net::DrainableIOBuffer> io_buf =
- new net::DrainableIOBuffer(buf, buf_len);
+ scoped_refptr<net::DrainableIOBuffer> io_buf(
+ new net::DrainableIOBuffer(buf, buf_len));
// Iterate until we have read enough.
while (io_buf->BytesRemaining()) {
@@ -218,8 +218,8 @@ int MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
if (offset < 0 || buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
- scoped_refptr<net::DrainableIOBuffer> io_buf =
- new net::DrainableIOBuffer(buf, buf_len);
+ scoped_refptr<net::DrainableIOBuffer> io_buf(
+ new net::DrainableIOBuffer(buf, buf_len));
// This loop walks through child entries continuously starting from |offset|
// and writes blocks of data (of maximum size kMaxSparseEntrySize) into each
diff --git a/net/disk_cache/sparse_control.cc b/net/disk_cache/sparse_control.cc
index e94a1bc..32f44ab 100644
--- a/net/disk_cache/sparse_control.cc
+++ b/net/disk_cache/sparse_control.cc
@@ -319,8 +319,8 @@ int SparseControl::CreateSparseEntry() {
children_map_.Resize(kNumSparseBits, true);
// Save the header. The bitmap is saved in the destructor.
- scoped_refptr<net::IOBuffer> buf =
- new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
+ scoped_refptr<net::IOBuffer> buf(
+ new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
int rv = entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL,
false);
@@ -349,8 +349,8 @@ int SparseControl::OpenSparseEntry(int data_len) {
if (map_len > kMaxMapSize || map_len % 4)
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
- scoped_refptr<net::IOBuffer> buf =
- new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
+ scoped_refptr<net::IOBuffer> buf(
+ new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
// Read header.
int rv = entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL);
@@ -402,8 +402,8 @@ bool SparseControl::OpenChild() {
static_cast<int>(sizeof(child_data_)))
return KillChildAndContinue(key, false);
- scoped_refptr<net::WrappedIOBuffer> buf =
- new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
+ scoped_refptr<net::WrappedIOBuffer> buf(
+ new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
// Read signature.
int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL);
@@ -425,8 +425,8 @@ bool SparseControl::OpenChild() {
}
void SparseControl::CloseChild() {
- scoped_refptr<net::WrappedIOBuffer> buf =
- new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
+ scoped_refptr<net::WrappedIOBuffer> buf(
+ new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
// Save the allocation bitmap before closing the child entry.
int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
@@ -492,8 +492,8 @@ void SparseControl::SetChildBit(bool value) {
}
void SparseControl::WriteSparseData() {
- scoped_refptr<net::IOBuffer> buf = new net::WrappedIOBuffer(
- reinterpret_cast<const char*>(children_map_.GetMap()));
+ scoped_refptr<net::IOBuffer> buf(new net::WrappedIOBuffer(
+ reinterpret_cast<const char*>(children_map_.GetMap())));
int len = children_map_.ArraySize() * 4;
int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len,
@@ -597,8 +597,8 @@ void SparseControl::InitChildData() {
memset(&child_data_, 0, sizeof(child_data_));
child_data_.header = sparse_header_;
- scoped_refptr<net::WrappedIOBuffer> buf =
- new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
+ scoped_refptr<net::WrappedIOBuffer> buf(
+ new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
NULL, false);
diff --git a/net/disk_cache/stats_histogram.cc b/net/disk_cache/stats_histogram.cc
index 06ed1b3..366a7e1 100644
--- a/net/disk_cache/stats_histogram.cc
+++ b/net/disk_cache/stats_histogram.cc
@@ -42,7 +42,7 @@ scoped_refptr<StatsHistogram> StatsHistogram::StatsHistogramFactoryGet(
Histogram* temp_histogram = histogram.get();
StatsHistogram* temp_stats_histogram =
static_cast<StatsHistogram*>(temp_histogram);
- scoped_refptr<StatsHistogram> return_histogram = temp_stats_histogram;
+ scoped_refptr<StatsHistogram> return_histogram(temp_stats_histogram);
return return_histogram;
}
@@ -86,4 +86,10 @@ void StatsHistogram::SnapshotSample(SampleSet* sample) const {
mutable_me->ClearFlags(kUmaTargetedHistogramFlag);
}
+Histogram::Inconsistencies StatsHistogram::FindCorruption(
+ const SampleSet& snapshot) const {
+ return NO_INCONSISTENCIES; // This class won't monitor inconsistencies.
+}
+
+
} // namespace disk_cache
diff --git a/net/disk_cache/stats_histogram.h b/net/disk_cache/stats_histogram.h
index cbd8f03..499784c 100644
--- a/net/disk_cache/stats_histogram.h
+++ b/net/disk_cache/stats_histogram.h
@@ -44,6 +44,7 @@ class StatsHistogram : public base::Histogram {
virtual Sample ranges(size_t i) const;
virtual size_t bucket_count() const;
virtual void SnapshotSample(SampleSet* sample) const;
+ virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
private:
bool init_;
diff --git a/net/disk_cache/stress_cache.cc b/net/disk_cache/stress_cache.cc
index 98dcbe1..ae2f981 100644
--- a/net/disk_cache/stress_cache.cc
+++ b/net/disk_cache/stress_cache.cc
@@ -27,7 +27,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
-#include "base/debug_util.h"
+#include "base/debug/debugger.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/message_loop.h"
@@ -130,7 +130,7 @@ void StressTheCache(int iteration) {
}
const int kSize = 4000;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 'k', kSize);
for (int i = 0;; i++) {
@@ -213,7 +213,7 @@ bool StartCrashThread() {
void CrashHandler(const std::string& str) {
g_crashing = true;
- DebugUtil::BreakDebugger();
+ base::debug::BreakDebugger();
}
// -----------------------------------------------------------------------
diff --git a/net/ftp/ftp_ctrl_response_buffer.cc b/net/ftp/ftp_ctrl_response_buffer.cc
index 950e1e0..4aeef1f 100644
--- a/net/ftp/ftp_ctrl_response_buffer.cc
+++ b/net/ftp/ftp_ctrl_response_buffer.cc
@@ -91,7 +91,7 @@ FtpCtrlResponseBuffer::ParsedLine FtpCtrlResponseBuffer::ParseLine(
ParsedLine result;
if (line.length() >= 3) {
- if (base::StringToInt(line.substr(0, 3), &result.status_code))
+ if (base::StringToInt(line.begin(), line.begin() + 3, &result.status_code))
result.has_status_code = (100 <= result.status_code &&
result.status_code <= 599);
if (result.has_status_code && line.length() >= 4 && line[3] == ' ') {
diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc
index 86fc6e7..683e2f7 100644
--- a/net/ftp/ftp_directory_listing_buffer_unittest.cc
+++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc
@@ -41,6 +41,7 @@ TEST(FtpDirectoryListingBufferTest, Parse) {
"dir-listing-ls-16",
"dir-listing-ls-17",
"dir-listing-ls-18",
+ "dir-listing-ls-19",
"dir-listing-mlsd-1",
"dir-listing-mlsd-2",
"dir-listing-netware-1",
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc
index 89fc3d8..40546c8 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -126,8 +126,20 @@ bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
// We may receive file names containing spaces, which can make the number of
// columns arbitrarily large. We will handle that later. For now just make
- // sure we have all the columns that should normally be there.
- if (columns.size() < 7U + column_offset)
+ // sure we have all the columns that should normally be there:
+ //
+ // 1. permission listing
+ // 2. number of links (optional)
+ // 3. owner name
+ // 4. group name (optional)
+ // 5. size in bytes
+ // 6. month
+ // 7. day of month
+ // 8. year or time
+ //
+ // The number of optional columns is stored in |column_offset|
+ // and is between 0 and 2 (inclusive).
+ if (columns.size() < 6U + column_offset)
return false;
if (!LooksLikeUnixPermissionsListing(columns[0]))
@@ -165,6 +177,14 @@ bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
}
entry.name = FtpUtil::GetStringPartAfterColumns(line, 6 + column_offset);
+
+ if (entry.name.empty()) {
+ // Some FTP servers send listing entries with empty names. It's not obvious
+ // how to display such an entry, so we ignore them. We don't want to make
+ // the parsing fail at this point though. Other entries can still be useful.
+ return true;
+ }
+
if (entry.type == FtpDirectoryListingEntry::SYMLINK) {
string16::size_type pos = entry.name.rfind(ASCIIToUTF16(" -> "));
diff --git a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
index 4b36544..3e777cc 100644
--- a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -91,6 +91,28 @@ TEST_F(FtpDirectoryListingParserLsTest, Good) {
}
}
+TEST_F(FtpDirectoryListingParserLsTest, Ignored) {
+ const char* ignored_cases[] = {
+ "drwxr-xr-x 2 0 0 4096 Mar 18 2007 ", // http://crbug.com/60065
+
+ // Tests important for security: verify that after we detect the column
+ // offset we don't try to access invalid memory on malformed input.
+ "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11",
+ "drwxr-xr-x 3 ftp 4096 May 15 18:11",
+ "drwxr-xr-x folder 0 May 15 18:11",
+ };
+ for (size_t i = 0; i < arraysize(ignored_cases); i++) {
+ SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
+ ignored_cases[i]));
+
+ net::FtpDirectoryListingParserLs parser(GetMockCurrentTime());
+ EXPECT_TRUE(parser.ConsumeLine(UTF8ToUTF16(ignored_cases[i])));
+ EXPECT_FALSE(parser.EntryAvailable());
+ EXPECT_TRUE(parser.OnEndOfInput());
+ EXPECT_FALSE(parser.EntryAvailable());
+ }
+}
+
TEST_F(FtpDirectoryListingParserLsTest, Bad) {
const char* bad_cases[] = {
" foo",
@@ -112,12 +134,6 @@ TEST_F(FtpDirectoryListingParserLsTest, Bad) {
"d-wx-wx-wt++ 4 ftp 989 512 Dec 8 15:54 incoming",
"d-wx-wx-wt$ 4 ftp 989 512 Dec 8 15:54 incoming",
"-qqqqqqqqq+ 2 sys 512 Mar 27 2009 pub",
-
- // Tests important for security: verify that after we detect the column
- // offset we don't try to access invalid memory on malformed input.
- "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11",
- "drwxr-xr-x 3 ftp 4096 May 15 18:11",
- "drwxr-xr-x folder 0 May 15 18:11",
};
for (size_t i = 0; i < arraysize(bad_cases); i++) {
net::FtpDirectoryListingParserLs parser(GetMockCurrentTime());
diff --git a/net/ftp/ftp_directory_listing_parser_mlsd.cc b/net/ftp/ftp_directory_listing_parser_mlsd.cc
index fa9a44e..d8ae618 100644
--- a/net/ftp/ftp_directory_listing_parser_mlsd.cc
+++ b/net/ftp/ftp_directory_listing_parser_mlsd.cc
@@ -28,15 +28,23 @@ bool MlsdDateListingToTime(const string16& text, base::Time* time) {
if (text.length() < 14)
return false;
- if (!base::StringToInt(text.substr(0, 4), &time_exploded.year))
+ if (!base::StringToInt(text.begin(), text.begin() + 4, &time_exploded.year))
return false;
- if (!base::StringToInt(text.substr(4, 2), &time_exploded.month))
+ if (!base::StringToInt(text.begin() + 4,
+ text.begin() + 6,
+ &time_exploded.month))
return false;
- if (!base::StringToInt(text.substr(6, 2), &time_exploded.day_of_month))
+ if (!base::StringToInt(text.begin() + 6,
+ text.begin() + 8,
+ &time_exploded.day_of_month))
return false;
- if (!base::StringToInt(text.substr(8, 2), &time_exploded.hour))
+ if (!base::StringToInt(text.begin() + 8,
+ text.begin() + 10,
+ &time_exploded.hour))
return false;
- if (!base::StringToInt(text.substr(10, 2), &time_exploded.minute))
+ if (!base::StringToInt(text.begin() + 10,
+ text.begin() + 12,
+ &time_exploded.minute))
return false;
// We don't know the time zone of the server, so just use local time.
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 02e4be0..bc1c2a9 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -977,8 +977,14 @@ int FtpNetworkTransaction::ProcessResponseSIZE(
return Stop(ERR_INVALID_RESPONSE);
if (size < 0)
return Stop(ERR_INVALID_RESPONSE);
- response_.expected_content_size = size;
- resource_type_ = RESOURCE_TYPE_FILE;
+
+ // Some FTP servers respond with success to the SIZE command
+ // for directories, and return 0 size. Make sure we don't set
+ // the resource type to file if that's the case.
+ if (size > 0) {
+ response_.expected_content_size = size;
+ resource_type_ = RESOURCE_TYPE_FILE;
+ }
break;
case ERROR_CLASS_INFO_NEEDED:
break;
@@ -1298,6 +1304,7 @@ void FtpNetworkTransaction::RecordDataConnectionError(int result) {
type = NET_ERROR_OK;
break;
case ERR_ACCESS_DENIED:
+ case ERR_NETWORK_ACCESS_DENIED:
type = NET_ERROR_ACCESS_DENIED;
break;
case ERR_TIMED_OUT:
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index b504ae8..9c9f62e 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -231,6 +231,27 @@ class FtpSocketDataProviderDirectoryListingWithPasvFallback
FtpSocketDataProviderDirectoryListingWithPasvFallback);
};
+class FtpSocketDataProviderDirectoryListingZeroSize
+ : public FtpSocketDataProviderDirectoryListing {
+ public:
+ FtpSocketDataProviderDirectoryListingZeroSize() {
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, data.length());
+ switch (state()) {
+ case PRE_SIZE:
+ return Verify("SIZE /\r\n", data, PRE_CWD, "213 0\r\n");
+ default:
+ return FtpSocketDataProviderDirectoryListing::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListingZeroSize);
+};
+
class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
public:
FtpSocketDataProviderVMSDirectoryListing() {
@@ -385,6 +406,31 @@ class FtpSocketDataProviderFileDownloadWithPasvFallback
DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithPasvFallback);
};
+class FtpSocketDataProviderFileDownloadZeroSize
+ : public FtpSocketDataProviderFileDownload {
+ public:
+ FtpSocketDataProviderFileDownloadZeroSize() {
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, data.length());
+ switch (state()) {
+ case PRE_SIZE:
+ return Verify("SIZE /file\r\n", data, PRE_CWD,
+ "213 0\r\n");
+ case PRE_CWD:
+ return Verify("CWD /file\r\n", data, PRE_RETR,
+ "550 not a directory\r\n");
+ default:
+ return FtpSocketDataProviderFileDownload::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadZeroSize);
+};
+
class FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider {
public:
FtpSocketDataProviderVMSFileDownload() {
@@ -807,6 +853,12 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcomeShort) {
ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
}
+// Regression test for http://crbug.com/60555.
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionZeroSize) {
+ FtpSocketDataProviderDirectoryListingZeroSize ctrl_socket;
+ ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
+}
+
TEST_F(FtpNetworkTransactionTest, DirectoryTransactionVMS) {
FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
ExecuteTransaction(&ctrl_socket, "ftp://host/dir", OK);
@@ -873,6 +925,11 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionShortReads5) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
}
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionZeroSize) {
+ FtpSocketDataProviderFileDownloadZeroSize ctrl_socket;
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
+}
+
TEST_F(FtpNetworkTransactionTest, DownloadTransactionVMS) {
FtpSocketDataProviderVMSFileDownload ctrl_socket;
ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
diff --git a/net/ftp/ftp_util.cc b/net/ftp/ftp_util.cc
index aeb2355..2633e9d 100644
--- a/net/ftp/ftp_util.cc
+++ b/net/ftp/ftp_util.cc
@@ -162,17 +162,25 @@ bool FtpUtil::LsDateListingToTime(const string16& month, const string16& day,
if (!base::StringToInt(rest, &time_exploded.year)) {
// Maybe it's time. Does it look like time (HH:MM)?
if (rest.length() == 5 && rest[2] == ':') {
- if (!base::StringToInt(rest.substr(0, 2), &time_exploded.hour))
+ if (!base::StringToInt(rest.begin(),
+ rest.begin() + 2,
+ &time_exploded.hour))
return false;
- if (!base::StringToInt(rest.substr(3, 2), &time_exploded.minute))
+ if (!base::StringToInt(rest.begin() + 3,
+ rest.begin() + 5,
+ &time_exploded.minute))
return false;
} else if (rest.length() == 4 && rest[1] == ':') {
// Sometimes it's just H:MM.
- if (!base::StringToInt(rest.substr(0, 1), &time_exploded.hour))
+ if (!base::StringToInt(rest.begin(),
+ rest.begin() + 1,
+ &time_exploded.hour))
return false;
- if (!base::StringToInt(rest.substr(2, 2), &time_exploded.minute))
+ if (!base::StringToInt(rest.begin() + 2,
+ rest.begin() + 4,
+ &time_exploded.minute))
return false;
} else {
return false;
diff --git a/net/http/des.cc b/net/http/des.cc
index a083149..943f612 100644
--- a/net/http/des.cc
+++ b/net/http/des.cc
@@ -84,7 +84,14 @@ void DESMakeKey(const uint8* raw, uint8* key) {
key[7] = DESSetKeyParity((raw[6] << 1));
}
-#if defined(USE_NSS)
+#if defined(USE_OPENSSL)
+
+void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
+ // TODO(joth): When implementing consider splitting up this file by platform.
+ NOTIMPLEMENTED();
+}
+
+#elif defined(USE_NSS)
void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB;
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index 10b2e15..cd1cac8 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -13,8 +13,11 @@
namespace net {
DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo(
- const std::string& hostname, HttpCache* http_cache)
- : callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>(
+ const std::string& hostname,
+ const SSLConfig& ssl_config,
+ HttpCache* http_cache)
+ : SSLHostInfo(hostname, ssl_config),
+ callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>(
ALLOW_THIS_IN_INITIALIZER_LIST(this),
&DiskCacheBasedSSLHostInfo::DoLoop)),
state_(GET_BACKEND),
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index 51a4a91..1d53b90 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -16,8 +16,9 @@
namespace net {
-class IOBuffer;
class HttpCache;
+class IOBuffer;
+struct SSLConfig;
// DiskCacheBasedSSLHostInfo fetches information about an SSL host from our
// standard disk cache. Since the information is defined to be non-sensitive,
@@ -25,7 +26,9 @@ class HttpCache;
class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
public NonThreadSafe {
public:
- DiskCacheBasedSSLHostInfo(const std::string& hostname, HttpCache* http_cache);
+ DiskCacheBasedSSLHostInfo(const std::string& hostname,
+ const SSLConfig& ssl_config,
+ HttpCache* http_cache);
// Implementation of SSLHostInfo
virtual void Start();
diff --git a/net/http/http_auth.h b/net/http/http_auth.h
index 3611612..0034b1f 100644
--- a/net/http/http_auth.h
+++ b/net/http/http_auth.h
@@ -133,7 +133,8 @@ class HttpAuth {
//
// |headers| must be non-NULL and contain the new HTTP response.
//
- // |target| specifies whether the headers came from a server or proxy.
+ // |target| specifies whether the authentication challenge response came
+ // from a server or a proxy.
//
// |disabled_schemes| are the authentication schemes to ignore.
//
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc
index 054357a..35b088f 100644
--- a/net/http/http_auth_handler_basic.cc
+++ b/net/http/http_auth_handler_basic.cc
@@ -41,7 +41,7 @@ bool HttpAuthHandlerBasic::ParseChallenge(
std::string realm;
while (parameters.GetNext()) {
if (LowerCaseEqualsASCII(parameters.name(), "realm"))
- realm = parameters.unquoted_value();
+ realm = parameters.value();
}
if (!parameters.valid())
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc
index f7f178c..82aa9af 100644
--- a/net/http/http_auth_handler_digest.cc
+++ b/net/http/http_auth_handler_digest.cc
@@ -221,7 +221,7 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
while (parameters.GetNext()) {
if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
continue;
- if (LowerCaseEqualsASCII(parameters.unquoted_value(), "true"))
+ if (LowerCaseEqualsASCII(parameters.value(), "true"))
return HttpAuth::AUTHORIZATION_RESULT_STALE;
}
@@ -266,14 +266,9 @@ bool HttpAuthHandlerDigest::ParseChallenge(
// Loop through all the properties.
while (parameters.GetNext()) {
- if (parameters.value().empty()) {
- DVLOG(1) << "Invalid digest property";
- return false;
- }
-
// FAIL -- couldn't parse a property.
if (!ParseChallengeProperty(parameters.name(),
- parameters.unquoted_value()))
+ parameters.value()))
return false;
}
diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc
index 3068135..63ae3b0 100644
--- a/net/http/http_auth_unittest.cc
+++ b/net/http/http_auth_unittest.cc
@@ -149,22 +149,22 @@ TEST(HttpAuthTest, ChooseBestChallenge) {
TEST(HttpAuthTest, HandleChallengeResponse) {
std::string challenge_used;
- const char* kMockChallenge =
+ const char* const kMockChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Mock token_here\n";
- const char* kBasicChallenge =
+ const char* const kBasicChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Basic realm=\"happy\"\n";
- const char* kMissingChallenge =
+ const char* const kMissingChallenge =
"HTTP/1.1 401 Unauthorized\n";
- const char* kEmptyChallenge =
+ const char* const kEmptyChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: \n";
- const char* kBasicAndMockChallenges =
+ const char* const kBasicAndMockChallenges =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Basic realm=\"happy\"\n"
"WWW-Authenticate: Mock token_here\n";
- const char* kTwoMockChallenges =
+ const char* const kTwoMockChallenges =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Mock token_a\n"
"WWW-Authenticate: Mock token_b\n";
@@ -249,9 +249,7 @@ TEST(HttpAuthTest, ChallengeTokenizer) {
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foobar"), parameters.unquoted_value());
- EXPECT_EQ(std::string("\"foobar\""), parameters.value());
- EXPECT_TRUE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("foobar"), parameters.value());
EXPECT_FALSE(parameters.GetNext());
}
@@ -268,8 +266,6 @@ TEST(HttpAuthTest, ChallengeTokenizerNoQuotes) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -286,8 +282,6 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotes) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -304,7 +298,6 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesNoValue) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -322,15 +315,13 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesSpaces) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foo bar"), parameters.value());
- EXPECT_EQ(std::string("foo bar"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
// Use multiple name=value properties with mismatching quote marks in the last
// value.
TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesMultiple) {
- std::string challenge_str = "Digest qop=, algorithm=md5, realm=\"foo";
+ std::string challenge_str = "Digest qop=auth-int, algorithm=md5, realm=\"foo";
HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
challenge_str.end());
HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
@@ -340,20 +331,15 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesMultiple) {
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("auth-int"), parameters.value());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("algorithm"), parameters.name());
EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_EQ(std::string("md5"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foo"), parameters.value());
- EXPECT_EQ(std::string("foo"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -366,12 +352,8 @@ TEST(HttpAuthTest, ChallengeTokenizerNoValue) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("Digest"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
+ EXPECT_FALSE(parameters.valid());
}
// Specify multiple properties, comma separated.
@@ -388,18 +370,16 @@ TEST(HttpAuthTest, ChallengeTokenizerMultiple) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("algorithm"), parameters.name());
EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("Oblivion"), parameters.unquoted_value());
- EXPECT_TRUE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("Oblivion"), parameters.value());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("qop"), parameters.name());
EXPECT_EQ(std::string("auth-int"), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
}
// Use a challenge which has no property.
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index ecd692b..433b08e 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -4,33 +4,48 @@
#include "net/http/http_basic_stream.h"
+#include "base/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_request_info.h"
#include "net/http/http_stream_parser.h"
+#include "net/http/http_util.h"
#include "net/socket/client_socket_handle.h"
namespace net {
-HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection)
+HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
+ bool using_proxy)
: read_buf_(new GrowableIOBuffer()),
- connection_(connection) {
+ connection_(connection),
+ using_proxy_(using_proxy),
+ request_info_(NULL) {
}
int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& net_log,
CompletionCallback* callback) {
+ request_info_ = request_info;
parser_.reset(new HttpStreamParser(connection_.get(), request_info,
read_buf_, net_log));
return OK;
}
-int HttpBasicStream::SendRequest(const std::string& headers,
+int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) {
DCHECK(parser_.get());
- return parser_->SendRequest(headers, request_body, response, callback);
+ const std::string path = using_proxy_ ?
+ HttpUtil::SpecForRequest(request_info_->url) :
+ HttpUtil::PathForRequest(request_info_->url);
+ request_line_ = base::StringPrintf("%s %s HTTP/1.1\r\n",
+ request_info_->method.c_str(),
+ path.c_str()) + headers.ToString();
+
+ return parser_->SendRequest(request_line_, request_body, response, callback);
}
HttpBasicStream::~HttpBasicStream() {}
@@ -60,7 +75,7 @@ HttpStream* HttpBasicStream::RenewStreamForAuth() {
DCHECK(IsResponseBodyComplete());
DCHECK(!IsMoreDataBuffered());
parser_.reset();
- return new HttpBasicStream(connection_.release());
+ return new HttpBasicStream(connection_.release(), using_proxy_);
}
bool HttpBasicStream::IsResponseBodyComplete() const {
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index ffab967..83136c0 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -23,13 +23,14 @@ class ClientSocketHandle;
class GrowableIOBuffer;
class HttpResponseInfo;
struct HttpRequestInfo;
+class HttpRequestHeaders;
class HttpStreamParser;
class IOBuffer;
class UploadDataStream;
class HttpBasicStream : public HttpStream {
public:
- explicit HttpBasicStream(ClientSocketHandle* connection);
+ HttpBasicStream(ClientSocketHandle* connection, bool using_proxy);
virtual ~HttpBasicStream();
// HttpStream methods:
@@ -37,7 +38,7 @@ class HttpBasicStream : public HttpStream {
const BoundNetLog& net_log,
CompletionCallback* callback);
- virtual int SendRequest(const std::string& headers,
+ virtual int SendRequest(const HttpRequestHeaders& headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback);
@@ -76,6 +77,12 @@ class HttpBasicStream : public HttpStream {
scoped_ptr<ClientSocketHandle> connection_;
+ bool using_proxy_;
+
+ std::string request_line_;
+
+ const HttpRequestInfo* request_info_;
+
DISALLOW_COPY_AND_ASSIGN(HttpBasicStream);
};
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index eca95ef..0372222 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -267,8 +267,9 @@ class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
: http_cache_(http_cache) {
}
- SSLHostInfo* GetForHost(const std::string& hostname) {
- return new DiskCacheBasedSSLHostInfo(hostname, http_cache_);
+ SSLHostInfo* GetForHost(const std::string& hostname,
+ const SSLConfig& ssl_config) {
+ return new DiskCacheBasedSSLHostInfo(hostname, ssl_config, http_cache_);
}
private:
@@ -601,11 +602,10 @@ HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
}
HttpCache::ActiveEntry* HttpCache::ActivateEntry(
- const std::string& key,
disk_cache::Entry* disk_entry) {
- DCHECK(!FindActiveEntry(key));
+ DCHECK(!FindActiveEntry(disk_entry->GetKey()));
ActiveEntry* entry = new ActiveEntry(disk_entry);
- active_entries_[key] = entry;
+ active_entries_[disk_entry->GetKey()] = entry;
return entry;
}
@@ -990,7 +990,7 @@ void HttpCache::OnIOComplete(int result, PendingOp* pending_op) {
fail_requests = true;
} else if (item->IsValid()) {
key = pending_op->disk_entry->GetKey();
- entry = ActivateEntry(key, pending_op->disk_entry);
+ entry = ActivateEntry(pending_op->disk_entry);
} else {
// The writer transaction is gone.
if (op == WI_CREATE_ENTRY)
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 255d7b6..0ce22e5 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -257,10 +257,8 @@ class HttpCache : public HttpTransactionFactory,
ActiveEntry* FindActiveEntry(const std::string& key);
// Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
- // cache entry that corresponds to the desired |key|.
- // TODO(rvargas): remove the |key| argument.
- ActiveEntry* ActivateEntry(const std::string& key,
- disk_cache::Entry* disk_entry);
+ // cache entry.
+ ActiveEntry* ActivateEntry(disk_cache::Entry* disk_entry);
// Deletes an ActiveEntry.
void DeactivateEntry(ActiveEntry* entry);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 58288f4..873ccf4 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -1801,7 +1801,7 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
DCHECK_EQ(200, response_.headers->response_code());
}
- scoped_refptr<PickledIOBuffer> data = new PickledIOBuffer();
+ scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
response_.Persist(data->pickle(), skip_transient_headers, truncated);
data->Done();
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index eec8098..f71cec9 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -573,7 +573,7 @@ class MockHttpCache {
int size = disk_entry->GetDataSize(0);
TestCompletionCallback cb;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size));
int rv = disk_entry->ReadData(0, 0, buffer, size, &cb);
rv = cb.GetResult(rv);
EXPECT_EQ(size, rv);
@@ -593,8 +593,8 @@ class MockHttpCache {
&pickle, skip_transient_headers, response_truncated);
TestCompletionCallback cb;
- scoped_refptr<net::WrappedIOBuffer> data = new net::WrappedIOBuffer(
- reinterpret_cast<const char*>(pickle.data()));
+ scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer(
+ reinterpret_cast<const char*>(pickle.data())));
int len = static_cast<int>(pickle.size());
int rv = disk_entry->WriteData(0, 0, data, len, &cb, true);
@@ -951,8 +951,8 @@ const MockTransaction kRangeGET_TransactionOK = {
void Verify206Response(std::string response, int start, int end) {
std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
response.size()));
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders(raw_headers);
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(raw_headers));
ASSERT_EQ(206, headers->response_code());
@@ -1854,7 +1854,7 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
rv = callback.WaitForResult();
ASSERT_EQ(net::OK, rv);
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(256);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
rv = trans->Read(buf, 256, &callback);
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -3544,7 +3544,7 @@ TEST(HttpCache, RangeGET_Cancel) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -3585,7 +3585,7 @@ TEST(HttpCache, RangeGET_Cancel2) {
// Make sure that we revalidate the entry and read from the cache (a single
// read will return while waiting for the network).
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(5);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
rv = c->trans->Read(buf, buf->size(), &c->callback);
EXPECT_EQ(5, c->callback.GetResult(rv));
rv = c->trans->Read(buf, buf->size(), &c->callback);
@@ -3631,7 +3631,7 @@ TEST(HttpCache, RangeGET_Cancel3) {
// Make sure that we revalidate the entry and read from the cache (a single
// read will return while waiting for the network).
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(5);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
rv = c->trans->Read(buf, buf->size(), &c->callback);
EXPECT_EQ(5, c->callback.GetResult(rv));
rv = c->trans->Read(buf, buf->size(), &c->callback);
@@ -4029,7 +4029,7 @@ TEST(HttpCache, DoomOnDestruction2) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -4073,7 +4073,7 @@ TEST(HttpCache, DoomOnDestruction3) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -4117,7 +4117,7 @@ TEST(HttpCache, Set_Truncated_Flag) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
diff --git a/net/http/http_chunked_decoder.cc b/net/http/http_chunked_decoder.cc
index 455c9ed..d5b16dd 100644
--- a/net/http/http_chunked_decoder.cc
+++ b/net/http/http_chunked_decoder.cc
@@ -192,7 +192,7 @@ bool HttpChunkedDecoder::ParseChunkSize(const char* start, int len, int* out) {
return false;
int parsed_number;
- bool ok = base::HexStringToInt(std::string(start, len), &parsed_number);
+ bool ok = base::HexStringToInt(start, start + len, &parsed_number);
if (ok && parsed_number >= 0) {
*out = parsed_number;
return true;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index e0b9c39..bc2d322 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -89,6 +89,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
request_(NULL),
headers_valid_(false),
logged_response_time_(false),
+ request_headers_(),
read_buf_len_(0),
next_state_(STATE_NONE),
establishing_tunnel_(false) {
@@ -284,7 +285,7 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
State next_state = STATE_NONE;
- scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
+ scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
if (headers_valid_ && headers.get() && stream_request_.get()) {
// We're trying to read the body of the response but we're still trying
// to establish an SSL tunnel through the proxy. We can't read these
@@ -535,6 +536,8 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
if (result == OK) {
next_state_ = STATE_INIT_STREAM;
DCHECK(stream_.get());
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ result = HandleCertificateRequest(result);
}
// At this point we are done with the stream_request_.
@@ -552,9 +555,6 @@ int HttpNetworkTransaction::DoInitStreamComplete(int result) {
if (result == OK) {
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
} else {
- if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
- result = HandleCertificateRequest(result);
-
if (result < 0)
result = HandleIOError(result);
@@ -624,38 +624,22 @@ int HttpNetworkTransaction::DoSendRequest() {
// This is constructed lazily (instead of within our Start method), so that
// we have proxy info available.
- if (request_headers_.empty() && !response_.was_fetched_via_spdy) {
+ if (request_headers_.IsEmpty()) {
bool using_proxy = (proxy_info_.is_http()|| proxy_info_.is_https()) &&
!is_https_request();
- const std::string path = using_proxy ?
- HttpUtil::SpecForRequest(request_->url) :
- HttpUtil::PathForRequest(request_->url);
- std::string request_line = base::StringPrintf(
- "%s %s HTTP/1.1\r\n", request_->method.c_str(), path.c_str());
-
- HttpRequestHeaders request_headers;
HttpUtil::BuildRequestHeaders(request_, request_body, auth_controllers_,
ShouldApplyServerAuth(),
ShouldApplyProxyAuth(), using_proxy,
- &request_headers);
+ &request_headers_);
if (session_->network_delegate())
- session_->network_delegate()->OnSendHttpRequest(&request_headers);
-
- if (net_log_.IsLoggingAllEvents()) {
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
- new NetLogHttpRequestParameter(request_line, request_headers));
- }
-
- request_headers_ = request_line + request_headers.ToString();
- } else {
- if (net_log_.IsLoggingAllEvents()) {
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
- new NetLogHttpRequestParameter(request_->url.spec(),
- request_->extra_headers));
- }
+ session_->network_delegate()->OnSendHttpRequest(&request_headers_);
+ }
+ if (net_log_.IsLoggingAllEvents()) {
+ net_log_.AddEvent(
+ NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
+ make_scoped_refptr(new NetLogHttpRequestParameter(
+ request_->url.spec(), request_->extra_headers)));
}
headers_valid_ = false;
@@ -748,7 +732,7 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
- new NetLogHttpResponseParameter(response_.headers));
+ make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
@@ -1050,7 +1034,7 @@ void HttpNetworkTransaction::ResetStateForAuthRestart() {
read_buf_ = NULL;
read_buf_len_ = 0;
headers_valid_ = false;
- request_headers_.clear();
+ request_headers_.Clear();
response_ = HttpResponseInfo();
establishing_tunnel_ = false;
}
@@ -1080,7 +1064,7 @@ void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
// We need to clear request_headers_ because it contains the real request
// headers, but we may need to resend the CONNECT request first to recreate
// the SSL tunnel.
- request_headers_.clear();
+ request_headers_.Clear();
next_state_ = STATE_CREATE_STREAM; // Resend the request.
}
@@ -1094,7 +1078,7 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
}
int HttpNetworkTransaction::HandleAuthChallenge() {
- scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
+ scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
DCHECK(headers);
int status = headers->response_code();
@@ -1105,6 +1089,11 @@ int HttpNetworkTransaction::HandleAuthChallenge() {
if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
return ERR_UNEXPECTED_PROXY_AUTH;
+ // This case can trigger when an HTTPS server responds with a 407 status
+ // code through a non-authenticating proxy.
+ if (!auth_controllers_[target].get())
+ return ERR_UNEXPECTED_PROXY_AUTH;
+
int rv = auth_controllers_[target]->HandleAuthChallenge(
headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
net_log_);
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index ce0c5bd..255fcdf 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -17,6 +17,7 @@
#include "net/base/request_priority.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_transaction.h"
#include "net/http/stream_factory.h"
@@ -222,7 +223,7 @@ class HttpNetworkTransaction : public HttpTransaction,
SSLConfig ssl_config_;
- std::string request_headers_;
+ HttpRequestHeaders request_headers_;
// The size in bytes of the buffer we use to drain the response body that
// we want to throw away. The response body is typically a small error
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 2066264..b060d7c 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -460,6 +460,67 @@ TEST_F(HttpNetworkTransactionTest,
}
TEST_F(HttpNetworkTransactionTest,
+ DuplicateContentLengthHeadersNoTransferEncoding) {
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Length: 5\r\n"),
+ MockRead("Content-Length: 5\r\n\r\n"),
+ MockRead("Hello"),
+ };
+ SimpleGetHelperResult out = SimpleGetHelper(data_reads,
+ arraysize(data_reads));
+ EXPECT_EQ(OK, out.rv);
+ EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
+ EXPECT_EQ("Hello", out.response_data);
+}
+
+TEST_F(HttpNetworkTransactionTest,
+ ComplexContentLengthHeadersNoTransferEncoding) {
+ // More than 2 dupes.
+ {
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Length: 5\r\n"),
+ MockRead("Content-Length: 5\r\n"),
+ MockRead("Content-Length: 5\r\n\r\n"),
+ MockRead("Hello"),
+ };
+ SimpleGetHelperResult out = SimpleGetHelper(data_reads,
+ arraysize(data_reads));
+ EXPECT_EQ(OK, out.rv);
+ EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
+ EXPECT_EQ("Hello", out.response_data);
+ }
+ // HTTP/1.0
+ {
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 OK\r\n"),
+ MockRead("Content-Length: 5\r\n"),
+ MockRead("Content-Length: 5\r\n"),
+ MockRead("Content-Length: 5\r\n\r\n"),
+ MockRead("Hello"),
+ };
+ SimpleGetHelperResult out = SimpleGetHelper(data_reads,
+ arraysize(data_reads));
+ EXPECT_EQ(OK, out.rv);
+ EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
+ EXPECT_EQ("Hello", out.response_data);
+ }
+ // 2 dupes and one mismatched.
+ {
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Length: 10\r\n"),
+ MockRead("Content-Length: 10\r\n"),
+ MockRead("Content-Length: 5\r\n\r\n"),
+ };
+ SimpleGetHelperResult out = SimpleGetHelper(data_reads,
+ arraysize(data_reads));
+ EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
+ }
+}
+
+TEST_F(HttpNetworkTransactionTest,
MultipleContentLengthHeadersTransferEncoding) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -544,7 +605,7 @@ TEST_F(HttpNetworkTransactionTest, Head) {
TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
@@ -733,7 +794,7 @@ TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
const MockRead& read_failure) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -850,7 +911,7 @@ TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
// reading the body.
TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -1707,6 +1768,66 @@ TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
}
+// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
+// through a non-authenticating proxy. The request should fail with
+// ERR_UNEXPECTED_PROXY_AUTH.
+// Note that it is impossible to detect if an HTTP server returns a 407 through
+// a non-authenticating proxy - there is nothing to indicate whether the
+// response came from the proxy or the server, so it is treated as if the proxy
+// issued the challenge.
+TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
+ SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+
+ // Since we have proxy, should try to establish tunnel.
+ MockWrite data_writes1[] = {
+ MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead data_reads1[] = {
+ MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
+
+ MockRead("HTTP/1.1 407 Unauthorized\r\n"),
+ MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
+ MockRead("\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
+ data_writes1, arraysize(data_writes1));
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+ SSLSocketDataProvider ssl(true, OK);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback1;
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
+ int rv = trans->Start(&request, &callback1, log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
+ size_t pos = ExpectLogContainsSomewhere(
+ log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ NetLog::PHASE_NONE);
+ ExpectLogContainsSomewhere(
+ log.entries(), pos,
+ NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
+ NetLog::PHASE_NONE);
+}
// Test a simple get through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
@@ -3189,7 +3310,7 @@ TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
request[1].load_flags = 0;
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
// The first socket is used for transaction 1 and the first attempt of
// transaction 2.
@@ -3457,7 +3578,7 @@ TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
// Test that previously tried username/passwords for a realm get re-used.
TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
// Transaction 1: authenticate (foo, bar) on MyRealm1
{
@@ -3850,7 +3971,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// are started with the same nonce.
TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpAuthHandlerDigest::SetFixedCnonce(true);
// Transaction 1: authenticate (foo, bar) on MyRealm1
@@ -3991,7 +4112,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
// Setup some state (which we expect ResetStateForRestart() will clear).
trans->read_buf_ = new IOBuffer(15);
trans->read_buf_len_ = 15;
- trans->request_headers_ = "Authorization: NTLM";
+ trans->request_headers_.SetHeader("Authorization", "NTLM");
// Setup state in response_
HttpResponseInfo* response = &trans->response_;
@@ -4004,7 +4125,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
HttpRequestInfo request;
std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
std::replace(temp.begin(), temp.end(), '\n', '\0');
- scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
+ scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
request.extra_headers.SetHeader("Foo", "1");
request.extra_headers.SetHeader("bar", "23");
EXPECT_TRUE(response->vary_data.Init(request, *headers));
@@ -4016,7 +4137,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
// Verify that the state that needed to be reset, has been reset.
EXPECT_TRUE(trans->read_buf_.get() == NULL);
EXPECT_EQ(0, trans->read_buf_len_);
- EXPECT_EQ(0U, trans->request_headers_.size());
+ EXPECT_TRUE(trans->request_headers_.IsEmpty());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_TRUE(response->headers.get() == NULL);
EXPECT_FALSE(response->was_cached);
@@ -5317,7 +5438,7 @@ TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
// Make sure we can handle an error when writing the request.
TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -5346,7 +5467,7 @@ TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
// Check that a connection closed after the start of the headers finishes ok.
TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -5388,7 +5509,7 @@ TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
// restart does the right thing.
TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -6412,8 +6533,8 @@ TEST_F(HttpNetworkTransactionTest,
scoped_refptr<SpdySession> spdy_session =
session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
BoundNetLog());
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
EXPECT_EQ(ERR_IO_PENDING,
@@ -6887,7 +7008,7 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
origin, BoundNetLog());
auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
int rv = OK;
@@ -7588,8 +7709,8 @@ TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
scoped_refptr<SpdySession> spdy_session =
session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
BoundNetLog());
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
TestCompletionCallback callback;
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index b5ede3d..186b459 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -185,6 +185,14 @@ bool HttpProxyClientSocket::WasEverUsed() const {
return false;
}
+bool HttpProxyClientSocket::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(!user_callback_);
@@ -335,8 +343,8 @@ int HttpProxyClientSocket::DoSendRequest() {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
- new NetLogHttpRequestParameter(
- request_line, request_headers));
+ make_scoped_refptr(new NetLogHttpRequestParameter(
+ request_line, request_headers)));
}
request_headers_ = request_line + request_headers.ToString();
}
@@ -373,7 +381,7 @@ int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
- new NetLogHttpResponseParameter(response_.headers));
+ make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
switch (response_.headers->response_code()) {
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index 6530285..b42c78b 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -78,6 +78,7 @@ class HttpProxyClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index e1ca2fe..ae84ecc 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -244,7 +244,8 @@ TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
CreateMockWrite(*rst, 2, true),
};
scoped_ptr<spdy::SpdyFrame> resp(
- ConstructSpdySynReplyError("407 Proxy Authentication Required", 1));
+ ConstructSpdySynReplyError(
+ "407 Proxy Authentication Required", NULL, 0, 1));
MockRead spdy_reads[] = {
CreateMockWrite(*resp, 1, true),
MockRead(true, 0, 3)
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index d57952d..d8c9bb7 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -78,7 +78,7 @@ class MockHttpStream : public HttpStream {
CompletionCallback* callback) {
return ERR_UNEXPECTED;
}
- virtual int SendRequest(const std::string& request_headers,
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) {
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index 99c5404..c2d098c 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -484,7 +484,7 @@ bool HttpResponseHeaders::HasHeaderValue(const std::string& name,
while (EnumerateHeader(&iter, name, &temp)) {
if (value.size() == temp.size() &&
std::equal(temp.begin(), temp.end(), value.begin(),
- CaseInsensitiveCompare<char>()))
+ base::CaseInsensitiveCompare<char>()))
return true;
}
return false;
@@ -598,7 +598,7 @@ void HttpResponseHeaders::ParseStatusLine(
raw_headers_.push_back(' ');
raw_headers_.append(code, p);
raw_headers_.push_back(' ');
- base::StringToInt(std::string(code, p), &response_code_);
+ base::StringToInt(code, p, &response_code_);
// Skip whitespace.
while (*p == ' ')
@@ -629,7 +629,7 @@ size_t HttpResponseHeaders::FindHeader(size_t from,
const std::string::const_iterator& name_end = parsed_[i].name_end;
if (static_cast<size_t>(name_end - name_begin) == search.size() &&
std::equal(name_begin, name_end, search.begin(),
- CaseInsensitiveCompare<char>()))
+ base::CaseInsensitiveCompare<char>()))
return i;
}
@@ -973,7 +973,9 @@ bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
value.begin() + kMaxAgePrefixLen,
kMaxAgePrefix)) {
int64 seconds;
- base::StringToInt64(value.substr(kMaxAgePrefixLen), &seconds);
+ base::StringToInt64(value.begin() + kMaxAgePrefixLen,
+ value.end(),
+ &seconds);
*result = TimeDelta::FromSeconds(seconds);
return true;
}
@@ -1148,9 +1150,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
byte_range_resp_spec.begin() + minus_position;
HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end);
- bool ok = base::StringToInt64(
- std::string(first_byte_pos_begin, first_byte_pos_end),
- first_byte_position);
+ bool ok = base::StringToInt64(first_byte_pos_begin,
+ first_byte_pos_end,
+ first_byte_position);
// Obtain last-byte-pos.
std::string::const_iterator last_byte_pos_begin =
@@ -1159,9 +1161,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
byte_range_resp_spec.end();
HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end);
- ok &= base::StringToInt64(
- std::string(last_byte_pos_begin, last_byte_pos_end),
- last_byte_position);
+ ok &= base::StringToInt64(last_byte_pos_begin,
+ last_byte_pos_end,
+ last_byte_position);
if (!ok) {
*first_byte_position = *last_byte_position = -1;
return false;
@@ -1184,9 +1186,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) {
return false;
- } else if (!base::StringToInt64(
- std::string(instance_length_begin, instance_length_end),
- instance_length)) {
+ } else if (!base::StringToInt64(instance_length_begin,
+ instance_length_end,
+ instance_length)) {
*instance_length = -1;
return false;
}
diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc
index 18cd1c4..6986723 100644
--- a/net/http/http_response_headers_unittest.cc
+++ b/net/http/http_response_headers_unittest.cc
@@ -51,8 +51,8 @@ void TestCommon(const TestData& test) {
string expected_headers(test.expected_headers);
string headers;
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(raw_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(raw_headers));
parsed->GetNormalizedHeaders(&headers);
// Transform to readable output format (so it's easier to see diffs).
@@ -281,7 +281,7 @@ TEST(HttpResponseHeadersTest, GetNormalizedHeader) {
"Cache-control: private\n"
"cache-Control: no-store\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
std::string value;
EXPECT_TRUE(parsed->GetNormalizedHeader("cache-control", &value));
@@ -448,15 +448,15 @@ TEST(HttpResponseHeadersTest, Persist) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
std::string headers = tests[i].raw_headers;
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed1 =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed1(
+ new HttpResponseHeaders(headers));
Pickle pickle;
parsed1->Persist(&pickle, tests[i].options);
void* iter = NULL;
- scoped_refptr<HttpResponseHeaders> parsed2 =
- new HttpResponseHeaders(pickle, &iter);
+ scoped_refptr<HttpResponseHeaders> parsed2(
+ new HttpResponseHeaders(pickle, &iter));
std::string h2;
parsed2->GetNormalizedHeaders(&h2);
@@ -472,7 +472,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Coalesced) {
"Cache-control:private , no-cache=\"set-cookie,server\" \n"
"cache-Control: no-store\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
void* iter = NULL;
std::string value;
@@ -493,7 +493,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Challenge) {
"WWW-Authenticate:Digest realm=foobar, nonce=x, domain=y\n"
"WWW-Authenticate:Basic realm=quatar\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
void* iter = NULL;
std::string value;
@@ -512,7 +512,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_DateValued) {
"Date: Tue, 07 Aug 2007 23:10:55 GMT\n"
"Last-Modified: Wed, 01 Aug 2007 23:23:45 GMT\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
std::string value;
EXPECT_TRUE(parsed->EnumerateHeader(NULL, "date", &value));
@@ -656,8 +656,8 @@ TEST(HttpResponseHeadersTest, GetMimeType) {
for (size_t i = 0; i < arraysize(tests); ++i) {
string headers(tests[i].raw_headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
std::string value;
EXPECT_EQ(tests[i].has_mimetype, parsed->GetMimeType(&value));
@@ -807,8 +807,8 @@ TEST(HttpResponseHeadersTest, RequiresValidation) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
bool requires_validation =
parsed->RequiresValidation(request_time, response_time, current_time);
@@ -871,13 +871,13 @@ TEST(HttpResponseHeadersTest, Update) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string new_headers(tests[i].new_headers);
HeadersToRaw(&new_headers);
- scoped_refptr<HttpResponseHeaders> new_parsed =
- new HttpResponseHeaders(new_headers);
+ scoped_refptr<HttpResponseHeaders> new_parsed(
+ new HttpResponseHeaders(new_headers));
parsed->Update(*new_parsed);
@@ -917,8 +917,8 @@ TEST(HttpResponseHeadersTest, EnumerateHeaderLines) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
string name, value, lines;
@@ -1001,8 +1001,8 @@ TEST(HttpResponseHeadersTest, IsRedirect) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
std::string location;
EXPECT_EQ(parsed->IsRedirect(&location), tests[i].is_redirect);
@@ -1087,8 +1087,8 @@ TEST(HttpResponseHeadersTest, GetContentLength) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_len, parsed->GetContentLength());
}
@@ -1338,8 +1338,8 @@ TEST(HttpResponseHeaders, GetContentRange) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
int64 first_byte_position;
int64 last_byte_position;
@@ -1420,8 +1420,8 @@ TEST(HttpResponseHeadersTest, IsKeepAlive) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_keep_alive, parsed->IsKeepAlive());
}
@@ -1473,8 +1473,8 @@ TEST(HttpResponseHeadersTest, HasStrongValidators) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_result, parsed->HasStrongValidators()) <<
"Failed test case " << i;
@@ -1484,14 +1484,14 @@ TEST(HttpResponseHeadersTest, HasStrongValidators) {
TEST(HttpResponseHeadersTest, GetStatusText) {
std::string headers("HTTP/1.1 404 Not Found");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText());
}
TEST(HttpResponseHeadersTest, GetStatusTextMissing) {
std::string headers("HTTP/1.1 404");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
// Since the status line gets normalized, we have OK
EXPECT_EQ(std::string("OK"), parsed->GetStatusText());
}
@@ -1499,14 +1499,14 @@ TEST(HttpResponseHeadersTest, GetStatusTextMissing) {
TEST(HttpResponseHeadersTest, GetStatusTextMultiSpace) {
std::string headers("HTTP/1.0 404 Not Found");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText());
}
TEST(HttpResponseHeadersTest, GetStatusBadStatusLine) {
std::string headers("Foo bar.");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
// The bad status line would have gotten rewritten as
// HTTP/1.0 200 OK.
EXPECT_EQ(std::string("OK"), parsed->GetStatusText());
@@ -1545,8 +1545,8 @@ TEST(HttpResponseHeadersTest, AddHeader) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string new_header(tests[i].new_header);
parsed->AddHeader(new_header);
@@ -1590,8 +1590,8 @@ TEST(HttpResponseHeadersTest, RemoveHeader) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string name(tests[i].to_remove);
parsed->RemoveHeader(name);
@@ -1645,8 +1645,8 @@ TEST(HttpResponseHeadersTest, ReplaceStatus) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string name(tests[i].new_status);
parsed->ReplaceStatusLine(name);
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index dc90d1f..00bfb92 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -182,6 +182,7 @@ void HttpResponseInfo::Persist(Pickle* pickle,
}
if (ssl_info.security_bits != -1)
flags |= RESPONSE_INFO_HAS_SECURITY_BITS;
+ // TODO(wtc): we should persist ssl_info.connection_status.
if (vary_data.is_valid())
flags |= RESPONSE_INFO_HAS_VARY_DATA;
if (response_truncated)
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index 5aa84e0..16f84cc 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -22,12 +22,13 @@
namespace net {
class BoundNetLog;
+class HttpRequestHeaders;
+struct HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
class SSLCertRequestInfo;
class SSLInfo;
class UploadDataStream;
-struct HttpRequestInfo;
class HttpStream {
public:
@@ -45,7 +46,7 @@ class HttpStream {
// synchronously, in which case the result will be passed to the callback
// when available. Returns OK on success. The HttpStream takes ownership
// of the request_body.
- virtual int SendRequest(const std::string& request_headers,
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) = 0;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 0e7610c..d3e4abd 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -53,7 +53,7 @@ int HttpStreamParser::SendRequest(const std::string& headers,
DCHECK(response);
response_ = response;
- scoped_refptr<StringIOBuffer> headers_io_buf = new StringIOBuffer(headers);
+ scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(headers));
request_headers_ = new DrainableIOBuffer(headers_io_buf,
headers_io_buf->size());
request_body_.reset(request_body);
@@ -510,13 +510,20 @@ int HttpStreamParser::DoParseResponseHeaders(int end_offset) {
void* it = NULL;
const std::string content_length_header("Content-Length");
- std::string ignored_header_value;
+ std::string content_length_value;
if (!headers->HasHeader("Transfer-Encoding") &&
headers->EnumerateHeader(
- &it, content_length_header, &ignored_header_value) &&
- headers->EnumerateHeader(
- &it, content_length_header, &ignored_header_value)) {
- return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
+ &it, content_length_header, &content_length_value)) {
+ // Ok, there's no Transfer-Encoding header and there's at least one
+ // Content-Length header. Check if there are any more Content-Length
+ // headers, and if so, make sure they have the same value. Otherwise, it's
+ // a possible response smuggling attack.
+ std::string content_length_value2;
+ while (headers->EnumerateHeader(
+ &it, content_length_header, &content_length_value2)) {
+ if (content_length_value != content_length_value2)
+ return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
+ }
}
response_->headers = headers;
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 2409d86..71bbdda 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -21,7 +21,6 @@
#include "net/socket/client_socket_pool.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
-#include "net/socket/ssl_client_socket.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/tcp_client_socket_pool.h"
#include "net/spdy/spdy_http_stream.h"
@@ -481,9 +480,9 @@ int HttpStreamRequest::DoInitConnection() {
} else {
ProxyServer proxy_server = proxy_info()->proxy_server();
proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair()));
- scoped_refptr<TCPSocketParams> proxy_tcp_params =
+ scoped_refptr<TCPSocketParams> proxy_tcp_params(
new TCPSocketParams(*proxy_host_port, request_info().priority,
- request_info().referrer, disable_resolver_cache);
+ request_info().referrer, disable_resolver_cache));
if (proxy_info()->is_http() || proxy_info()->is_https()) {
GURL authentication_url = request_info().url;
@@ -727,8 +726,12 @@ int HttpStreamRequest::DoCreateStream() {
if (connection_->socket() && !connection_->is_reused())
SetSocketMotivation();
+ const ProxyServer& proxy_server = proxy_info()->proxy_server();
+
if (!using_spdy_) {
- stream_.reset(new HttpBasicStream(connection_.release()));
+ bool using_proxy = (proxy_info()->is_http() || proxy_info()->is_https()) &&
+ request_info().url.SchemeIs("http");
+ stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
return OK;
}
@@ -738,7 +741,6 @@ int HttpStreamRequest::DoCreateStream() {
SpdySessionPool* spdy_pool = session_->spdy_session_pool();
scoped_refptr<SpdySession> spdy_session;
- const ProxyServer& proxy_server = proxy_info()->proxy_server();
HostPortProxyPair pair(endpoint_, proxy_server);
if (spdy_pool->HasSession(pair)) {
// We have a SPDY session to the origin server. This might be a direct
@@ -850,17 +852,17 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSslParams(
if (request_info().load_flags & LOAD_VERIFY_EV_CERT)
ssl_config()->verify_ev_cert = true;
- if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
- proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
- ssl_config()->mitm_proxies_allowed = true;
- }
+ if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
+ proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
+ ssl_config()->mitm_proxies_allowed = true;
+ }
- scoped_refptr<SSLSocketParams> ssl_params =
+ scoped_refptr<SSLSocketParams> ssl_params(
new SSLSocketParams(tcp_params, socks_params, http_proxy_params,
proxy_scheme, hostname,
*ssl_config(), load_flags,
force_spdy_always_ && force_spdy_over_ssl_,
- want_spdy_over_npn);
+ want_spdy_over_npn));
return ssl_params;
}
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index 4d9daa5..518c1f8 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -147,7 +147,7 @@ int ReadTransaction(net::HttpTransaction* trans, std::string* result) {
std::string content;
do {
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(256);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
rv = trans->Read(buf, 256, &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 5c7a4fc..a3d1ec5 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -292,7 +292,7 @@ bool HttpUtil::HasHeader(const std::string& headers, const char* name) {
headers.end(),
name,
name + name_len,
- CaseInsensitiveCompareASCII<char>());
+ base::CaseInsensitiveCompareASCII<char>());
if (it == headers.end())
return false;
@@ -828,12 +828,12 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
// Scan for the equals sign.
std::string::const_iterator equals = std::find(value_begin_, value_end_, '=');
if (equals == value_end_ || equals == value_begin_)
- return valid_ = false; // Malformed
+ return valid_ = false; // Malformed, no equals sign
// Verify that the equals sign we found wasn't inside of quote marks.
for (std::string::const_iterator it = value_begin_; it != equals; ++it) {
if (HttpUtil::IsQuote(*it))
- return valid_ = false; // Malformed
+ return valid_ = false; // Malformed, quote appears before equals sign
}
name_begin_ = value_begin_;
@@ -843,25 +843,28 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
TrimLWS(&name_begin_, &name_end_);
TrimLWS(&value_begin_, &value_end_);
value_is_quoted_ = false;
- if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) {
+ unquoted_value_.clear();
+
+ if (value_begin_ == value_end_)
+ return valid_ = false; // Malformed, value is empty
+
+ if (HttpUtil::IsQuote(*value_begin_)) {
// Trim surrounding quotemarks off the value
- if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_)
+ if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) {
// NOTE: This is not as graceful as it sounds:
// * quoted-pairs will no longer be unquoted
// (["\"hello] should give ["hello]).
// * Does not detect when the final quote is escaped
// (["value\"] should give [value"])
++value_begin_; // Gracefully recover from mismatching quotes.
- else
+ } else {
value_is_quoted_ = true;
+ // Do not store iterators into this. See declaration of unquoted_value_.
+ unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
+ }
}
return true;
}
-// If value() has quotemarks, unquote it.
-std::string HttpUtil::NameValuePairsIterator::unquoted_value() const {
- return HttpUtil::Unquote(value_begin_, value_end_);
-}
-
} // namespace net
diff --git a/net/http/http_util.h b/net/http/http_util.h
index f41c4e4..2f5bd85 100644
--- a/net/http/http_util.h
+++ b/net/http/http_util.h
@@ -275,6 +275,9 @@ class HttpUtil {
// Each pair consists of a token (the name), an equals sign, and either a
// token or quoted-string (the value). Arbitrary HTTP LWS is permitted outside
// of and between names, values, and delimiters.
+ //
+ // String iterators returned from this class' methods may be invalidated upon
+ // calls to GetNext() or after the NameValuePairsIterator is destroyed.
class NameValuePairsIterator {
public:
NameValuePairsIterator(std::string::const_iterator begin,
@@ -295,15 +298,16 @@ class HttpUtil {
std::string name() const { return std::string(name_begin_, name_end_); }
// The value of the current name-value pair.
- std::string::const_iterator value_begin() const { return value_begin_; }
- std::string::const_iterator value_end() const { return value_end_; }
- std::string value() const { return std::string(value_begin_, value_end_); }
-
- // If value() has quotemarks, unquote it.
- std::string unquoted_value() const;
-
- // True if the name-value pair's value has quote marks.
- bool value_is_quoted() const { return value_is_quoted_; }
+ std::string::const_iterator value_begin() const {
+ return value_is_quoted_ ? unquoted_value_.begin() : value_begin_;
+ }
+ std::string::const_iterator value_end() const {
+ return value_is_quoted_ ? unquoted_value_.end() : value_end_;
+ }
+ std::string value() const {
+ return value_is_quoted_ ? unquoted_value_ : std::string(value_begin_,
+ value_end_);
+ }
private:
HttpUtil::ValuesIterator props_;
@@ -318,6 +322,11 @@ class HttpUtil {
std::string::const_iterator value_begin_;
std::string::const_iterator value_end_;
+ // Do not store iterators into this string. The NameValuePairsIterator
+ // is copyable/assignable, and if copied the copy's iterators would point
+ // into the original's unquoted_value_ member.
+ std::string unquoted_value_;
+
bool value_is_quoted_;
};
};
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index 4ebbd2e..47242d2 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -673,27 +673,48 @@ TEST(HttpUtilTest, ParseRanges) {
}
namespace {
-
-void CheckNameValuePair(HttpUtil::NameValuePairsIterator* parser,
- bool expect_next,
- bool expect_valid,
- std::string expected_name,
- std::string expected_value,
- std::string expected_unquoted_value) {
- ASSERT_EQ(expect_next, parser->GetNext());
+void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator* parser,
+ bool expect_valid,
+ std::string expected_name,
+ std::string expected_value) {
ASSERT_EQ(expect_valid, parser->valid());
- if (!expect_next || !expect_valid) {
+ if (!expect_valid) {
return;
}
+
+ // Let's make sure that these never change (i.e., when a quoted value is
+ // unquoted, it should be cached on the first calls and not regenerated
+ // later).
+ std::string::const_iterator first_value_begin = parser->value_begin();
+ std::string::const_iterator first_value_end = parser->value_end();
+
ASSERT_EQ(expected_name, std::string(parser->name_begin(),
parser->name_end()));
ASSERT_EQ(expected_name, parser->name());
ASSERT_EQ(expected_value, std::string(parser->value_begin(),
parser->value_end()));
ASSERT_EQ(expected_value, parser->value());
- ASSERT_EQ(expected_unquoted_value, parser->unquoted_value());
- ASSERT_EQ(expected_value != expected_unquoted_value,
- parser->value_is_quoted());
+
+ // Make sure they didn't/don't change.
+ ASSERT_TRUE(first_value_begin == parser->value_begin());
+ ASSERT_TRUE(first_value_end == parser->value_end());
+}
+
+void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser,
+ bool expect_next,
+ bool expect_valid,
+ std::string expected_name,
+ std::string expected_value) {
+ ASSERT_EQ(expect_next, parser->GetNext());
+ ASSERT_EQ(expect_valid, parser->valid());
+ if (!expect_next || !expect_valid) {
+ return;
+ }
+
+ CheckCurrentNameValuePair(parser,
+ expect_valid,
+ expected_name,
+ expected_value);
}
void CheckInvalidNameValuePair(std::string valid_part,
@@ -731,35 +752,78 @@ void CheckInvalidNameValuePair(std::string valid_part,
} // anonymous namespace
+TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) {
+ std::string data = "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\"";
+ HttpUtil::NameValuePairsIterator parser_a(data.begin(), data.end(), ';');
+
+ EXPECT_TRUE(parser_a.valid());
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_a, true, true, "alpha", "'a'"));
+
+ HttpUtil::NameValuePairsIterator parser_b(parser_a);
+ // a and b now point to same location
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "alpha", "'a'"));
+
+ // advance a, no effect on b
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_a, true, true, "beta", " b "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
+
+ // assign b the current state of a, no effect on a
+ parser_b = parser_a;
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "beta", " b "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
+
+ // advance b, no effect on a
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_b, true, true, "cappa", "c;"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
+}
+
TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) {
std::string data = "";
HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
TEST(HttpUtilTest, NameValuePairsIterator) {
- std::string data = "alpha=1; beta= 2 ;cappa =' 3 ';"
- "delta= \" 4 \"; e= \" '5'\"; e=6";
+ std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';"
+ "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
+ "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';"
+ "g=''; h='hello'";
HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "alpha", "1", "1"));
+ CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "beta", "2"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "cappa", " 3; "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "delta", " \"4\" "));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "beta", "2", "2"));
+ CheckNextNameValuePair(&parser, true, true, "e", " '5'"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "cappa", "' 3 '", " 3 "));
+ CheckNextNameValuePair(&parser, true, true, "e", "6"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "delta", "\" 4 \"", " 4 "));
+ CheckNextNameValuePair(&parser, true, true, "f", "'hello world'"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "e", "\" '5'\"", " '5'"));
+ CheckNextNameValuePair(&parser, true, true, "g", ""));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "e", "6", "6"));
+ CheckNextNameValuePair(&parser, true, true, "h", "hello"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
@@ -768,6 +832,9 @@ TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2"));
ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("", "'beta'=2"));
+ ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
+ ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
+ ";beta=;cappa=2"));
// According to the spec this is an error, but it doesn't seem appropriate to
// change our behaviour to be less permissive at this time.
@@ -783,13 +850,13 @@ TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) {
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "alpha", "1", "1"));
+ CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "beta", "2", "2"));
+ CheckNextNameValuePair(&parser, true, true, "beta", "2"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "cappa", "3", "3"));
+ CheckNextNameValuePair(&parser, true, true, "cappa", "3"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
// See comments on the implementation of NameValuePairsIterator::GetNext
@@ -800,7 +867,7 @@ TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) {
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "name", "value", "value"));
+ CheckNextNameValuePair(&parser, true, true, "name", "value"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
diff --git a/net/net.gyp b/net/net.gyp
index 3c19189..083aac4 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -196,6 +196,8 @@
'base/x509_cert_types.cc',
'base/x509_cert_types.h',
'base/x509_cert_types_mac.cc',
+ 'base/x509_openssl_util.cc',
+ 'base/x509_openssl_util.h',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
@@ -232,9 +234,19 @@
'dependencies': [
'../build/linux/system.gyp:gconf',
'../build/linux/system.gyp:gdk',
- '../build/linux/system.gyp:nss',
'../build/linux/system.gyp:libresolv',
],
+ 'conditions': [
+ ['use_openssl==1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:openssl',
+ ],
+ }, { # else: not using openssl. Use NSS.
+ 'dependencies': [
+ '../build/linux/system.gyp:nss',
+ ],
+ }],
+ ],
},
{ # else: OS is not in the above list
'sources!': [
@@ -252,12 +264,14 @@
],
},
],
- [ 'use_openssl == 1 and OS == "linux"', {
- # When building for OpenSSL, we need to exclude some NSS files.
- # TODO(bulach): remove once we fully support OpenSSL.
+ [ 'use_openssl==1', {
'sources!': [
'base/cert_database_nss.cc',
+ 'base/dnssec_keyset.cc',
+ 'base/dnssec_keyset.h',
'base/keygen_handler_nss.cc',
+ 'base/nss_memio.c',
+ 'base/nss_memio.h',
'base/x509_certificate_nss.cc',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
@@ -269,13 +283,15 @@
'third_party/mozilla_security_manager/nsPKCS12Blob.h',
],
},
- { # else: not using openssl.
+ { # else: not using openssl.
'sources!': [
'base/cert_database_openssl.cc',
'base/keygen_handler_openssl.cc',
'base/openssl_util.cc',
'base/openssl_util.h',
'base/x509_certificate_openssl.cc',
+ 'base/x509_openssl_util.cc',
+ 'base/x509_openssl_util.h',
],
},
],
@@ -570,6 +586,8 @@
'socket/client_socket_pool_histograms.h',
'socket/client_socket_pool_manager.cc',
'socket/client_socket_pool_manager.h',
+ 'socket/dns_cert_provenance_check.cc',
+ 'socket/dns_cert_provenance_check.h',
'socket/socket.h',
'socket/socks5_client_socket.cc',
'socket/socks5_client_socket.h',
@@ -592,6 +610,7 @@
'socket/ssl_client_socket_pool.h',
'socket/ssl_client_socket_win.cc',
'socket/ssl_client_socket_win.h',
+ 'socket/tcp_client_socket.cc',
'socket/tcp_client_socket.h',
'socket/tcp_client_socket_libevent.cc',
'socket/tcp_client_socket_libevent.h',
@@ -701,11 +720,10 @@
'proxy/proxy_config_service_linux.h',
],
}],
- ['use_openssl==1 and OS == "linux"', {
- 'dependencies': [
- '../build/linux/system.gyp:openssl',
- ],
+ ['use_openssl==1', {
'sources!': [
+ 'socket/dns_cert_provenance_check.cc',
+ 'socket/dns_cert_provenance_check.h',
'socket/ssl_client_socket_nss.cc',
'socket/ssl_client_socket_nss.h',
'socket/ssl_client_socket_nss_factory.cc',
@@ -723,7 +741,18 @@
'dependencies': [
'../build/linux/system.gyp:gconf',
'../build/linux/system.gyp:gdk',
- '../build/linux/system.gyp:nss',
+ ],
+ 'conditions': [
+ ['use_openssl==1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:openssl',
+ ],
+ },
+ { # else use_openssl==0, use NSS
+ 'dependencies': [
+ '../build/linux/system.gyp:nss',
+ ],
+ }],
],
},
{ # else: OS is not in the above list
@@ -784,7 +813,6 @@
'net_test_support',
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
- '../base/base.gyp:test_support_base',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../third_party/zlib/zlib.gyp:zlib',
@@ -972,11 +1000,13 @@
}],
],
}],
- [ 'use_openssl == 1 and OS == "linux"', {
- # When building for OpenSSL, we need to exclude some NSS files.
- # TODO(bulach): remove once we fully support OpenSSL.
+ [ 'use_openssl==1', {
+ # When building for OpenSSL, we need to exclude NSS specific tests.
+ # TODO(bulach): Add equivalent tests when the underlying
+ # functionality is ported to OpenSSL.
'sources!': [
'base/cert_database_nss_unittest.cc',
+ 'base/dnssec_unittest.cc',
],
},
],
@@ -1041,7 +1071,6 @@
'net_test_support',
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
- '../base/base.gyp:test_support_base',
'../base/base.gyp:test_support_perf',
'../testing/gtest.gyp:gtest',
],
@@ -1120,6 +1149,7 @@
'dependencies': [
'net',
'../base/base.gyp:base',
+ '../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
],
'sources': [
@@ -1146,8 +1176,16 @@
],
}],
['OS == "linux" or OS == "freebsd" or OS == "openbsd"', {
- 'dependencies': [
- '../build/linux/system.gyp:nss',
+ 'conditions': [
+ ['use_openssl==1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:openssl',
+ ]
+ }, {
+ 'dependencies': [
+ '../build/linux/system.gyp:nss',
+ ],
+ }],
],
}],
['OS == "linux"', {
@@ -1159,11 +1197,6 @@
}],
],
}],
- ['use_openssl == 1 and OS == "linux"', {
- 'dependencies': [
- '../build/linux/system.gyp:openssl',
- ]
- }],
],
},
{
diff --git a/net/ocsp/nss_ocsp.cc b/net/ocsp/nss_ocsp.cc
index b7fcb65..fafaa68 100644
--- a/net/ocsp/nss_ocsp.cc
+++ b/net/ocsp/nss_ocsp.cc
@@ -22,9 +22,10 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
-#include "base/thread.h"
+#include "base/thread_checker.h"
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/io_buffer.h"
@@ -40,16 +41,16 @@ namespace {
pthread_mutex_t g_request_context_lock = PTHREAD_MUTEX_INITIALIZER;
static URLRequestContext* g_request_context = NULL;
-class OCSPIOLoop : public MessageLoop::DestructionObserver {
- public:
- // MessageLoop::DestructionObserver:
- virtual void WillDestroyCurrentMessageLoop() { Shutdown(); }
+class OCSPRequestSession;
+class OCSPIOLoop {
+ public:
void StartUsing() {
AutoLock autolock(lock_);
used_ = true;
}
+ // Called on IO loop.
void Shutdown();
bool used() const {
@@ -62,69 +63,28 @@ class OCSPIOLoop : public MessageLoop::DestructionObserver {
void EnsureIOLoop();
+ void AddRequest(OCSPRequestSession* request);
+ void RemoveRequest(OCSPRequestSession* request);
+
private:
friend struct base::DefaultLazyInstanceTraits<OCSPIOLoop>;
OCSPIOLoop();
~OCSPIOLoop();
+ void CancelAllRequests();
+
mutable Lock lock_;
+ bool shutdown_; // Protected by |lock_|.
+ std::set<OCSPRequestSession*> requests_; // Protected by |lock_|.
bool used_; // Protected by |lock_|.
// This should not be modified after |used_|.
MessageLoopForIO* io_loop_; // Protected by |lock_|.
+ ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop);
};
-OCSPIOLoop::OCSPIOLoop()
- : used_(false),
- io_loop_(MessageLoopForIO::current()) {
- DCHECK(io_loop_);
- io_loop_->AddDestructionObserver(this);
-}
-
-OCSPIOLoop::~OCSPIOLoop() {
- // IO thread was already deleted before the singleton is deleted
- // in AtExitManager.
- {
- AutoLock autolock(lock_);
- DCHECK(!io_loop_);
- DCHECK(!used_);
- }
-
- pthread_mutex_lock(&g_request_context_lock);
- DCHECK(!g_request_context);
- pthread_mutex_unlock(&g_request_context_lock);
-}
-
-void OCSPIOLoop::Shutdown() {
- MessageLoopForIO::current()->RemoveDestructionObserver(this);
-
- // Prevent the worker thread from trying to access |io_loop_|.
- {
- AutoLock autolock(lock_);
- DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
- io_loop_ = NULL;
- used_ = false;
- }
-
- pthread_mutex_lock(&g_request_context_lock);
- g_request_context = NULL;
- pthread_mutex_unlock(&g_request_context_lock);
-}
-
-void OCSPIOLoop::PostTaskToIOLoop(
- const tracked_objects::Location& from_here, Task* task) {
- AutoLock autolock(lock_);
- if (io_loop_)
- io_loop_->PostTask(from_here, task);
-}
-
-void OCSPIOLoop::EnsureIOLoop() {
- AutoLock autolock(lock_);
- DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
-}
-
base::LazyInstance<OCSPIOLoop> g_ocsp_io_loop(base::LINKER_INITIALIZED);
const int kRecvBufferSize = 4096;
@@ -175,44 +135,6 @@ class OCSPNSSInitialization {
DISALLOW_COPY_AND_ASSIGN(OCSPNSSInitialization);
};
-OCSPNSSInitialization::OCSPNSSInitialization() {
- // NSS calls the functions in the function table to download certificates
- // or CRLs or talk to OCSP responders over HTTP. These functions must
- // set an NSS/NSPR error code when they fail. Otherwise NSS will get the
- // residual error code from an earlier failed function call.
- client_fcn_.version = 1;
- SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1;
- ft->createSessionFcn = OCSPCreateSession;
- ft->keepAliveSessionFcn = OCSPKeepAliveSession;
- ft->freeSessionFcn = OCSPFreeSession;
- ft->createFcn = OCSPCreate;
- ft->setPostDataFcn = OCSPSetPostData;
- ft->addHeaderFcn = OCSPAddHeader;
- ft->trySendAndReceiveFcn = OCSPTrySendAndReceive;
- ft->cancelFcn = NULL;
- ft->freeFcn = OCSPFree;
- SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_);
- if (status != SECSuccess) {
- NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
- }
-
- // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the
- // CRLs for Network Solutions Certificate Authority have bad signatures,
- // which causes certificates issued by that CA to be reported as revoked.
- // By using OCSP for those certificates, which don't have AIA extensions,
- // we can work around these bugs. See http://crbug.com/41730.
- CERT_StringFromCertFcn old_callback = NULL;
- status = CERT_RegisterAlternateOCSPAIAInfoCallBack(
- GetAlternateOCSPAIAInfo, &old_callback);
- if (status == SECSuccess) {
- DCHECK(!old_callback);
- } else {
- NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
- }
-}
-
-OCSPNSSInitialization::~OCSPNSSInitialization() {}
-
base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization(
base::LINKER_INITIALIZED);
@@ -223,8 +145,7 @@ base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization(
// on IO thread.
class OCSPRequestSession
: public base::RefCountedThreadSafe<OCSPRequestSession>,
- public URLRequest::Delegate,
- public MessageLoop::DestructionObserver {
+ public URLRequest::Delegate {
public:
OCSPRequestSession(const GURL& url,
const char* http_request_method,
@@ -353,7 +274,7 @@ class OCSPRequestSession
if (!request_->status().is_io_pending()) {
delete request_;
request_ = NULL;
- io_loop_->RemoveDestructionObserver(this);
+ g_ocsp_io_loop.Get().RemoveRequest(this);
{
AutoLock autolock(lock_);
finished_ = true;
@@ -364,13 +285,28 @@ class OCSPRequestSession
}
}
- virtual void WillDestroyCurrentMessageLoop() {
- DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+ // Must be called on the IO loop thread.
+ void CancelURLRequest() {
+#ifndef NDEBUG
{
AutoLock autolock(lock_);
- io_loop_ = NULL;
+ if (io_loop_)
+ DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+ }
+#endif
+ if (request_) {
+ request_->Cancel();
+ delete request_;
+ request_ = NULL;
+ g_ocsp_io_loop.Get().RemoveRequest(this);
+ {
+ AutoLock autolock(lock_);
+ finished_ = true;
+ io_loop_ = NULL;
+ }
+ cv_.Signal();
+ Release(); // Balanced with StartURLRequest().
}
- CancelURLRequest();
}
private:
@@ -409,7 +345,7 @@ class OCSPRequestSession
AutoLock autolock(lock_);
DCHECK(!io_loop_);
io_loop_ = MessageLoopForIO::current();
- io_loop_->AddDestructionObserver(this);
+ g_ocsp_io_loop.Get().AddRequest(this);
}
request_ = new URLRequest(url_, this);
@@ -436,32 +372,6 @@ class OCSPRequestSession
AddRef(); // Release after |request_| deleted.
}
- void CancelURLRequest() {
-#ifndef NDEBUG
- {
- AutoLock autolock(lock_);
- if (io_loop_)
- DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
- }
-#endif
- if (request_) {
- request_->Cancel();
- delete request_;
- request_ = NULL;
- // |io_loop_| may be NULL here if it called from
- // WillDestroyCurrentMessageLoop().
- if (io_loop_)
- io_loop_->RemoveDestructionObserver(this);
- {
- AutoLock autolock(lock_);
- finished_ = true;
- io_loop_ = NULL;
- }
- cv_.Signal();
- Release(); // Balanced with StartURLRequest().
- }
- }
-
GURL url_; // The URL we eventually wound up at
std::string http_request_method_;
base::TimeDelta timeout_; // The timeout for OCSP
@@ -527,6 +437,123 @@ class OCSPServerSession {
DISALLOW_COPY_AND_ASSIGN(OCSPServerSession);
};
+OCSPIOLoop::OCSPIOLoop()
+ : shutdown_(false),
+ used_(false),
+ io_loop_(MessageLoopForIO::current()) {
+ DCHECK(io_loop_);
+}
+
+OCSPIOLoop::~OCSPIOLoop() {
+ // IO thread was already deleted before the singleton is deleted
+ // in AtExitManager.
+ {
+ AutoLock autolock(lock_);
+ DCHECK(!io_loop_);
+ DCHECK(!used_);
+ DCHECK(shutdown_);
+ }
+
+ pthread_mutex_lock(&g_request_context_lock);
+ DCHECK(!g_request_context);
+ pthread_mutex_unlock(&g_request_context_lock);
+}
+
+void OCSPIOLoop::Shutdown() {
+ // Safe to read outside lock since we only write on IO thread anyway.
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Prevent the worker thread from trying to access |io_loop_|.
+ {
+ AutoLock autolock(lock_);
+ io_loop_ = NULL;
+ used_ = false;
+ shutdown_ = true;
+ }
+
+ CancelAllRequests();
+
+ pthread_mutex_lock(&g_request_context_lock);
+ g_request_context = NULL;
+ pthread_mutex_unlock(&g_request_context_lock);
+}
+
+void OCSPIOLoop::PostTaskToIOLoop(
+ const tracked_objects::Location& from_here, Task* task) {
+ AutoLock autolock(lock_);
+ if (io_loop_)
+ io_loop_->PostTask(from_here, task);
+}
+
+void OCSPIOLoop::EnsureIOLoop() {
+ AutoLock autolock(lock_);
+ DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+}
+
+void OCSPIOLoop::AddRequest(OCSPRequestSession* request) {
+ DCHECK(!ContainsKey(requests_, request));
+ requests_.insert(request);
+}
+
+void OCSPIOLoop::RemoveRequest(OCSPRequestSession* request) {
+ {
+ // Ignore if we've already shutdown.
+ AutoLock auto_lock(lock_);
+ if (shutdown_)
+ return;
+ }
+
+ DCHECK(ContainsKey(requests_, request));
+ requests_.erase(request);
+}
+
+void OCSPIOLoop::CancelAllRequests() {
+ std::set<OCSPRequestSession*> requests;
+ requests.swap(requests_);
+
+ for (std::set<OCSPRequestSession*>::iterator it = requests.begin();
+ it != requests.end(); ++it)
+ (*it)->CancelURLRequest();
+}
+
+OCSPNSSInitialization::OCSPNSSInitialization() {
+ // NSS calls the functions in the function table to download certificates
+ // or CRLs or talk to OCSP responders over HTTP. These functions must
+ // set an NSS/NSPR error code when they fail. Otherwise NSS will get the
+ // residual error code from an earlier failed function call.
+ client_fcn_.version = 1;
+ SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1;
+ ft->createSessionFcn = OCSPCreateSession;
+ ft->keepAliveSessionFcn = OCSPKeepAliveSession;
+ ft->freeSessionFcn = OCSPFreeSession;
+ ft->createFcn = OCSPCreate;
+ ft->setPostDataFcn = OCSPSetPostData;
+ ft->addHeaderFcn = OCSPAddHeader;
+ ft->trySendAndReceiveFcn = OCSPTrySendAndReceive;
+ ft->cancelFcn = NULL;
+ ft->freeFcn = OCSPFree;
+ SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_);
+ if (status != SECSuccess) {
+ NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
+ }
+
+ // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the
+ // CRLs for Network Solutions Certificate Authority have bad signatures,
+ // which causes certificates issued by that CA to be reported as revoked.
+ // By using OCSP for those certificates, which don't have AIA extensions,
+ // we can work around these bugs. See http://crbug.com/41730.
+ CERT_StringFromCertFcn old_callback = NULL;
+ status = CERT_RegisterAlternateOCSPAIAInfoCallBack(
+ GetAlternateOCSPAIAInfo, &old_callback);
+ if (status == SECSuccess) {
+ DCHECK(!old_callback);
+ } else {
+ NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
+ }
+}
+
+OCSPNSSInitialization::~OCSPNSSInitialization() {}
+
// OCSP Http Client functions.
// Our Http Client functions operate in blocking mode.
@@ -878,7 +905,7 @@ URLRequestContext* GetURLRequestContextForOCSP() {
pthread_mutex_lock(&g_request_context_lock);
URLRequestContext* request_context = g_request_context;
pthread_mutex_unlock(&g_request_context_lock);
- DCHECK(request_context->is_main());
+ DCHECK(!request_context || request_context->is_main());
return request_context;
}
diff --git a/net/proxy/init_proxy_resolver.cc b/net/proxy/init_proxy_resolver.cc
index 368fcf0..4bf250e 100644
--- a/net/proxy/init_proxy_resolver.cc
+++ b/net/proxy/init_proxy_resolver.cc
@@ -169,8 +169,8 @@ int InitProxyResolver::DoFetchPacScript() {
net_log_.BeginEvent(
NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT,
- new NetLogStringParameter("url",
- effective_pac_url.possibly_invalid_spec()));
+ make_scoped_refptr(new NetLogStringParameter(
+ "url", effective_pac_url.possibly_invalid_spec())));
if (!proxy_script_fetcher_) {
net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL);
@@ -190,7 +190,7 @@ int InitProxyResolver::DoFetchPacScriptComplete(int result) {
} else {
net_log_.EndEvent(
NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT,
- new NetLogIntegerParameter("net_error", result));
+ make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
return TryToFallbackPacUrl(result);
}
@@ -222,7 +222,7 @@ int InitProxyResolver::DoSetPacScriptComplete(int result) {
if (result != OK) {
net_log_.EndEvent(
NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT,
- new NetLogIntegerParameter("net_error", result));
+ make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
return TryToFallbackPacUrl(result);
}
diff --git a/net/proxy/multi_threaded_proxy_resolver.cc b/net/proxy/multi_threaded_proxy_resolver.cc
index 95071b1..d696438 100644
--- a/net/proxy/multi_threaded_proxy_resolver.cc
+++ b/net/proxy/multi_threaded_proxy_resolver.cc
@@ -247,8 +247,8 @@ class MultiThreadedProxyResolver::GetProxyForURLJob
net_log_.AddEvent(
NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD,
- new NetLogIntegerParameter(
- "thread_number", executor()->thread_number()));
+ make_scoped_refptr(new NetLogIntegerParameter(
+ "thread_number", executor()->thread_number())));
}
// Runs on the worker thread.
@@ -410,8 +410,8 @@ int MultiThreadedProxyResolver::GetProxyForURL(const GURL& url,
DCHECK(current_script_data_.get())
<< "Resolver is un-initialized. Must call SetPacScript() first!";
- scoped_refptr<GetProxyForURLJob> job =
- new GetProxyForURLJob(url, results, callback, net_log);
+ scoped_refptr<GetProxyForURLJob> job(
+ new GetProxyForURLJob(url, results, callback, net_log));
// Completion will be notified through |callback|, unless the caller cancels
// the request using |request|.
@@ -557,7 +557,7 @@ MultiThreadedProxyResolver::AddNewExecutor() {
ProxyResolver* resolver = resolver_factory_->CreateProxyResolver();
Executor* executor = new Executor(
this, resolver, thread_number);
- executors_.push_back(executor);
+ executors_.push_back(make_scoped_refptr(executor));
return executor;
}
diff --git a/net/proxy/proxy_bypass_rules.cc b/net/proxy/proxy_bypass_rules.cc
index 757d817..d80e6f1 100644
--- a/net/proxy/proxy_bypass_rules.cc
+++ b/net/proxy/proxy_bypass_rules.cc
@@ -171,14 +171,14 @@ bool ProxyBypassRules::AddRuleForHostname(const std::string& optional_scheme,
if (hostname_pattern.empty())
return false;
- rules_.push_back(new HostnamePatternRule(optional_scheme,
- hostname_pattern,
- optional_port));
+ rules_.push_back(make_scoped_refptr(new HostnamePatternRule(optional_scheme,
+ hostname_pattern,
+ optional_port)));
return true;
}
void ProxyBypassRules::AddRuleToBypassLocal() {
- rules_.push_back(new BypassLocalRule);
+ rules_.push_back(make_scoped_refptr(new BypassLocalRule));
}
bool ProxyBypassRules::AddRuleFromString(const std::string& raw) {
@@ -241,8 +241,8 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
return false;
- rules_.push_back(
- new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits));
+ rules_.push_back(make_scoped_refptr(
+ new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits)));
return true;
}
@@ -264,7 +264,7 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
host = raw;
port = -1;
if (pos_colon != std::string::npos) {
- if (!base::StringToInt(raw.substr(pos_colon + 1), &port) ||
+ if (!base::StringToInt(raw.begin() + pos_colon + 1, raw.end(), &port) ||
(port < 0 || port > 0xFFFF)) {
return false; // Port was invalid.
}
diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc
index d0a387f..5aca4ae 100644
--- a/net/proxy/proxy_config_service_win.cc
+++ b/net/proxy/proxy_config_service_win.cc
@@ -12,6 +12,7 @@
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "base/stl_util-inl.h"
+#include "base/thread_restrictions.h"
#include "base/win/registry.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_config.h"
@@ -72,6 +73,9 @@ ProxyConfigServiceWin::ProxyConfigServiceWin()
}
ProxyConfigServiceWin::~ProxyConfigServiceWin() {
+ // The registry functions below will end up going to disk. Do this on another
+ // thread to avoid slowing the IO thread. http://crbug.com/61453
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
STLDeleteElements(&keys_to_watch_);
}
@@ -87,6 +91,10 @@ void ProxyConfigServiceWin::StartWatchingRegistryForChanges() {
if (!keys_to_watch_.empty())
return; // Already initialized.
+ // The registry functions below will end up going to disk. Do this on another
+ // thread to avoid slowing the IO thread. http://crbug.com/61453
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
// There are a number of different places where proxy settings can live
// in the registry. In some cases it appears in a binary value, in other
// cases string values. Furthermore winhttp and wininet appear to have
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index f84be57..2642f4d 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -36,7 +36,7 @@ class RequestContext : public URLRequestContext {
net::ProxyConfig no_proxy;
host_resolver_ =
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
- NULL);
+ NULL, NULL);
proxy_service_ = net::ProxyService::CreateFixed(no_proxy);
ssl_config_service_ = new net::SSLConfigServiceDefaults;
@@ -78,7 +78,7 @@ class ProxyScriptFetcherImplTest : public PlatformTest {
};
TEST_F(ProxyScriptFetcherImplTest, FileUrl) {
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -107,7 +107,7 @@ TEST_F(ProxyScriptFetcherImplTest, FileUrl) {
TEST_F(ProxyScriptFetcherImplTest, HttpMimeType) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -143,7 +143,7 @@ TEST_F(ProxyScriptFetcherImplTest, HttpMimeType) {
TEST_F(ProxyScriptFetcherImplTest, HttpStatusCode) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -170,7 +170,7 @@ TEST_F(ProxyScriptFetcherImplTest, HttpStatusCode) {
TEST_F(ProxyScriptFetcherImplTest, ContentDisposition) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -188,7 +188,7 @@ TEST_F(ProxyScriptFetcherImplTest, ContentDisposition) {
TEST_F(ProxyScriptFetcherImplTest, NoCache) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -221,7 +221,7 @@ TEST_F(ProxyScriptFetcherImplTest, NoCache) {
TEST_F(ProxyScriptFetcherImplTest, TooLarge) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcherImpl> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -263,7 +263,7 @@ TEST_F(ProxyScriptFetcherImplTest, TooLarge) {
TEST_F(ProxyScriptFetcherImplTest, Hang) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcherImpl> pac_fetcher(
new ProxyScriptFetcherImpl(context));
@@ -302,7 +302,7 @@ TEST_F(ProxyScriptFetcherImplTest, Hang) {
TEST_F(ProxyScriptFetcherImplTest, Encodings) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new RequestContext;
+ scoped_refptr<URLRequestContext> context(new RequestContext);
scoped_ptr<ProxyScriptFetcher> pac_fetcher(
new ProxyScriptFetcherImpl(context));
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index 5e11ef1..b4aa96d 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -525,8 +525,8 @@ int ProxyService::ResolveProxy(const GURL& raw_url,
if (rv != ERR_IO_PENDING)
return DidFinishResolvingProxy(result, rv, net_log);
- scoped_refptr<PacRequest> req =
- new PacRequest(this, url, result, callback, net_log);
+ scoped_refptr<PacRequest> req(
+ new PacRequest(this, url, result, callback, net_log));
if (current_state_ == STATE_READY) {
// Start the resolve request.
@@ -715,13 +715,15 @@ int ProxyService::DidFinishResolvingProxy(ProxyInfo* result,
if (net_log.IsLoggingAllEvents()) {
net_log.AddEvent(
NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
- new NetLogStringParameter("pac_string", result->ToPacString()));
+ make_scoped_refptr(new NetLogStringParameter(
+ "pac_string", result->ToPacString())));
}
result->DeprioritizeBadProxies(proxy_retry_info_);
} else {
net_log.AddEvent(
NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
- new NetLogIntegerParameter("net_error", result_code));
+ make_scoped_refptr(new NetLogIntegerParameter(
+ "net_error", result_code)));
// Fall-back to direct when the proxy resolver fails. This corresponds
// with a javascript runtime error in the PAC script.
@@ -831,8 +833,8 @@ ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
void ProxyService::OnProxyConfigChanged(const ProxyConfig& config) {
// Emit the proxy settings change to the NetLog stream.
if (net_log_) {
- scoped_refptr<NetLog::EventParameters> params =
- new ProxyConfigChangedNetLogParam(fetched_config_, config);
+ scoped_refptr<NetLog::EventParameters> params(
+ new ProxyConfigChangedNetLogParam(fetched_config_, config));
net_log_->AddEntry(net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
base::TimeTicks::Now(),
NetLog::Source(),
diff --git a/net/server/http_listen_socket.cc b/net/server/http_listen_socket.cc
index b4f05d9..f35582b 100644
--- a/net/server/http_listen_socket.cc
+++ b/net/server/http_listen_socket.cc
@@ -37,8 +37,8 @@ void HttpListenSocket::Accept() {
if (conn == ListenSocket::kInvalidSocket) {
// TODO
} else {
- scoped_refptr<HttpListenSocket> sock =
- new HttpListenSocket(conn, delegate_);
+ scoped_refptr<HttpListenSocket> sock(
+ new HttpListenSocket(conn, delegate_));
#if defined(OS_POSIX)
sock->WatchSocket(WAITING_READ);
#endif
diff --git a/net/socket/client_socket.cc b/net/socket/client_socket.cc
index 6f38eae..6b12841 100644
--- a/net/socket/client_socket.cc
+++ b/net/socket/client_socket.cc
@@ -58,6 +58,14 @@ ClientSocket::UseHistory::~UseHistory() {
EmitPreconnectionHistograms();
}
+void ClientSocket::UseHistory::Reset() {
+ EmitPreconnectionHistograms();
+ was_ever_connected_ = false;
+ was_used_to_convey_data_ = false;
+ // omnibox_speculation_ and subresource_speculation_ values
+ // are intentionally preserved.
+}
+
void ClientSocket::UseHistory::EmitPreconnectionHistograms() const {
DCHECK(!subresource_speculation_ || !omnibox_speculation_);
// 0 ==> non-speculative, never connected.
diff --git a/net/socket/client_socket.h b/net/socket/client_socket.h
index b4173c0..358716c 100644
--- a/net/socket/client_socket.h
+++ b/net/socket/client_socket.h
@@ -69,6 +69,10 @@ class ClientSocket : public Socket {
// this call to the transport socket.
virtual bool WasEverUsed() const = 0;
+ // Returns true if the underlying transport socket is using TCP FastOpen.
+ // TCP FastOpen is an experiment with sending data in the TCP SYN packet.
+ virtual bool UsingTCPFastOpen() const = 0;
+
protected:
// The following class is only used to gather statistics about the history of
// a socket. It is only instantiated and used in basic sockets, such as
@@ -80,6 +84,10 @@ class ClientSocket : public Socket {
UseHistory();
~UseHistory();
+ // Resets the state of UseHistory and emits histograms for the
+ // current state.
+ void Reset();
+
void set_was_ever_connected();
void set_was_used_to_convey_data();
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 3ac5a00..947a2fa 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -16,7 +16,6 @@
#elif defined(USE_OPENSSL) && defined(ANDROID)
#include "net/socket/ssl_client_socket_openssl.h"
#elif defined(OS_MACOSX)
-#include "net/socket/ssl_client_socket_mac.h"
#include "net/socket/ssl_client_socket_nss.h"
#endif
#include "net/socket/ssl_host_info.h"
@@ -24,13 +23,16 @@
namespace net {
+class DnsRRResolver;
+
namespace {
SSLClientSocket* DefaultSSLClientSocketFactory(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
scoped_ptr<SSLHostInfo> shi(ssl_host_info);
#if defined(OS_WIN)
return new SSLClientSocketWin(transport_socket, hostname, ssl_config);
@@ -38,16 +40,10 @@ SSLClientSocket* DefaultSSLClientSocketFactory(
return new SSLClientSocketOpenSSL(transport_socket, hostname, ssl_config);
#elif defined(USE_NSS)
return new SSLClientSocketNSS(transport_socket, hostname, ssl_config,
- shi.release());
+ shi.release(), dnsrr_resolver);
#elif defined(OS_MACOSX)
- // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
- // Mac OS X CDSA/CSSM yet (http://crbug.com/45369), so fall back on
- // SSLClientSocketMac.
- if (ssl_config.send_client_cert)
- return new SSLClientSocketMac(transport_socket, hostname, ssl_config);
-
return new SSLClientSocketNSS(transport_socket, hostname, ssl_config,
- shi.release());
+ shi.release(), dnsrr_resolver);
#else
NOTIMPLEMENTED();
return NULL;
@@ -69,8 +65,10 @@ class DefaultClientSocketFactory : public ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
- return g_ssl_factory(transport_socket, hostname, ssl_config, ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
+ return g_ssl_factory(transport_socket, hostname, ssl_config, ssl_host_info,
+ dnsrr_resolver);
}
};
@@ -96,7 +94,7 @@ SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket(
ClientSocketHandle* socket_handle = new ClientSocketHandle();
socket_handle->set_socket(transport_socket);
return CreateSSLClientSocket(socket_handle, hostname, ssl_config,
- ssl_host_info);
+ ssl_host_info, NULL /* DnsRRResolver */);
}
} // namespace net
diff --git a/net/socket/client_socket_factory.h b/net/socket/client_socket_factory.h
index ad2cc54..4814b9c 100644
--- a/net/socket/client_socket_factory.h
+++ b/net/socket/client_socket_factory.h
@@ -15,6 +15,7 @@ namespace net {
class AddressList;
class ClientSocket;
class ClientSocketHandle;
+class DnsRRResolver;
class SSLClientSocket;
struct SSLConfig;
class SSLHostInfo;
@@ -24,7 +25,8 @@ typedef SSLClientSocket* (*SSLClientSocketFactory)(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
// An interface used to instantiate ClientSocket objects. Used to facilitate
// testing code with mock socket implementations.
@@ -43,7 +45,8 @@ class ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) = 0;
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) = 0;
// Deprecated function (http://crbug.com/37810) that takes a ClientSocket.
virtual SSLClientSocket* CreateSSLClientSocket(ClientSocket* transport_socket,
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc
index 6184905..29b5bd3 100644
--- a/net/socket/client_socket_handle.cc
+++ b/net/socket/client_socket_handle.cc
@@ -116,7 +116,8 @@ void ClientSocketHandle::HandleInitCompletion(int result) {
DCHECK(socket_.get());
socket_->NetLog().BeginEvent(
NetLog::TYPE_SOCKET_IN_USE,
- new NetLogSourceParameter("source_dependency", requesting_source_));
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", requesting_source_)));
}
} // namespace net
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 75abae6..2228729 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -87,9 +87,9 @@ void ConnectJob::UseForNormalRequest() {
void ConnectJob::set_socket(ClientSocket* socket) {
if (socket) {
- net_log().AddEvent(NetLog::TYPE_CONNECT_JOB_SET_SOCKET,
- new NetLogSourceParameter("source_dependency",
- socket->NetLog().source()));
+ net_log().AddEvent(NetLog::TYPE_CONNECT_JOB_SET_SOCKET, make_scoped_refptr(
+ new NetLogSourceParameter("source_dependency",
+ socket->NetLog().source())));
}
socket_.reset(socket);
}
@@ -110,7 +110,7 @@ void ConnectJob::ResetTimer(base::TimeDelta remaining_time) {
void ConnectJob::LogConnectStart() {
net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT,
- new NetLogStringParameter("group_name", group_name_));
+ make_scoped_refptr(new NetLogStringParameter("group_name", group_name_)));
}
void ConnectJob::LogConnectCompletion(int net_error) {
@@ -239,7 +239,8 @@ void ClientSocketPoolBaseHelper::RequestSockets(
request.net_log().BeginEvent(
NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS,
- new NetLogIntegerParameter("num_sockets", num_sockets));
+ make_scoped_refptr(new NetLogIntegerParameter(
+ "num_sockets", num_sockets)));
Group* group = GetOrCreateGroup(group_name);
@@ -394,7 +395,8 @@ void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest(
const NetLog::Source& connect_job_source, const Request* request) {
request->net_log().AddEvent(
NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
- new NetLogSourceParameter("source_dependency", connect_job_source));
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", connect_job_source)));
}
void ClientSocketPoolBaseHelper::CancelRequest(
@@ -763,8 +765,8 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete(
HandOutSocket(socket.release(), false /* unused socket */, r->handle(),
base::TimeDelta(), group, r->net_log());
}
- r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL,
- new NetLogIntegerParameter("net_error", result));
+ r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, make_scoped_refptr(
+ new NetLogIntegerParameter("net_error", result)));
InvokeUserCallbackLater(r->handle(), r->callback(), result);
} else {
RemoveConnectJob(job, group);
@@ -849,13 +851,13 @@ void ClientSocketPoolBaseHelper::HandOutSocket(
if (reused) {
net_log.AddEvent(
NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET,
- new NetLogIntegerParameter(
- "idle_ms", static_cast<int>(idle_time.InMilliseconds())));
+ make_scoped_refptr(new NetLogIntegerParameter(
+ "idle_ms", static_cast<int>(idle_time.InMilliseconds()))));
}
net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
- new NetLogSourceParameter(
- "source_dependency", socket->NetLog().source()));
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", socket->NetLog().source())));
handed_out_socket_count_++;
group->IncrementActiveSocketCount();
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 820b030..7b83162 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -81,6 +81,7 @@ class MockClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation() {}
virtual void SetOmniboxSpeculation() {}
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
+ virtual bool UsingTCPFastOpen() const { return false; }
private:
bool connected_;
@@ -108,7 +109,8 @@ class MockClientSocketFactory : public ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
NOTIMPLEMENTED();
delete ssl_host_info;
return NULL;
@@ -1280,7 +1282,7 @@ class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
}
within_callback_ = true;
TestCompletionCallback next_job_callback;
- scoped_refptr<TestSocketParams> params = new TestSocketParams();
+ scoped_refptr<TestSocketParams> params(new TestSocketParams());
int rv = handle_->Init("a",
params,
kDefaultPriority,
@@ -2086,7 +2088,7 @@ class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > {
callback_.RunWithParams(params);
if (reset_releasing_handle_)
handle_.Reset();
- scoped_refptr<TestSocketParams> con_params = new TestSocketParams();
+ scoped_refptr<TestSocketParams> con_params(new TestSocketParams());
EXPECT_EQ(expected_result_, handle2_.Init("a",
con_params,
kDefaultPriority,
diff --git a/net/socket/deterministic_socket_data_unittest.cc b/net/socket/deterministic_socket_data_unittest.cc
index 199dd0b..5e25aa0 100644
--- a/net/socket/deterministic_socket_data_unittest.cc
+++ b/net/socket/deterministic_socket_data_unittest.cc
@@ -131,7 +131,7 @@ void DeterministicSocketDataTest::AssertReadBufferEquals(const char* data,
void DeterministicSocketDataTest::AssertSyncWriteEquals(const char* data,
int len) {
- scoped_refptr<IOBuffer> buf = new IOBuffer(len);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(len));
memcpy(buf->data(), data, len);
// Issue the write, which will complete immediately
@@ -152,7 +152,7 @@ void DeterministicSocketDataTest::AssertAsyncWriteEquals(const char* data,
void DeterministicSocketDataTest::AssertWriteReturns(const char* data,
int len, int rv) {
- scoped_refptr<IOBuffer> buf = new IOBuffer(len);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(len));
memcpy(buf->data(), data, len);
// Issue the read, which will complete asynchronously
diff --git a/net/socket/dns_cert_provenance_check.cc b/net/socket/dns_cert_provenance_check.cc
new file mode 100644
index 0000000..e83cb5e
--- /dev/null
+++ b/net/socket/dns_cert_provenance_check.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 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/socket/dns_cert_provenance_check.h"
+
+#include <nspr.h>
+#include <hasht.h>
+#include <sechash.h>
+
+#include <string>
+
+#include "base/non_thread_safe.h"
+#include "net/base/completion_callback.h"
+#include "net/base/dns_util.h"
+#include "net/base/dnsrr_resolver.h"
+#include "net/base/net_log.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+namespace {
+
+class DNSCertProvenanceChecker : public NonThreadSafe {
+ public:
+ DNSCertProvenanceChecker(const std::string hostname,
+ DnsRRResolver* dnsrr_resolver,
+ const std::vector<base::StringPiece>& der_certs)
+ : hostname_(hostname),
+ dnsrr_resolver_(dnsrr_resolver),
+ der_certs_(der_certs.size()),
+ handle_(DnsRRResolver::kInvalidHandle),
+ ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
+ this, &DNSCertProvenanceChecker::ResolutionComplete)) {
+ for (size_t i = 0; i < der_certs.size(); i++)
+ der_certs_[i] = der_certs[i].as_string();
+ }
+
+ void Start() {
+ DCHECK(CalledOnValidThread());
+
+ if (der_certs_.empty())
+ return;
+
+ uint8 fingerprint[SHA1_LENGTH];
+ SECStatus rv = HASH_HashBuf(
+ HASH_AlgSHA1, fingerprint, (uint8*) der_certs_[0].data(),
+ der_certs_[0].size());
+ DCHECK_EQ(SECSuccess, rv);
+ char fingerprint_hex[SHA1_LENGTH * 2 + 1];
+ for (unsigned i = 0; i < sizeof(fingerprint); i++) {
+ static const char hextable[] = "0123456789abcdef";
+ fingerprint_hex[i*2] = hextable[fingerprint[i] >> 4];
+ fingerprint_hex[i*2 + 1] = hextable[fingerprint[i] & 15];
+ }
+ fingerprint_hex[SHA1_LENGTH * 2] = 0;
+
+ static const char kBaseCertName[] = ".certs.links.org";
+ domain_.assign(fingerprint_hex);
+ domain_.append(kBaseCertName);
+
+ handle_ = dnsrr_resolver_->Resolve(
+ domain_, kDNS_TXT, 0 /* flags */, &callback_, &response_,
+ 0 /* priority */, BoundNetLog());
+ if (handle_ == DnsRRResolver::kInvalidHandle) {
+ LOG(ERROR) << "Failed to resolve " << domain_ << " for " << hostname_;
+ delete this;
+ }
+ }
+
+ private:
+ void ResolutionComplete(int status) {
+ DCHECK(CalledOnValidThread());
+
+ if (status == ERR_NAME_NOT_RESOLVED ||
+ (status == OK && response_.rrdatas.empty())) {
+ LOG(ERROR) << "FAILED"
+ << " hostname:" << hostname_
+ << " domain:" << domain_;
+ } else if (status == OK) {
+ LOG(ERROR) << "GOOD"
+ << " hostname:" << hostname_
+ << " resp:" << response_.rrdatas[0];
+ } else {
+ LOG(ERROR) << "Unknown error " << status << " for " << domain_;
+ }
+
+ delete this;
+ }
+
+ const std::string hostname_;
+ std::string domain_;
+ DnsRRResolver* const dnsrr_resolver_;
+ std::vector<std::string> der_certs_;
+ RRResponse response_;
+ DnsRRResolver::Handle handle_;
+ CompletionCallbackImpl<DNSCertProvenanceChecker> callback_;
+};
+
+} // anonymous namespace
+
+void DoAsyncDNSCertProvenanceVerification(
+ const std::string& hostname,
+ DnsRRResolver* dnsrr_resolver,
+ const std::vector<base::StringPiece>& der_certs) {
+ DNSCertProvenanceChecker* c(new DNSCertProvenanceChecker(
+ hostname, dnsrr_resolver, der_certs));
+ c->Start();
+}
+
+} // namespace net
diff --git a/net/socket/dns_cert_provenance_check.h b/net/socket/dns_cert_provenance_check.h
new file mode 100644
index 0000000..289cccf
--- /dev/null
+++ b/net/socket/dns_cert_provenance_check.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2010 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_SOCKET_DNS_CERT_PROVENANCE_CHECK_H
+#define NET_SOCKET_DNS_CERT_PROVENANCE_CHECK_H
+
+#include <string>
+#include <vector>
+
+#include "base/string_piece.h"
+
+namespace net {
+
+class DnsRRResolver;
+
+// DoAsyncDNSCertProvenanceVerification starts an asynchronous check for the
+// given certificate chain. It must be run on the network thread.
+void DoAsyncDNSCertProvenanceVerification(
+ const std::string& hostname,
+ DnsRRResolver* dnsrr_resolver,
+ const std::vector<base::StringPiece>& der_certs);
+
+} // namespace net
+
+#endif // NET_SOCKET_DNS_CERT_PROVENANCE_CHECK_H
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 53bcf89..57aef05 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -513,6 +513,10 @@ bool MockSSLClientSocket::WasEverUsed() const {
return transport_->socket()->WasEverUsed();
}
+bool MockSSLClientSocket::UsingTCPFastOpen() const {
+ return transport_->socket()->UsingTCPFastOpen();
+}
+
int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
net::CompletionCallback* callback) {
return transport_->socket()->Read(buf, buf_len, callback);
@@ -1011,7 +1015,8 @@ SSLClientSocket* MockClientSocketFactory::CreateSSLClientSocket(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
MockSSLClientSocket* socket =
new MockSSLClientSocket(transport_socket, hostname, ssl_config,
ssl_host_info, mock_ssl_data_.GetNext());
@@ -1060,7 +1065,8 @@ SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
MockSSLClientSocket* socket =
new MockSSLClientSocket(transport_socket, hostname, ssl_config,
ssl_host_info, mock_ssl_data_.GetNext());
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index a8e4537..349013e 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -534,7 +534,8 @@ class MockClientSocketFactory : public ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
SocketDataProviderArray<SocketDataProvider>& mock_data() {
return mock_data_;
}
@@ -609,6 +610,7 @@ class MockTCPClientSocket : public MockClientSocket {
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const { return IsConnected(); }
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
+ virtual bool UsingTCPFastOpen() const { return false; }
// Socket methods:
virtual int Read(net::IOBuffer* buf, int buf_len,
@@ -654,6 +656,7 @@ class DeterministicMockTCPClientSocket : public MockClientSocket,
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const { return IsConnected(); }
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
+ virtual bool UsingTCPFastOpen() const { return false; }
// Socket methods:
virtual int Write(net::IOBuffer* buf, int buf_len,
@@ -698,6 +701,7 @@ class MockSSLClientSocket : public MockClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(net::IOBuffer* buf, int buf_len,
@@ -875,7 +879,8 @@ class DeterministicMockClientSocketFactory : public ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
SocketDataProviderArray<DeterministicSocketData>& mock_data() {
return mock_data_;
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index 42bb859..02e5b1f 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
#include "base/format_macros.h"
#include "base/string_util.h"
#include "net/base/io_buffer.h"
@@ -133,6 +134,14 @@ bool SOCKS5ClientSocket::WasEverUsed() const {
return false;
}
+bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
// Read is called by the transport layer above to read. This can only be done
// if the SOCKS handshake is complete.
int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len,
@@ -303,13 +312,15 @@ int SOCKS5ClientSocket::DoGreetReadComplete(int result) {
// Got the greet data.
if (buffer_[0] != kSOCKS5Version) {
- net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
- new NetLogIntegerParameter("version", buffer_[0]));
+ net_log_.AddEvent(
+ NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
+ make_scoped_refptr(new NetLogIntegerParameter("version", buffer_[0])));
return ERR_SOCKS_CONNECTION_FAILED;
}
if (buffer_[1] != 0x00) {
- net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH,
- new NetLogIntegerParameter("method", buffer_[1]));
+ net_log_.AddEvent(
+ NetLog::TYPE_SOCKS_UNEXPECTED_AUTH,
+ make_scoped_refptr(new NetLogIntegerParameter("method", buffer_[1])));
return ERR_SOCKS_CONNECTION_FAILED;
}
@@ -412,13 +423,17 @@ int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
// and accordingly increase them
if (bytes_received_ == kReadHeaderSize) {
if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) {
- net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
- new NetLogIntegerParameter("version", buffer_[0]));
+ net_log_.AddEvent(
+ NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
+ make_scoped_refptr(
+ new NetLogIntegerParameter("version", buffer_[0])));
return ERR_SOCKS_CONNECTION_FAILED;
}
if (buffer_[1] != 0x00) {
- net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR,
- new NetLogIntegerParameter("error_code", buffer_[1]));
+ net_log_.AddEvent(
+ NetLog::TYPE_SOCKS_SERVER_ERROR,
+ make_scoped_refptr(
+ new NetLogIntegerParameter("error_code", buffer_[1])));
return ERR_SOCKS_CONNECTION_FAILED;
}
@@ -436,8 +451,10 @@ int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
else if (address_type == kEndPointResolvedIPv6)
read_header_size += sizeof(struct in6_addr) - 1;
else {
- net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE,
- new NetLogIntegerParameter("address_type", buffer_[3]));
+ net_log_.AddEvent(
+ NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE,
+ make_scoped_refptr(
+ new NetLogIntegerParameter("address_type", buffer_[3])));
return ERR_SOCKS_CONNECTION_FAILED;
}
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index 72e27db..5a918cc 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -59,6 +59,7 @@ class SOCKS5ClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index 43a441d..2152c86 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -141,7 +141,7 @@ TEST_F(SOCKS5ClientSocketTest, CompleteHandshake) {
EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
NetLog::TYPE_SOCKS5_CONNECT));
- scoped_refptr<IOBuffer> buffer = new IOBuffer(payload_write.size());
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
memcpy(buffer->data(), payload_write.data(), payload_write.size());
rv = user_sock_->Write(buffer, payload_write.size(), &callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index 26cad34..4dad417 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -168,6 +168,15 @@ bool SOCKSClientSocket::WasEverUsed() const {
return false;
}
+bool SOCKSClientSocket::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
+
// Read is called by the transport layer above to read. This can only be done
// if the SOCKS handshake is complete.
int SOCKSClientSocket::Read(IOBuffer* buf, int buf_len,
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index e9e9695..86511cf 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -56,6 +56,7 @@ class SOCKSClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index 086b21d..11a88ae 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -153,7 +153,7 @@ TEST_F(SOCKSClientSocketTest, CompleteHandshake) {
EXPECT_TRUE(LogContainsEndEvent(
log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
- scoped_refptr<IOBuffer> buffer = new IOBuffer(payload_write.size());
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
memcpy(buffer->data(), payload_write.data(), payload_write.size());
rv = user_sock_->Write(buffer, payload_write.size(), &callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 6a8270e..d6fca9b 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -614,6 +614,14 @@ bool SSLClientSocketMac::WasEverUsed() const {
return false;
}
+bool SSLClientSocketMac::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(completed_handshake());
@@ -1124,8 +1132,8 @@ int SSLClientSocketMac::DidCompleteHandshake() {
DCHECK(!server_cert_ || renegotiating_);
VLOG(1) << "Handshake completed, next verify cert";
- scoped_refptr<X509Certificate> new_server_cert =
- GetServerCert(ssl_context_);
+ scoped_refptr<X509Certificate> new_server_cert(
+ GetServerCert(ssl_context_));
if (!new_server_cert)
return ERR_UNEXPECTED;
diff --git a/net/socket/ssl_client_socket_mac.h b/net/socket/ssl_client_socket_mac.h
index 00438fc..0763fd3 100644
--- a/net/socket/ssl_client_socket_mac.h
+++ b/net/socket/ssl_client_socket_mac.h
@@ -50,6 +50,7 @@ class SSLClientSocketMac : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/socket/ssl_client_socket_mac_factory.cc b/net/socket/ssl_client_socket_mac_factory.cc
index 7f0c5ce..d10e10d 100644
--- a/net/socket/ssl_client_socket_mac_factory.cc
+++ b/net/socket/ssl_client_socket_mac_factory.cc
@@ -13,7 +13,8 @@ SSLClientSocket* SSLClientSocketMacFactory(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
delete ssl_host_info;
return new SSLClientSocketMac(transport_socket, hostname, ssl_config);
}
diff --git a/net/socket/ssl_client_socket_mac_factory.h b/net/socket/ssl_client_socket_mac_factory.h
index ca97b00..6f12883 100644
--- a/net/socket/ssl_client_socket_mac_factory.h
+++ b/net/socket/ssl_client_socket_mac_factory.h
@@ -10,6 +10,7 @@
namespace net {
+class DnsRRResolver;
class SSLHostInfo;
// Creates SSLClientSocketMac objects.
@@ -17,7 +18,8 @@ SSLClientSocket* SSLClientSocketMacFactory(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 136f138..a6aa458 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -50,6 +50,9 @@
#if defined(USE_SYSTEM_SSL)
#include <dlfcn.h>
#endif
+#if defined(OS_MACOSX)
+#include <Security/Security.h>
+#endif
#include <certdb.h>
#include <hasht.h>
#include <keyhi.h>
@@ -60,6 +63,7 @@
#include <sechash.h>
#include <ssl.h>
#include <sslerr.h>
+#include <sslproto.h>
#include <limits>
@@ -71,10 +75,12 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/thread_restrictions.h"
#include "base/values.h"
#include "net/base/address_list.h"
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verifier.h"
+#include "net/base/connection_type_histograms.h"
#include "net/base/dns_util.h"
#include "net/base/dnsrr_resolver.h"
#include "net/base/dnssec_chain_verifier.h"
@@ -87,6 +93,7 @@
#include "net/base/sys_addrinfo.h"
#include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h"
+#include "net/socket/dns_cert_provenance_check.h"
#include "net/socket/ssl_host_info.h"
static const int kRecvBufferSize = 4096;
@@ -176,6 +183,11 @@ class NSSSSLInitSingleton {
// thread-safe, and the NSS SSL library will only ever be initialized once.
// The NSS SSL library will be properly shut down on program exit.
void EnsureNSSSSLInit() {
+ // Initializing SSL causes us to do blocking IO.
+ // Temporarily allow it until we fix
+ // http://code.google.com/p/chromium/issues/detail?id=59847
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
Singleton<NSSSSLInitSingleton>::get();
}
@@ -206,6 +218,8 @@ int MapNSPRError(PRErrorCode err) {
return ERR_INVALID_ARGUMENT;
case PR_END_OF_FILE_ERROR:
return ERR_CONNECTION_CLOSED;
+ case PR_NOT_IMPLEMENTED_ERROR:
+ return ERR_NOT_IMPLEMENTED;
case SEC_ERROR_INVALID_ARGS:
return ERR_INVALID_ARGUMENT;
@@ -309,52 +323,13 @@ class SSLFailedNSSFunctionParams : public NetLog::EventParameters {
void LogFailedNSSFunction(const BoundNetLog& net_log,
const char* function,
const char* param) {
- net_log.AddEvent(NetLog::TYPE_SSL_NSS_ERROR,
- new SSLFailedNSSFunctionParams(function, param));
+ net_log.AddEvent(
+ NetLog::TYPE_SSL_NSS_ERROR,
+ make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param)));
}
#if defined(OS_WIN)
-// A certificate for COMODO EV SGC CA, issued by AddTrust External CA Root,
-// causes CertGetCertificateChain to report CERT_TRUST_IS_NOT_VALID_FOR_USAGE.
-// It seems to be caused by the szOID_APPLICATION_CERT_POLICIES extension in
-// that certificate.
-//
-// This function is used in the workaround for http://crbug.com/43538
-bool IsProblematicComodoEVCACert(const CERTCertificate& cert) {
- // Issuer:
- // CN = AddTrust External CA Root
- // OU = AddTrust External TTP Network
- // O = AddTrust AB
- // C = SE
- static const uint8 kIssuer[] = {
- 0x30, 0x6f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
- 0x06, 0x13, 0x02, 0x53, 0x45, 0x31, 0x14, 0x30, 0x12, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x64, 0x64, 0x54,
- 0x72, 0x75, 0x73, 0x74, 0x20, 0x41, 0x42, 0x31, 0x26, 0x30,
- 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x64,
- 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x54, 0x54, 0x50, 0x20,
- 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x22, 0x30,
- 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, 0x64,
- 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x20, 0x52,
- 0x6f, 0x6f, 0x74
- };
-
- // Serial number: 79:0A:83:4D:48:40:6B:AB:6C:35:2A:D5:1F:42:83:FE.
- static const uint8 kSerialNumber[] = {
- 0x79, 0x0a, 0x83, 0x4d, 0x48, 0x40, 0x6b, 0xab, 0x6c, 0x35,
- 0x2a, 0xd5, 0x1f, 0x42, 0x83, 0xfe
- };
-
- return cert.derIssuer.len == sizeof(kIssuer) &&
- memcmp(cert.derIssuer.data, kIssuer, cert.derIssuer.len) == 0 &&
- cert.serialNumber.len == sizeof(kSerialNumber) &&
- memcmp(cert.serialNumber.data, kSerialNumber,
- cert.serialNumber.len) == 0;
-}
-
// This callback is intended to be used with CertFindChainInStore. In addition
// to filtering by extended/enhanced key usage, we do not show expired
// certificates and require digital signature usage in the key usage
@@ -391,17 +366,61 @@ BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
#endif
-} // namespace
+// PeerCertificateChain is a helper object which extracts the certificate
+// chain, as given by the server, from an NSS socket and performs the needed
+// resource management. The first element of the chain is the leaf certificate
+// and the other elements are in the order given by the server.
+class PeerCertificateChain {
+ public:
+ explicit PeerCertificateChain(PRFileDesc* nss_fd)
+ : num_certs_(0),
+ certs_(NULL) {
+ SECStatus rv = SSL_PeerCertificateChain(nss_fd, NULL, &num_certs_);
+ DCHECK_EQ(rv, SECSuccess);
-#if defined(OS_WIN)
-// static
-HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL;
-#endif
+ certs_ = new CERTCertificate*[num_certs_];
+ const unsigned expected_num_certs = num_certs_;
+ rv = SSL_PeerCertificateChain(nss_fd, certs_, &num_certs_);
+ DCHECK_EQ(rv, SECSuccess);
+ DCHECK_EQ(num_certs_, expected_num_certs);
+ }
+
+ ~PeerCertificateChain() {
+ for (unsigned i = 0; i < num_certs_; i++)
+ CERT_DestroyCertificate(certs_[i]);
+ delete[] certs_;
+ }
+
+ unsigned size() const { return num_certs_; }
+
+ CERTCertificate* operator[](unsigned i) {
+ DCHECK_LT(i, num_certs_);
+ return certs_[i];
+ }
+
+ std::vector<base::StringPiece> AsStringPieceVector() const {
+ std::vector<base::StringPiece> v(size());
+ for (unsigned i = 0; i < size(); i++) {
+ v[i] = base::StringPiece(
+ reinterpret_cast<const char*>(certs_[i]->derCert.data),
+ certs_[i]->derCert.len);
+ }
+
+ return v;
+ }
+
+ private:
+ unsigned num_certs_;
+ CERTCertificate** certs_;
+};
+
+} // namespace
SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info)
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver)
: ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
this, &SSLClientSocketNSS::BufferSendComplete)),
ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
@@ -420,12 +439,15 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
user_read_buf_len_(0),
user_write_buf_len_(0),
server_cert_nss_(NULL),
+ server_cert_verify_result_(NULL),
+ ssl_connection_status_(0),
client_auth_cert_needed_(false),
handshake_callback_called_(false),
completed_handshake_(false),
pseudo_connected_(false),
eset_mitm_detected_(false),
- netnanny_mitm_detected_(false),
+ predicted_cert_chain_correct_(false),
+ peername_initialized_(false),
dnssec_provider_(NULL),
next_handshake_state_(STATE_NONE),
nss_fd_(NULL),
@@ -433,7 +455,8 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
net_log_(transport_socket->socket()->NetLog()),
predicted_npn_status_(kNextProtoUnsupported),
predicted_npn_proto_used_(false),
- ssl_host_info_(ssl_host_info) {
+ ssl_host_info_(ssl_host_info),
+ dnsrr_resolver_(dnsrr_resolver) {
EnterFunction("");
}
@@ -475,6 +498,8 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
NOTREACHED();
return;
}
+ net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START,
+ new NetLogIntegerParameter("type", snap_start_type));
LOG(ERROR) << "Snap Start: " << snap_start_type << " " << hostname_;
if (snap_start_type == SSL_SNAP_START_FULL ||
snap_start_type == SSL_SNAP_START_RESUME) {
@@ -490,43 +515,32 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
NOTREACHED();
return;
}
- // If the server doesn't support Snap Start then |hello_data_len| is zero.
- if (!hello_data_len)
- return;
if (hello_data_len > std::numeric_limits<uint16>::max())
return;
SSLHostInfo::State* state = ssl_host_info_->mutable_state();
state->server_hello =
std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
- state->npn_valid = true;
- state->npn_status = GetNextProto(&state->npn_protocol);
-
- // TODO(wtc): CERT_GetCertChainFromCert might not return the same cert chain
- // that the Certificate message actually contained. http://crbug.com/48854
- CERTCertList* cert_list = CERT_GetCertChainFromCert(
- server_cert_nss_, PR_Now(), certUsageSSLCA);
- if (!cert_list)
- return;
+ if (hello_data_len > 0) {
+ state->npn_valid = true;
+ state->npn_status = GetNextProto(&state->npn_protocol);
+ } else {
+ state->npn_valid = false;
+ }
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- !CERT_LIST_END(node, cert_list);
- node = CERT_LIST_NEXT(node)) {
- if (node->cert->derCert.len > std::numeric_limits<uint16>::max()) {
- CERT_DestroyCertList(cert_list);
+ state->certs.clear();
+ PeerCertificateChain certs(nss_fd_);
+ for (unsigned i = 0; i < certs.size(); i++) {
+ if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
return;
- }
- if (node->cert->isRoot == PR_TRUE)
- continue;
+
state->certs.push_back(std::string(
- reinterpret_cast<char*>(node->cert->derCert.data),
- node->cert->derCert.len));
+ reinterpret_cast<char*>(certs[i]->derCert.data),
+ certs[i]->derCert.len));
}
LOG(ERROR) << "Setting Snap Start info " << hostname_;
ssl_host_info_->Persist();
-
- CERT_DestroyCertList(cert_list);
}
static void DestroyCertificates(CERTCertificate** certs, unsigned len) {
@@ -625,6 +639,16 @@ int SSLClientSocketNSS::Connect(CompletionCallback* callback) {
return rv;
}
+ // Attempt to initialize the peer name. In the case of TCP FastOpen,
+ // we don't have the peer yet.
+ if (!UsingTCPFastOpen()) {
+ rv = InitializeSSLPeerName();
+ if (rv != OK) {
+ net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+ return rv;
+ }
+ }
+
if (ssl_config_.snap_start_enabled && ssl_host_info_.get()) {
GotoState(STATE_SNAP_START_LOAD_INFO);
} else {
@@ -655,28 +679,6 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
}
- // Tell NSS who we're connected to
- AddressList peer_address;
- int err = transport_->socket()->GetPeerAddress(&peer_address);
- if (err != OK)
- return err;
-
- const struct addrinfo* ai = peer_address.head();
-
- PRNetAddr peername;
- memset(&peername, 0, sizeof(peername));
- DCHECK_LE(ai->ai_addrlen, sizeof(peername));
- size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername));
- memcpy(&peername, ai->ai_addr, len);
-
- // Adjust the address family field for BSD, whose sockaddr
- // structure has a one-byte length and one-byte address family
- // field at the beginning. PRNetAddr has a two-byte address
- // family field at the beginning.
- peername.raw.family = ai->ai_addr->sa_family;
-
- memio_SetPeerName(nss_fd_, &peername);
-
// Grab pointer to buffers
nss_bufs_ = memio_GetSecret(nss_fd_);
@@ -761,7 +763,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// TODO(agl): check that SSL_ENABLE_SNAP_START actually does something in the
// current NSS code.
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SNAP_START,
- SSLConfigService::snap_start_enabled());
+ ssl_config_.snap_start_enabled);
if (rv != SECSuccess)
VLOG(1) << "SSL_ENABLE_SNAP_START failed. Old system nss?";
#endif
@@ -816,7 +818,12 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
+#if defined(NSS_PLATFORM_CLIENT_AUTH)
+ rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler,
+ this);
+#else
rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
+#endif
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", "");
return ERR_UNEXPECTED;
@@ -831,6 +838,36 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// Tell SSL the hostname we're trying to connect to.
SSL_SetURL(nss_fd_, hostname_.c_str());
+ // Tell SSL we're a client; needed if not letting NSPR do socket I/O
+ SSL_ResetHandshake(nss_fd_, 0);
+
+ return OK;
+}
+
+int SSLClientSocketNSS::InitializeSSLPeerName() {
+ // Tell NSS who we're connected to
+ AddressList peer_address;
+ int err = transport_->socket()->GetPeerAddress(&peer_address);
+ if (err != OK)
+ return err;
+
+ const struct addrinfo* ai = peer_address.head();
+
+ PRNetAddr peername;
+ memset(&peername, 0, sizeof(peername));
+ DCHECK_LE(ai->ai_addrlen, sizeof(peername));
+ size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
+ sizeof(peername));
+ memcpy(&peername, ai->ai_addr, len);
+
+ // Adjust the address family field for BSD, whose sockaddr
+ // structure has a one-byte length and one-byte address family
+ // field at the beginning. PRNetAddr has a two-byte address
+ // family field at the beginning.
+ peername.raw.family = ai->ai_addr->sa_family;
+
+ memio_SetPeerName(nss_fd_, &peername);
+
// Set the peer ID for session reuse. This is necessary when we create an
// SSL tunnel through a proxy -- GetPeerName returns the proxy's address
// rather than the destination server's address in that case.
@@ -838,13 +875,11 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// used.
std::string peer_id = base::StringPrintf("%s:%d", hostname_.c_str(),
peer_address.GetPort());
- rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
+ SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
if (rv != SECSuccess)
LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
- // Tell SSL we're a client; needed if not letting NSPR do socket I/O
- SSL_ResetHandshake(nss_fd_, 0);
-
+ peername_initialized_ = true;
return OK;
}
@@ -885,11 +920,14 @@ void SSLClientSocketNSS::Disconnect() {
CERT_DestroyCertificate(server_cert_nss_);
server_cert_nss_ = NULL;
}
- server_cert_verify_result_.Reset();
+ local_server_cert_verify_result_.Reset();
+ server_cert_verify_result_ = NULL;
+ ssl_connection_status_ = 0;
completed_handshake_ = false;
pseudo_connected_ = false;
eset_mitm_detected_ = false;
- netnanny_mitm_detected_= false;
+ predicted_cert_chain_correct_ = false;
+ peername_initialized_ = false;
nss_bufs_ = NULL;
client_certs_.clear();
client_auth_cert_needed_ = false;
@@ -955,6 +993,14 @@ bool SSLClientSocketNSS::WasEverUsed() const {
return false;
}
+bool SSLClientSocketNSS::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
EnterFunction(buf_len);
@@ -1044,157 +1090,110 @@ bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
return transport_->socket()->SetSendBufferSize(size);
}
-#if defined(OS_WIN)
-// static
-X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert(
- const SECItem& der_cert) {
- // TODO(wtc): close cert_store_ at shutdown.
- if (!cert_store_)
- cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
-
- X509Certificate::OSCertHandle cert_handle = NULL;
- BOOL ok = CertAddEncodedCertificateToStore(
- cert_store_, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- der_cert.data, der_cert.len, CERT_STORE_ADD_USE_EXISTING, &cert_handle);
- return ok ? cert_handle : NULL;
-}
-#elif defined(OS_MACOSX)
-// static
-X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert(
- const SECItem& der_cert) {
- return X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<char*>(der_cert.data), der_cert.len);
-}
-#endif
-
+// Sets server_cert_ and server_cert_nss_ if not yet set.
+// Returns server_cert_.
X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
- // We set the server_cert_ from HandshakeCallback(), but this handler
- // does not necessarily get called if we are continuing a cached SSL
- // session.
+ // We set the server_cert_ from HandshakeCallback().
if (server_cert_ == NULL) {
server_cert_nss_ = SSL_PeerCertificate(nss_fd_);
if (server_cert_nss_) {
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // Get each of the intermediate certificates in the server's chain.
- // These will be added to the server's X509Certificate object, making
- // them available to X509Certificate::Verify() for chain building.
- X509Certificate::OSCertHandles intermediate_ca_certs;
- X509Certificate::OSCertHandle cert_handle = NULL;
- CERTCertList* cert_list = CERT_GetCertChainFromCert(
- server_cert_nss_, PR_Now(), certUsageSSLCA);
- if (cert_list) {
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- !CERT_LIST_END(node, cert_list);
- node = CERT_LIST_NEXT(node)) {
- if (node->cert == server_cert_nss_)
- continue;
-#if defined(OS_WIN)
- // Work around http://crbug.com/43538 by not importing the
- // problematic COMODO EV SGC CA certificate. CryptoAPI will
- // download a good certificate for that CA, issued by COMODO
- // Certification Authority, using the AIA extension in the server
- // certificate.
- if (IsProblematicComodoEVCACert(*node->cert))
- continue;
-#endif
- cert_handle = CreateOSCert(node->cert->derCert);
- DCHECK(cert_handle);
- intermediate_ca_certs.push_back(cert_handle);
- }
- CERT_DestroyCertList(cert_list);
- }
-
- // Finally create the X509Certificate object.
- cert_handle = CreateOSCert(server_cert_nss_->derCert);
- DCHECK(cert_handle);
- server_cert_ = X509Certificate::CreateFromHandle(
- cert_handle,
- X509Certificate::SOURCE_FROM_NETWORK,
- intermediate_ca_certs);
- X509Certificate::FreeOSCertHandle(cert_handle);
- for (size_t i = 0; i < intermediate_ca_certs.size(); ++i)
- X509Certificate::FreeOSCertHandle(intermediate_ca_certs[i]);
-#else
- server_cert_ = X509Certificate::CreateFromHandle(
- server_cert_nss_,
- X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
-#endif
+ PeerCertificateChain certs(nss_fd_);
+ server_cert_ = X509Certificate::CreateFromDERCertChain(
+ certs.AsStringPieceVector());
}
}
return server_cert_;
}
-// Log an informational message if the server does not support secure
-// renegotiation (RFC 5746).
-void SSLClientSocketNSS::CheckSecureRenegotiation() const {
- // 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 received_renego_info;
- if (SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
- &received_renego_info) == SECSuccess &&
- !received_renego_info) {
- VLOG(1) << "The server " << hostname_
- << " does not support the TLS renegotiation_info extension.";
- }
-#endif
-}
-
-void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
- EnterFunction("");
- ssl_info->Reset();
-
- if (!server_cert_) {
- LOG(DFATAL) << "!server_cert_";
- return;
- }
-
+// Sets ssl_connection_status_.
+void SSLClientSocketNSS::UpdateConnectionStatus() {
SSLChannelInfo channel_info;
SECStatus ok = SSL_GetChannelInfo(nss_fd_,
&channel_info, sizeof(channel_info));
if (ok == SECSuccess &&
channel_info.length == sizeof(channel_info) &&
channel_info.cipherSuite) {
- SSLCipherSuiteInfo cipher_info;
- ok = SSL_GetCipherSuiteInfo(channel_info.cipherSuite,
- &cipher_info, sizeof(cipher_info));
- if (ok == SECSuccess) {
- ssl_info->security_bits = cipher_info.effectiveKeyBits;
- } else {
- ssl_info->security_bits = -1;
- LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
- << " for cipherSuite " << channel_info.cipherSuite;
- }
- ssl_info->connection_status |=
- (((int)channel_info.cipherSuite) & SSL_CONNECTION_CIPHERSUITE_MASK) <<
+ ssl_connection_status_ |=
+ (static_cast<int>(channel_info.cipherSuite) &
+ SSL_CONNECTION_CIPHERSUITE_MASK) <<
SSL_CONNECTION_CIPHERSUITE_SHIFT;
- ssl_info->connection_status |=
- (((int)channel_info.compressionMethod) &
+ ssl_connection_status_ |=
+ (static_cast<int>(channel_info.compressionMethod) &
SSL_CONNECTION_COMPRESSION_MASK) <<
SSL_CONNECTION_COMPRESSION_SHIFT;
- UpdateServerCert();
+ // 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.
+ 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
+ // version 2.
+ version = SSL_CONNECTION_VERSION_SSL2;
+ } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
+ 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) {
+ version = SSL_CONNECTION_VERSION_TLS1_1;
+ } else if (channel_info.protocolVersion == 0x0303) {
+ version = SSL_CONNECTION_VERSION_TLS1_2;
+ }
+ ssl_connection_status_ |=
+ (version & SSL_CONNECTION_VERSION_MASK) <<
+ SSL_CONNECTION_VERSION_SHIFT;
}
- ssl_info->cert_status = server_cert_verify_result_.cert_status;
- DCHECK(server_cert_ != NULL);
- ssl_info->cert = server_cert_;
+ // 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);
if (ok == SECSuccess) {
- if (!peer_supports_renego_ext)
- ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
+ if (!peer_supports_renego_ext) {
+ ssl_connection_status_ |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
+ // Log an informational message if the server does not support secure
+ // renegotiation (RFC 5746).
+ VLOG(1) << "The server " << hostname_
+ << " does not support the TLS renegotiation_info extension.";
+ }
UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
- (int)peer_supports_renego_ext, 2);
+ peer_supports_renego_ext, 2);
}
+#endif
if (ssl_config_.ssl3_fallback)
- ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
+ ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK;
+}
+
+void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
+ EnterFunction("");
+ ssl_info->Reset();
+ if (!server_cert_) {
+ LOG(DFATAL) << "!server_cert_";
+ return;
+ }
+
+ ssl_info->cert_status = server_cert_verify_result_->cert_status;
+ DCHECK(server_cert_ != NULL);
+ ssl_info->cert = server_cert_;
+ ssl_info->connection_status = ssl_connection_status_;
+
+ PRUint16 cipher_suite =
+ SSLConnectionStatusToCipherSuite(ssl_connection_status_);
+ SSLCipherSuiteInfo cipher_info;
+ SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
+ &cipher_info, sizeof(cipher_info));
+ if (ok == SECSuccess) {
+ ssl_info->security_bits = cipher_info.effectiveKeyBits;
+ } else {
+ ssl_info->security_bits = -1;
+ LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
+ << " for cipherSuite " << cipher_suite;
+ }
LeaveFunction("");
}
@@ -1378,8 +1377,11 @@ static PRErrorCode MapErrorToNSS(int result) {
case ERR_IO_PENDING:
return PR_WOULD_BLOCK_ERROR;
case ERR_ACCESS_DENIED:
+ case ERR_NETWORK_ACCESS_DENIED:
// For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
return PR_NO_ACCESS_RIGHTS_ERROR;
+ case ERR_NOT_IMPLEMENTED:
+ return PR_NOT_IMPLEMENTED_ERROR;
case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN.
return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation.
case ERR_CONNECTION_TIMED_OUT:
@@ -1437,7 +1439,7 @@ int SSLClientSocketNSS::BufferSend(void) {
int rv = 0;
if (len) {
- scoped_refptr<IOBuffer> send_buffer = new IOBuffer(len);
+ scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
memcpy(send_buffer->data(), buf1, len1);
memcpy(send_buffer->data() + len1, buf2, len2);
rv = transport_->socket()->Write(send_buffer, len,
@@ -1455,6 +1457,11 @@ int SSLClientSocketNSS::BufferSend(void) {
void SSLClientSocketNSS::BufferSendComplete(int result) {
EnterFunction(result);
+
+ // In the case of TCP FastOpen, connect is now finished.
+ if (!peername_initialized_ && UsingTCPFastOpen())
+ InitializeSSLPeerName();
+
memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
transport_send_busy_ = false;
OnSendComplete(result);
@@ -1565,7 +1572,8 @@ int SSLClientSocketNSS::DoReadLoop(int result) {
if (!nss_bufs_) {
LOG(DFATAL) << "!nss_bufs_";
int rv = ERR_UNEXPECTED;
- net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, new SSLErrorParams(rv, 0));
+ net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, 0)));
return rv;
}
@@ -1591,7 +1599,8 @@ int SSLClientSocketNSS::DoWriteLoop(int result) {
if (!nss_bufs_) {
LOG(DFATAL) << "!nss_bufs_";
int rv = ERR_UNEXPECTED;
- net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, new SSLErrorParams(rv, 0));
+ net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, 0)));
return rv;
}
@@ -1624,16 +1633,10 @@ SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
// different reads or not, depending on network conditions.
PRBool false_start = 0;
SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start);
- if (rv != SECSuccess)
- NOTREACHED();
+ DCHECK_EQ(SECSuccess, rv);
+
if (false_start) {
SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
- if (!that->handshake_callback_called_) {
- that->corked_ = true;
- that->uncork_timer_.Start(
- base::TimeDelta::FromMilliseconds(kCorkTimeoutMs),
- that, &SSLClientSocketNSS::UncorkAfterTimeout);
- }
// ESET anti-virus is capable of intercepting HTTPS connections on Windows.
// However, it is False Start intolerant and causes the connections to hang
@@ -1646,12 +1649,24 @@ SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
if (common_name) {
if (strcmp(common_name, "ESET_RootSslCert") == 0)
that->eset_mitm_detected_ = true;
- if (strcmp(common_name, "ContentWatch Root Certificate Authority") == 0)
- that->netnanny_mitm_detected_ = true;
+ if (strcmp(common_name, "ContentWatch Root Certificate Authority") == 0) {
+ // This is NetNanny. NetNanny are updating their product so we
+ // silently disable False Start for now.
+ rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE);
+ DCHECK_EQ(SECSuccess, rv);
+ false_start = 0;
+ }
PORT_Free(common_name);
}
CERT_DestroyCertificate(cert);
}
+
+ if (false_start && !that->handshake_callback_called_) {
+ that->corked_ = true;
+ that->uncork_timer_.Start(
+ base::TimeDelta::FromMilliseconds(kCorkTimeoutMs),
+ that, &SSLClientSocketNSS::UncorkAfterTimeout);
+ }
}
#endif
@@ -1659,24 +1674,69 @@ SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
return SECSuccess;
}
+#if defined(NSS_PLATFORM_CLIENT_AUTH)
// static
// NSS calls this if a client certificate is needed.
-// Based on Mozilla's NSS_GetClientAuthData.
-SECStatus SSLClientSocketNSS::ClientAuthHandler(
+SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
void* arg,
PRFileDesc* socket,
CERTDistNames* ca_names,
- CERTCertificate** result_certificate,
- SECKEYPrivateKey** result_private_key) {
+ CERTCertList** result_certs,
+ void** result_private_key) {
SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
-
#if defined(OS_WIN)
if (that->ssl_config_.send_client_cert) {
- // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
- // CryptoAPI yet (http://crbug.com/37560), so client_cert must be NULL.
- DCHECK(!that->ssl_config_.client_cert);
+ if (that->ssl_config_.client_cert) {
+ PCCERT_CONTEXT cert_context =
+ that->ssl_config_.client_cert->os_cert_handle();
+ HCRYPTPROV provider = NULL;
+ DWORD key_spec = AT_KEYEXCHANGE;
+ BOOL must_free = FALSE;
+ BOOL acquired_key = CryptAcquireCertificatePrivateKey(
+ cert_context,
+ CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
+ NULL, &provider, &key_spec, &must_free);
+ if (acquired_key && provider) {
+ DCHECK_NE(key_spec, CERT_NCRYPT_KEY_SPEC);
+
+ // The certificate cache may have been updated/used, in which case,
+ // duplicate the existing handle, since NSS will free it when no
+ // longer in use.
+ if (!must_free)
+ CryptContextAddRef(provider, NULL, 0);
+
+ SECItem der_cert;
+ der_cert.type = siDERCertBuffer;
+ der_cert.data = cert_context->pbCertEncoded;
+ der_cert.len = cert_context->cbCertEncoded;
+
+ // TODO(rsleevi): Error checking for NSS allocation errors.
+ *result_certs = CERT_NewCertList();
+ CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
+ CERTCertificate* user_cert = CERT_NewTempCertificate(
+ db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
+ CERT_AddCertToListTail(*result_certs, user_cert);
+
+ // Add the intermediates.
+ X509Certificate::OSCertHandles intermediates =
+ that->ssl_config_.client_cert->GetIntermediateCertificates();
+ for (X509Certificate::OSCertHandles::const_iterator it =
+ intermediates.begin(); it != intermediates.end(); ++it) {
+ der_cert.data = (*it)->pbCertEncoded;
+ der_cert.len = (*it)->cbCertEncoded;
+
+ CERTCertificate* intermediate = CERT_NewTempCertificate(
+ db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
+ CERT_AddCertToListTail(*result_certs, intermediate);
+ }
+ // TODO(wtc): |key_spec| should be passed along with |provider|.
+ *result_private_key = reinterpret_cast<void*>(provider);
+ return SECSuccess;
+ }
+ LOG(WARNING) << "Client cert found without private key";
+ }
// Send no client certificate.
return SECFailure;
}
@@ -1708,10 +1768,6 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler(
PCCERT_CHAIN_CONTEXT chain_context = NULL;
- // TODO(wtc): close cert_store_ at shutdown.
- if (!cert_store_)
- cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
-
for (;;) {
// Find a certificate chain.
chain_context = CertFindChainInStore(my_cert_store,
@@ -1733,18 +1789,42 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler(
// Copy it to our own certificate store, so that we can close the "MY"
// certificate store before returning from this function.
PCCERT_CONTEXT cert_context2;
- BOOL ok = CertAddCertificateContextToStore(cert_store_, cert_context,
+ BOOL ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
+ cert_context,
CERT_STORE_ADD_USE_EXISTING,
&cert_context2);
if (!ok) {
NOTREACHED();
continue;
}
+
+ // Copy the rest of the chain to our own store as well. Copying the chain
+ // stops gracefully if an error is encountered, with the partial chain
+ // being used as the intermediates, rather than failing to consider the
+ // client certificate.
+ net::X509Certificate::OSCertHandles intermediates;
+ for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; i++) {
+ PCCERT_CONTEXT intermediate_copy;
+ ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
+ chain_context->rgpChain[0]->rgpElement[i]->pCertContext,
+ CERT_STORE_ADD_USE_EXISTING, &intermediate_copy);
+ if (!ok) {
+ NOTREACHED();
+ break;
+ }
+ intermediates.push_back(intermediate_copy);
+ }
+
scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
- X509Certificate::FreeOSCertHandle(cert_context2);
+ intermediates);
that->client_certs_.push_back(cert);
+
+ X509Certificate::FreeOSCertHandle(cert_context2);
+ for (net::X509Certificate::OSCertHandles::iterator it =
+ intermediates.begin(); it != intermediates.end(); ++it) {
+ net::X509Certificate::FreeOSCertHandle(*it);
+ }
}
BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
@@ -1755,9 +1835,63 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler(
return SECWouldBlock;
#elif defined(OS_MACOSX)
if (that->ssl_config_.send_client_cert) {
- // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
- // CDSA/CSSM yet (http://crbug.com/45369), so client_cert must be NULL.
- DCHECK(!that->ssl_config_.client_cert);
+ if (that->ssl_config_.client_cert) {
+ OSStatus os_error = noErr;
+ SecIdentityRef identity = NULL;
+ SecKeyRef private_key = NULL;
+ CFArrayRef chain =
+ that->ssl_config_.client_cert->CreateClientCertificateChain();
+ if (chain) {
+ identity = reinterpret_cast<SecIdentityRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(chain, 0)));
+ }
+ if (identity)
+ os_error = SecIdentityCopyPrivateKey(identity, &private_key);
+
+ if (chain && identity && os_error == noErr) {
+ // TODO(rsleevi): Error checking for NSS allocation errors.
+ *result_certs = CERT_NewCertList();
+ *result_private_key = reinterpret_cast<void*>(private_key);
+
+ for (CFIndex i = 0; i < CFArrayGetCount(chain); ++i) {
+ CSSM_DATA cert_data;
+ SecCertificateRef cert_ref;
+ if (i == 0) {
+ cert_ref = that->ssl_config_.client_cert->os_cert_handle();
+ } else {
+ cert_ref = reinterpret_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(chain, i)));
+ }
+ os_error = SecCertificateGetData(cert_ref, &cert_data);
+ if (os_error != noErr)
+ break;
+
+ SECItem der_cert;
+ der_cert.type = siDERCertBuffer;
+ der_cert.data = cert_data.Data;
+ der_cert.len = cert_data.Length;
+ CERTCertificate* nss_cert = CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
+ CERT_AddCertToListTail(*result_certs, nss_cert);
+ }
+ }
+ if (os_error == noErr) {
+ CFRelease(chain);
+ return SECSuccess;
+ }
+ LOG(WARNING) << "Client cert found, but could not be used: "
+ << os_error;
+ if (*result_certs) {
+ CERT_DestroyCertList(*result_certs);
+ *result_certs = NULL;
+ }
+ if (*result_private_key)
+ *result_private_key = NULL;
+ if (private_key)
+ CFRelease(private_key);
+ if (chain)
+ CFRelease(chain);
+ }
// Send no client certificate.
return SECFailure;
}
@@ -1785,6 +1919,24 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler(
// handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
return SECWouldBlock;
#else
+ return SECFailure;
+#endif
+}
+
+#else // NSS_PLATFORM_CLIENT_AUTH
+
+// static
+// NSS calls this if a client certificate is needed.
+// Based on Mozilla's NSS_GetClientAuthData.
+SECStatus SSLClientSocketNSS::ClientAuthHandler(
+ void* arg,
+ PRFileDesc* socket,
+ CERTDistNames* ca_names,
+ CERTCertificate** result_certificate,
+ SECKEYPrivateKey** result_private_key) {
+ SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
+
+ that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
void* wincx = SSL_RevealPinArg(socket);
// Second pass: a client certificate should have been selected.
@@ -1838,8 +1990,8 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler(
// Tell NSS to suspend the client authentication. We will then abort the
// handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
return SECWouldBlock;
-#endif
}
+#endif // NSS_PLATFORM_CLIENT_AUTH
// static
// NSS calls this when handshake is completed.
@@ -1852,22 +2004,32 @@ void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
that->handshake_callback_called_ = true;
that->UpdateServerCert();
-
- that->CheckSecureRenegotiation();
+ that->UpdateConnectionStatus();
}
int SSLClientSocketNSS::DoSnapStartLoadInfo() {
EnterFunction("");
int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
+ GotoState(STATE_HANDSHAKE);
if (rv == OK) {
- if (LoadSnapStartInfo()) {
- pseudo_connected_ = true;
- GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
- if (user_connect_callback_)
- DoConnectCallback(OK);
- } else {
- GotoState(STATE_HANDSHAKE);
+ if (ssl_host_info_->WaitForCertVerification(NULL) == OK) {
+ if (LoadSnapStartInfo()) {
+ pseudo_connected_ = true;
+ GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
+ if (user_connect_callback_)
+ DoConnectCallback(OK);
+ }
+ } else if (!ssl_host_info_->state().server_hello.empty()) {
+ // A non-empty ServerHello suggests that we would have tried a Snap Start
+ // connection.
+ base::TimeTicks now = base::TimeTicks::Now();
+ const base::TimeDelta duration =
+ now - ssl_host_info_->verification_start_time();
+ UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration);
+ VLOG(1) << "Cannot snap start because verification isn't ready. "
+ << "Wanted verification after "
+ << duration.InMilliseconds() << "ms";
}
} else {
DCHECK_EQ(ERR_IO_PENDING, rv);
@@ -1909,7 +2071,6 @@ int SSLClientSocketNSS::DoSnapStartWaitForWrite() {
nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()),
user_write_buf_len_);
DCHECK_EQ(SECSuccess, rv);
- user_write_buf_ = NULL;
GotoState(STATE_HANDSHAKE);
LeaveFunction("");
@@ -1924,7 +2085,7 @@ int SSLClientSocketNSS::DoHandshake() {
if (client_auth_cert_needed_) {
net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- new SSLErrorParams(net_error, 0));
+ make_scoped_refptr(new SSLErrorParams(net_error, 0)));
// If the handshake already succeeded (because the server requests but
// doesn't require a client cert), we need to invalidate the SSL session
// so that we won't try to resume the non-client-authenticated session in
@@ -1937,9 +2098,27 @@ int SSLClientSocketNSS::DoHandshake() {
if (handshake_callback_called_) {
if (eset_mitm_detected_) {
net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION;
- } else if (netnanny_mitm_detected_) {
- net_error = ERR_NETNANNY_SSL_INTERCEPTION;
} else {
+ // We need to see if the predicted certificate chain (in
+ // |ssl_host_info_->state().certs) matches the actual certificate chain
+ // before we call SaveSnapStartInfo, as that will update
+ // |ssl_host_info_|.
+ if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
+ PeerCertificateChain certs(nss_fd_);
+ const SSLHostInfo::State& state = ssl_host_info_->state();
+ predicted_cert_chain_correct_ = certs.size() == state.certs.size();
+ if (predicted_cert_chain_correct_) {
+ for (unsigned i = 0; i < certs.size(); i++) {
+ if (certs[i]->derCert.len != state.certs[i].size() ||
+ memcmp(certs[i]->derCert.data, state.certs[i].data(),
+ certs[i]->derCert.len) != 0) {
+ predicted_cert_chain_correct_ = false;
+ break;
+ }
+ }
+ }
+ }
+
SaveSnapStartInfo();
// SSL handshake is completed. It's possible that we mispredicted the
// NPN agreed protocol. In this case, we've just sent a request in the
@@ -1961,7 +2140,7 @@ int SSLClientSocketNSS::DoHandshake() {
rv = SECFailure;
net_error = ERR_SSL_PROTOCOL_ERROR;
net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- new SSLErrorParams(net_error, 0));
+ make_scoped_refptr(new SSLErrorParams(net_error, 0)));
}
} else {
PRErrorCode prerr = PR_GetError();
@@ -1973,8 +2152,9 @@ int SSLClientSocketNSS::DoHandshake() {
} else {
LOG(ERROR) << "handshake failed; NSS error code " << prerr
<< ", net_error " << net_error;
- net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- new SSLErrorParams(net_error, prerr));
+ net_log_.AddEvent(
+ NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
}
}
@@ -2135,10 +2315,19 @@ static DNSValidationResult CheckDNSSECChain(
}
int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
+#if !defined(USE_OPENSSL)
+ if (ssl_config_.dns_cert_provenance_checking_enabled && dnsrr_resolver_) {
+ PeerCertificateChain certs(nss_fd_);
+ DoAsyncDNSCertProvenanceVerification(
+ hostname_, dnsrr_resolver_, certs.AsStringPieceVector());
+ }
+#endif
+
if (ssl_config_.dnssec_enabled) {
DNSValidationResult r = CheckDNSSECChain(hostname_, server_cert_nss_);
if (r == DNSVR_SUCCESS) {
- server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+ local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+ server_cert_verify_result_ = &local_server_cert_verify_result_;
GotoState(STATE_VERIFY_CERT_COMPLETE);
return OK;
}
@@ -2183,13 +2372,15 @@ int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
switch (r) {
case DNSVR_FAILURE:
GotoState(STATE_VERIFY_CERT_COMPLETE);
- server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS;
+ local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS;
+ server_cert_verify_result_ = &local_server_cert_verify_result_;
return ERR_CERT_NOT_IN_DNS;
case DNSVR_CONTINUE:
GotoState(STATE_VERIFY_CERT);
break;
case DNSVR_SUCCESS:
- server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+ local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+ server_cert_verify_result_ = &local_server_cert_verify_result_;
GotoState(STATE_VERIFY_CERT_COMPLETE);
break;
default:
@@ -2202,16 +2393,35 @@ int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
int SSLClientSocketNSS::DoVerifyCert(int result) {
DCHECK(server_cert_);
+
GotoState(STATE_VERIFY_CERT_COMPLETE);
- int flags = 0;
+ if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
+ predicted_cert_chain_correct_) {
+ // If the SSLHostInfo had a prediction for the certificate chain of this
+ // server then it will have optimistically started a verification of that
+ // chain. So, if the prediction was correct, we should wait for that
+ // verification to finish rather than start our own.
+ net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL);
+ UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2);
+ base::TimeTicks now = base::TimeTicks::Now();
+ UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
+ now - ssl_host_info_->verification_start_time());
+ server_cert_verify_result_ = &ssl_host_info_->cert_verify_result();
+ return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2);
+ }
+
+ int flags = 0;
if (ssl_config_.rev_checking_enabled)
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
if (ssl_config_.verify_ev_cert)
flags |= X509Certificate::VERIFY_EV_CERT;
verifier_.reset(new CertVerifier);
+ server_cert_verify_result_ = &local_server_cert_verify_result_;
return verifier_->Verify(server_cert_, hostname_, flags,
- &server_cert_verify_result_,
+ &local_server_cert_verify_result_,
&handshake_io_callback_);
}
@@ -2220,45 +2430,15 @@ int SSLClientSocketNSS::DoVerifyCert(int result) {
int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
verifier_.reset();
- // Using Snap Start disables certificate verification for now.
- if (SSLConfigService::snap_start_enabled())
- result = OK;
-
- if (result == OK) {
- // Remember the intermediate CA certs if the server sends them to us.
- //
- // We used to remember the intermediate CA certs in the NSS database
- // persistently. However, NSS opens a connection to the SQLite database
- // during NSS initialization and doesn't close the connection until NSS
- // shuts down. If the file system where the database resides is gone,
- // the database connection goes bad. What's worse, the connection won't
- // recover when the file system comes back. Until this NSS or SQLite bug
- // is fixed, we need to avoid using the NSS database for non-essential
- // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
- // http://crbug.com/15630 for more info.
- CERTCertList* cert_list = CERT_GetCertChainFromCert(
- server_cert_nss_, PR_Now(), certUsageSSLCA);
- if (cert_list) {
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- !CERT_LIST_END(node, cert_list);
- node = CERT_LIST_NEXT(node)) {
- if (node->cert->slot || node->cert->isRoot || node->cert->isperm ||
- node->cert == server_cert_nss_) {
- // Some certs we don't want to remember are:
- // - found on a token.
- // - the root cert.
- // - already stored in perm db.
- // - the server cert itself.
- continue;
- }
-
- // We have found a CA cert that we want to remember.
- // TODO(wtc): Remember the intermediate CA certs in a std::set
- // temporarily (http://crbug.com/15630).
- }
- CERT_DestroyCertList(cert_list);
- }
- }
+ // We used to remember the intermediate CA certs in the NSS database
+ // persistently. However, NSS opens a connection to the SQLite database
+ // during NSS initialization and doesn't close the connection until NSS
+ // shuts down. If the file system where the database resides is gone,
+ // the database connection goes bad. What's worse, the connection won't
+ // recover when the file system comes back. Until this NSS or SQLite bug
+ // is fixed, we need to avoid using the NSS database for non-essential
+ // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
+ // http://crbug.com/15630 for more info.
// If we have been explicitly told to accept this certificate, override the
// result of verifier_.Verify.
@@ -2272,16 +2452,45 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
result = OK;
}
+ if (result == OK)
+ LogConnectionTypeMetrics();
+
completed_handshake_ = true;
// TODO(ukai): we may not need this call because it is now harmless to have a
// session with a bad cert.
InvalidateSessionIfBadCertificate();
- // Likewise, if we merged a Write call into the handshake we need to make the
+ // If we merged a Write call into the handshake we need to make the
// callback now.
if (user_write_callback_) {
corked_ = false;
- DoWriteCallback(user_write_buf_len_);
+ if (result != OK) {
+ DoWriteCallback(result);
+ } else {
+ SSLSnapStartResult snap_start_type;
+ SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
+ DCHECK_EQ(rv, SECSuccess);
+ DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE);
+ if (snap_start_type == SSL_SNAP_START_RECOVERY ||
+ snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) {
+ // If we mispredicted the server's handshake then Snap Start will have
+ // triggered a recovery mode. The misprediction could have been caused
+ // by the server having a different certificate so the application data
+ // wasn't resent. Now that we have verified the certificate, we need to
+ // resend the application data.
+ int bytes_written = DoPayloadWrite();
+ if (bytes_written != ERR_IO_PENDING)
+ DoWriteCallback(bytes_written);
+ } else {
+ DoWriteCallback(user_write_buf_len_);
+ }
+ }
+ }
+
+ if (user_read_callback_) {
+ int rv = DoReadLoop(OK);
+ if (rv != ERR_IO_PENDING)
+ DoReadCallback(rv);
}
// Exit DoHandshakeLoop and return the result to the caller to Connect.
@@ -2300,7 +2509,7 @@ int SSLClientSocketNSS::DoPayloadRead() {
LeaveFunction("");
rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
- new SSLErrorParams(rv, 0));
+ make_scoped_refptr(new SSLErrorParams(rv, 0)));
return rv;
}
if (rv >= 0) {
@@ -2315,7 +2524,8 @@ int SSLClientSocketNSS::DoPayloadRead() {
}
LeaveFunction("");
rv = MapNSPRError(prerr);
- net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, new SSLErrorParams(rv, prerr));
+ net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, prerr)));
return rv;
}
@@ -2336,8 +2546,40 @@ int SSLClientSocketNSS::DoPayloadWrite() {
LeaveFunction("");
rv = MapNSPRError(prerr);
net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
- new SSLErrorParams(rv, prerr));
+ make_scoped_refptr(new SSLErrorParams(rv, prerr)));
return rv;
}
+void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
+ UpdateConnectionTypeHistograms(CONNECTION_SSL);
+ if (server_cert_verify_result_->has_md5)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
+ if (server_cert_verify_result_->has_md2)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
+ if (server_cert_verify_result_->has_md4)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
+ if (server_cert_verify_result_->has_md5_ca)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
+ if (server_cert_verify_result_->has_md2_ca)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
+ int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
+ switch (ssl_version) {
+ case SSL_CONNECTION_VERSION_SSL2:
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
+ break;
+ case SSL_CONNECTION_VERSION_SSL3:
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
+ break;
+ case SSL_CONNECTION_VERSION_TLS1:
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
+ break;
+ case SSL_CONNECTION_VERSION_TLS1_1:
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
+ break;
+ case SSL_CONNECTION_VERSION_TLS1_2:
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
+ break;
+ };
+}
+
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 56d16b2..87f7b92 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -30,6 +30,7 @@ namespace net {
class BoundNetLog;
class CertVerifier;
class ClientSocketHandle;
+class DnsRRResolver;
class SSLHostInfo;
class X509Certificate;
@@ -43,14 +44,15 @@ class SSLClientSocketNSS : public SSLClientSocket {
SSLClientSocketNSS(ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
~SSLClientSocketNSS();
// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
virtual NextProtoStatus GetNextProto(std::string* proto);
- virtual void UseDNSSEC(DNSSECProvider*);
+ virtual void UseDNSSEC(DNSSECProvider* provider);
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
@@ -62,6 +64,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
@@ -73,13 +76,16 @@ class SSLClientSocketNSS : public SSLClientSocket {
// Initializes NSS SSL options. Returns a net error code.
int InitializeSSLOptions();
+ // Initializes the socket peer name in SSL. Returns a net error code.
+ int InitializeSSLPeerName();
+
void InvalidateSessionIfBadCertificate();
#if defined(OS_MACOSX) || defined(OS_WIN)
// Creates an OS certificate from a DER-encoded certificate.
static X509Certificate::OSCertHandle CreateOSCert(const SECItem& der_cert);
#endif
X509Certificate* UpdateServerCert();
- void CheckSecureRenegotiation() const;
+ void UpdateConnectionStatus();
void DoReadCallback(int result);
void DoWriteCallback(int result);
void DoConnectCallback(int result);
@@ -101,6 +107,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
int DoVerifyCertComplete(int result);
int DoPayloadRead();
int DoPayloadWrite();
+ void LogConnectionTypeMetrics() const;
int Init();
void SaveSnapStartInfo();
bool LoadSnapStartInfo();
@@ -118,11 +125,19 @@ class SSLClientSocketNSS : public SSLClientSocket {
static SECStatus OwnAuthCertHandler(void* arg, PRFileDesc* socket,
PRBool checksig, PRBool is_server);
// NSS calls this when client authentication is requested.
+#if defined(NSS_PLATFORM_CLIENT_AUTH)
+ static SECStatus PlatformClientAuthHandler(void* arg,
+ PRFileDesc* socket,
+ CERTDistNames* ca_names,
+ CERTCertList** result_certs,
+ void** result_private_key);
+#else
static SECStatus ClientAuthHandler(void* arg,
PRFileDesc* socket,
CERTDistNames* ca_names,
CERTCertificate** result_certificate,
SECKEYPrivateKey** result_private_key);
+#endif
// NSS calls this when handshake is completed. We pass 'this' as the second
// argument.
static void HandshakeCallback(PRFileDesc* socket, void* arg);
@@ -161,7 +176,12 @@ class SSLClientSocketNSS : public SSLClientSocket {
// converted into an X509Certificate object (server_cert_).
scoped_refptr<X509Certificate> server_cert_;
CERTCertificate* server_cert_nss_;
- CertVerifyResult server_cert_verify_result_;
+ // |server_cert_verify_result_| points at the verification result, which may,
+ // or may not be, |&local_server_cert_verify_result_|, depending on whether
+ // we used an SSLHostInfo's verification.
+ const CertVerifyResult* server_cert_verify_result_;
+ CertVerifyResult local_server_cert_verify_result_;
+ int ssl_connection_status_;
// Stores client authentication information between ClientAuthHandler and
// GetSSLCertRequestInfo calls.
@@ -184,9 +204,12 @@ class SSLClientSocketNSS : public SSLClientSocket {
// HTTPS connections.
bool eset_mitm_detected_;
- // True iff we believe that the user has NetNanny intercepting our HTTPS
- // connections.
- bool netnanny_mitm_detected_;
+ // True iff |ssl_host_info_| contained a predicted certificate chain and
+ // that we found the prediction to be correct.
+ bool predicted_cert_chain_correct_;
+
+ // True if the peer name has been initialized.
+ bool peername_initialized_;
// This pointer is owned by the caller of UseDNSSEC.
DNSSECProvider* dnssec_provider_;
@@ -222,16 +245,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
bool predicted_npn_proto_used_;
scoped_ptr<SSLHostInfo> ssl_host_info_;
-
-#if defined(OS_WIN)
- // A CryptoAPI in-memory certificate store. We use it for two purposes:
- // 1. Import server certificates into this store so that we can verify and
- // display the certificates using CryptoAPI.
- // 2. Copy client certificates from the "MY" system certificate store into
- // this store so that we can close the system store when we finish
- // searching for client certificates.
- static HCERTSTORE cert_store_;
-#endif
+ DnsRRResolver* const dnsrr_resolver_;
};
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss_factory.cc b/net/socket/ssl_client_socket_nss_factory.cc
index efa6e23..f4e8215 100644
--- a/net/socket/ssl_client_socket_nss_factory.cc
+++ b/net/socket/ssl_client_socket_nss_factory.cc
@@ -4,12 +4,8 @@
#include "net/socket/client_socket_factory.h"
-#include "build/build_config.h"
#include "net/socket/ssl_client_socket_nss.h"
#include "net/socket/ssl_host_info.h"
-#if defined(OS_WIN)
-#include "net/socket/ssl_client_socket_win.h"
-#endif
// This file is only used on platforms where NSS is not the system SSL
// library. When compiled, this file is the only object module that pulls
@@ -22,18 +18,11 @@ SSLClientSocket* SSLClientSocketNSSFactory(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
scoped_ptr<SSLHostInfo> shi(ssl_host_info);
- // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
- // CryptoAPI yet (http://crbug.com/37560), so we fall back on
- // SSLClientSocketWin.
-#if defined(OS_WIN)
- if (ssl_config.send_client_cert)
- return new SSLClientSocketWin(transport_socket, hostname, ssl_config);
-#endif
-
return new SSLClientSocketNSS(transport_socket, hostname, ssl_config,
- shi.release());
+ shi.release(), dnsrr_resolver);
}
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss_factory.h b/net/socket/ssl_client_socket_nss_factory.h
index d454bb9..29f9af4 100644
--- a/net/socket/ssl_client_socket_nss_factory.h
+++ b/net/socket/ssl_client_socket_nss_factory.h
@@ -10,6 +10,7 @@
namespace net {
+class DnsRRResolver;
class SSLHostInfo;
// Creates SSLClientSocketNSS objects.
@@ -17,7 +18,8 @@ SSLClientSocket* SSLClientSocketNSSFactory(
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver);
} // namespace net
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index bbe3ee4..3aae457 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -631,6 +631,14 @@ bool SSLClientSocketOpenSSL::WasEverUsed() const {
return false;
}
+bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket())
+ return transport_->socket()->UsingTCPFastOpen();
+
+ NOTREACHED();
+ return false;
+}
+
// Socket methods
int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index 20f321e..31d5c1c 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -51,6 +51,7 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 98e3b09..a7eea3a 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -193,7 +193,8 @@ int SSLConnectJob::DoTCPConnect() {
if (ssl_host_info_factory_ && SSLConfigService::snap_start_enabled()) {
ssl_host_info_.reset(
- ssl_host_info_factory_->GetForHost(params_->hostname()));
+ ssl_host_info_factory_->GetForHost(params_->hostname(),
+ params_->ssl_config()));
}
if (ssl_host_info_.get()) {
// This starts fetching the SSL host info from the disk cache for Snap
@@ -284,7 +285,8 @@ int SSLConnectJob::DoSSLConnect() {
ssl_socket_.reset(client_socket_factory_->CreateSSLClientSocket(
transport_socket_handle_.release(), params_->hostname(),
- params_->ssl_config(), ssl_host_info_.release()));
+ params_->ssl_config(), ssl_host_info_.release(),
+ dnsrr_resolver_));
return ssl_socket_->Connect(&callback_);
}
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index bfcbe81..a32d5df 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -93,8 +93,9 @@ TEST_F(SSLClientSocketTest, Connect) {
}
TEST_F(SSLClientSocketTest, ConnectExpired) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE,
- FilePath());
+ net::TestServer::HTTPSOptions https_options(
+ net::TestServer::HTTPSOptions::CERT_EXPIRED);
+ net::TestServer test_server(https_options, FilePath());
ASSERT_TRUE(test_server.Start());
net::AddressList addr;
@@ -136,8 +137,9 @@ TEST_F(SSLClientSocketTest, ConnectExpired) {
}
TEST_F(SSLClientSocketTest, ConnectMismatched) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME,
- FilePath());
+ net::TestServer::HTTPSOptions https_options(
+ net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME);
+ net::TestServer test_server(https_options, FilePath());
ASSERT_TRUE(test_server.Start());
net::AddressList addr;
@@ -181,9 +183,11 @@ TEST_F(SSLClientSocketTest, ConnectMismatched) {
// Attempt to connect to a page which requests a client certificate. It should
// return an error code on connect.
+// Flaky: http://crbug.com/54445
TEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_CLIENT_AUTH,
- FilePath());
+ net::TestServer::HTTPSOptions https_options;
+ https_options.request_client_certificate = true;
+ net::TestServer test_server(https_options, FilePath());
ASSERT_TRUE(test_server.Start());
net::AddressList addr;
@@ -229,8 +233,9 @@ TEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) {
//
// TODO(davidben): Also test providing an actual certificate.
TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_CLIENT_AUTH,
- FilePath());
+ net::TestServer::HTTPSOptions https_options;
+ https_options.request_client_certificate = true;
+ net::TestServer test_server(https_options, FilePath());
ASSERT_TRUE(test_server.Start());
net::AddressList addr;
@@ -315,8 +320,8 @@ TEST_F(SSLClientSocketTest, Read) {
EXPECT_TRUE(sock->IsConnected());
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<net::IOBuffer> request_buffer =
- new net::IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<net::IOBuffer> request_buffer(
+ new net::IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -326,7 +331,7 @@ TEST_F(SSLClientSocketTest, Read) {
rv = callback.WaitForResult();
EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(4096);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
for (;;) {
rv = sock->Read(buf, 4096, &callback);
EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
@@ -376,7 +381,7 @@ TEST_F(SSLClientSocketTest, Read_FullDuplex) {
EXPECT_TRUE(sock->IsConnected());
// Issue a "hanging" Read first.
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(4096);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
rv = sock->Read(buf, 4096, &callback);
// We haven't written the request, so there should be no response yet.
ASSERT_EQ(net::ERR_IO_PENDING, rv);
@@ -389,8 +394,8 @@ TEST_F(SSLClientSocketTest, Read_FullDuplex) {
for (int i = 0; i < 3800; ++i)
request_text.push_back('*');
request_text.append("\r\n\r\n");
- scoped_refptr<net::IOBuffer> request_buffer =
- new net::StringIOBuffer(request_text);
+ scoped_refptr<net::IOBuffer> request_buffer(
+ new net::StringIOBuffer(request_text));
rv = sock->Write(request_buffer, request_text.size(), &callback2);
EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
@@ -433,8 +438,8 @@ TEST_F(SSLClientSocketTest, Read_SmallChunks) {
}
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<net::IOBuffer> request_buffer =
- new net::IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<net::IOBuffer> request_buffer(
+ new net::IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -444,7 +449,7 @@ TEST_F(SSLClientSocketTest, Read_SmallChunks) {
rv = callback.WaitForResult();
EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(1);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1));
for (;;) {
rv = sock->Read(buf, 1, &callback);
EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
@@ -487,8 +492,8 @@ TEST_F(SSLClientSocketTest, Read_Interrupted) {
}
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<net::IOBuffer> request_buffer =
- new net::IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<net::IOBuffer> request_buffer(
+ new net::IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -499,7 +504,7 @@ TEST_F(SSLClientSocketTest, Read_Interrupted) {
EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
// Do a partial read and then exit. This test should not crash!
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(512);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512));
rv = sock->Read(buf, 512, &callback);
EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING);
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index 7e8c29e..eead7ed 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -705,6 +705,14 @@ bool SSLClientSocketWin::WasEverUsed() const {
return false;
}
+bool SSLClientSocketWin::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(completed_handshake());
diff --git a/net/socket/ssl_client_socket_win.h b/net/socket/ssl_client_socket_win.h
index 38cdb32..4f96e80 100644
--- a/net/socket/ssl_client_socket_win.h
+++ b/net/socket/ssl_client_socket_win.h
@@ -54,6 +54,7 @@ class SSLClientSocketWin : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc
index cc29545..4f6c1bb 100644
--- a/net/socket/ssl_host_info.cc
+++ b/net/socket/ssl_host_info.cc
@@ -4,6 +4,11 @@
#include "net/socket/ssl_host_info.h"
+#include "base/metrics/histogram.h"
+#include "base/string_piece.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/ssl_config_service.h"
+#include "net/base/x509_certificate.h"
#include "net/socket/ssl_client_socket.h"
#ifdef ANDROID
// the android platform build system use a fixed include path relative to the
@@ -15,7 +20,25 @@
namespace net {
-SSLHostInfo::SSLHostInfo() {
+SSLHostInfo::State::State()
+ : npn_valid(false),
+ npn_status(SSLClientSocket::kNextProtoUnsupported) {
+}
+
+SSLHostInfo::State::~State() {}
+
+SSLHostInfo::SSLHostInfo(
+ const std::string& hostname,
+ const SSLConfig& ssl_config)
+ : hostname_(hostname),
+ cert_verification_complete_(false),
+ cert_parsing_failed_(false),
+ cert_verification_callback_(NULL),
+ rev_checking_enabled_(ssl_config.rev_checking_enabled),
+ verify_ev_cert_(ssl_config.verify_ev_cert),
+ callback_(new CancelableCompletionCallback<SSLHostInfo>(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this),
+ &SSLHostInfo::VerifyCallback)) {
state_.npn_valid = false;
}
@@ -66,6 +89,7 @@ bool SSLHostInfo::Parse(const std::string& data) {
state->certs.clear();
state->server_hello.clear();
state->npn_valid = false;
+ cert_verification_complete_ = false;
if (!proto.ParseFromString(data))
return false;
@@ -80,6 +104,30 @@ bool SSLHostInfo::Parse(const std::string& data) {
state->npn_protocol = proto.npn_protocol();
}
+ if (state->certs.size() > 0) {
+ std::vector<base::StringPiece> der_certs(state->certs.size());
+ for (size_t i = 0; i < state->certs.size(); i++)
+ der_certs[i] = state->certs[i];
+ cert_ = X509Certificate::CreateFromDERCertChain(der_certs);
+ if (cert_.get()) {
+ int flags = 0;
+ if (verify_ev_cert_)
+ flags |= X509Certificate::VERIFY_EV_CERT;
+ if (rev_checking_enabled_)
+ flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
+ verifier_.reset(new CertVerifier);
+ VLOG(1) << "Kicking off verification for " << hostname_;
+ verification_start_time_ = base::TimeTicks::Now();
+ if (verifier_->Verify(cert_.get(), hostname_, flags,
+ &cert_verify_result_, callback_) == OK) {
+ VerifyCallback(OK);
+ }
+ } else {
+ cert_parsing_failed_ = true;
+ DCHECK(!cert_verification_callback_);
+ }
+ }
+
return true;
}
@@ -101,6 +149,35 @@ std::string SSLHostInfo::Serialize() const {
return proto.SerializeAsString();
}
+const CertVerifyResult& SSLHostInfo::cert_verify_result() const {
+ return cert_verify_result_;
+}
+
+int SSLHostInfo::WaitForCertVerification(CompletionCallback* callback) {
+ if (cert_verification_complete_)
+ return cert_verification_result_;
+ DCHECK(!cert_parsing_failed_);
+ DCHECK(!cert_verification_callback_);
+ DCHECK(!state_.certs.empty());
+ cert_verification_callback_ = callback;
+ return ERR_IO_PENDING;
+}
+
+void SSLHostInfo::VerifyCallback(int rv) {
+ DCHECK(!verification_start_time_.is_null());
+ base::TimeTicks now = base::TimeTicks::Now();
+ const base::TimeDelta duration = now - verification_start_time();
+ UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs", duration);
+ VLOG(1) << "Verification took " << duration.InMilliseconds() << "ms";
+ cert_verification_complete_ = true;
+ cert_verification_result_ = rv;
+ if (cert_verification_callback_) {
+ CompletionCallback* callback = cert_verification_callback_;
+ cert_verification_callback_ = NULL;
+ callback->Run(rv);
+ }
+}
+
SSLHostInfoFactory::~SSLHostInfoFactory() {}
} // namespace net
diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h
index 8065b47..5f515fb 100644
--- a/net/socket/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -9,18 +9,25 @@
#include <vector>
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "net/base/cert_verify_result.h"
#include "net/base/completion_callback.h"
#include "net/socket/ssl_client_socket.h"
namespace net {
+class CertVerifier;
+class X509Certificate;
+struct SSLConfig;
+
// SSLHostInfo is an interface for fetching information about an SSL server.
// This information may be stored on disk so does not include keys or session
// information etc. Primarily it's intended for caching the server's
// certificates.
class SSLHostInfo {
public:
- SSLHostInfo();
+ SSLHostInfo(const std::string& hostname, const SSLConfig& ssl_config);
virtual ~SSLHostInfo();
// Start will commence the lookup. This must be called before any other
@@ -48,6 +55,9 @@ class SSLHostInfo {
virtual void Persist() = 0;
struct State {
+ State();
+ ~State();
+
// certs is a vector of DER encoded X.509 certificates, as the server
// returned them and in the same order.
std::vector<std::string> certs;
@@ -59,6 +69,9 @@ class SSLHostInfo {
// these members contain the NPN result of a connection to the server.
SSLClientSocket::NextProtoStatus npn_status;
std::string npn_protocol;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(State);
};
// Once the data is ready, it can be read using the following members. These
@@ -66,6 +79,21 @@ class SSLHostInfo {
const State& state() const;
State* mutable_state();
+ // If |cert_valid()| returns true, then this contains the result of verifying
+ // the certificate.
+ const CertVerifyResult& cert_verify_result() const;
+
+ // WaitForCertVerification returns ERR_IO_PENDING if the certificate chain in
+ // |state().certs| is still being validated and arranges for the given
+ // callback to be called when the verification completes. If the verification has
+ // already finished then WaitForCertVerification returns the result of that
+ // verification.
+ int WaitForCertVerification(CompletionCallback* callback);
+
+ base::TimeTicks verification_start_time() const {
+ return verification_start_time_;
+ }
+
protected:
// Parse parses an opaque blob of data and fills out the public member fields
// of this object. It returns true iff the parse was successful. The public
@@ -73,6 +101,25 @@ class SSLHostInfo {
bool Parse(const std::string& data);
std::string Serialize() const;
State state_;
+
+ private:
+ // This is the callback function which the CertVerifier calls via |callback_|.
+ void VerifyCallback(int rv);
+
+ // This is the hostname that we'll validate the certificates against.
+ const std::string hostname_;
+ bool cert_verification_complete_;
+ bool cert_parsing_failed_;
+ int cert_verification_result_;
+ CompletionCallback* cert_verification_callback_;
+ // These two members are taken from the SSLConfig.
+ bool rev_checking_enabled_;
+ bool verify_ev_cert_;
+ base::TimeTicks verification_start_time_;
+ CertVerifyResult cert_verify_result_;
+ scoped_ptr<CertVerifier> verifier_;
+ scoped_refptr<X509Certificate> cert_;
+ scoped_refptr<CancelableCompletionCallback<SSLHostInfo> > callback_;
};
class SSLHostInfoFactory {
@@ -81,7 +128,8 @@ class SSLHostInfoFactory {
// GetForHost returns a fresh, allocated SSLHostInfo for the given hostname
// or NULL on failure.
- virtual SSLHostInfo* GetForHost(const std::string& hostname) = 0;
+ virtual SSLHostInfo* GetForHost(const std::string& hostname,
+ const SSLConfig& ssl_config) = 0;
};
} // namespace net
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
new file mode 100644
index 0000000..d3d4e20
--- /dev/null
+++ b/net/socket/tcp_client_socket.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2006-2009 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/socket/tcp_client_socket.h"
+
+namespace net {
+
+static bool g_tcp_fastopen_enabled = false;
+
+void set_tcp_fastopen_enabled(bool value) {
+ g_tcp_fastopen_enabled = value;
+}
+
+bool is_tcp_fastopen_enabled() {
+ return g_tcp_fastopen_enabled;
+}
+
+} // namespace net
diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h
index 6139b5b..13d2dfb 100644
--- a/net/socket/tcp_client_socket.h
+++ b/net/socket/tcp_client_socket.h
@@ -23,6 +23,13 @@ typedef TCPClientSocketWin TCPClientSocket;
typedef TCPClientSocketLibevent TCPClientSocket;
#endif
+// Enable/disable experimental TCP FastOpen option.
+// Not thread safe. Must be called during initialization/startup only.
+void set_tcp_fastopen_enabled(bool value);
+
+// Check if the TCP FastOpen option is enabled.
+bool is_tcp_fastopen_enabled();
+
} // namespace net
#endif // NET_SOCKET_TCP_CLIENT_SOCKET_H_
diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc
index aedbf8a..1bbe827 100644
--- a/net/socket/tcp_client_socket_libevent.cc
+++ b/net/socket/tcp_client_socket_libevent.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/socket/tcp_client_socket_libevent.h"
+#include "net/socket/tcp_client_socket.h"
#include <errno.h>
#include <fcntl.h>
@@ -86,6 +86,8 @@ int MapPosixError(int os_error) {
int MapConnectError(int os_error) {
switch (os_error) {
+ case EACCES:
+ return ERR_NETWORK_ACCESS_DENIED;
case ETIMEDOUT:
return ERR_CONNECTION_TIMED_OUT;
default: {
@@ -120,11 +122,17 @@ TCPClientSocketLibevent::TCPClientSocketLibevent(
write_callback_(NULL),
next_connect_state_(CONNECT_STATE_NONE),
connect_os_error_(0),
- net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
+ net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
+ previously_disconnected_(false),
+ use_tcp_fastopen_(false),
+ tcp_fastopen_connected_(false) {
scoped_refptr<NetLog::EventParameters> params;
if (source.is_valid())
params = new NetLogSourceParameter("source_dependency", source);
net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
+
+ if (is_tcp_fastopen_enabled())
+ use_tcp_fastopen_ = true;
}
TCPClientSocketLibevent::~TCPClientSocketLibevent() {
@@ -144,8 +152,9 @@ int TCPClientSocketLibevent::Connect(CompletionCallback* callback) {
DCHECK(!waiting_connect());
- net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
- new AddressListNetLogParam(addresses_));
+ net_log_.BeginEvent(
+ NetLog::TYPE_TCP_CONNECT,
+ make_scoped_refptr(new AddressListNetLogParam(addresses_)));
// We will try to connect to each address in addresses_. Start with the
// first one in the list.
@@ -194,9 +203,14 @@ int TCPClientSocketLibevent::DoConnect() {
DCHECK_EQ(0, connect_os_error_);
+ if (previously_disconnected_) {
+ use_history_.Reset();
+ previously_disconnected_ = false;
+ }
+
net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
- new NetLogStringParameter(
- "address", NetAddressToStringWithPort(current_ai_)));
+ make_scoped_refptr(new NetLogStringParameter(
+ "address", NetAddressToStringWithPort(current_ai_))));
next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
@@ -206,9 +220,15 @@ int TCPClientSocketLibevent::DoConnect() {
return MapPosixError(connect_os_error_);
// Connect the socket.
- if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
- static_cast<int>(current_ai_->ai_addrlen)))) {
- // Connected without waiting!
+ if (!use_tcp_fastopen_) {
+ if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
+ static_cast<int>(current_ai_->ai_addrlen)))) {
+ // Connected without waiting!
+ return OK;
+ }
+ } else {
+ // With TCP FastOpen, we pretend that the socket is connected.
+ DCHECK(!tcp_fastopen_connected_);
return OK;
}
@@ -278,6 +298,7 @@ void TCPClientSocketLibevent::DoDisconnect() {
if (HANDLE_EINTR(close(socket_)) < 0)
PLOG(ERROR) << "close";
socket_ = kInvalidSocket;
+ previously_disconnected_ = true;
}
bool TCPClientSocketLibevent::IsConnected() const {
@@ -365,7 +386,7 @@ int TCPClientSocketLibevent::Write(IOBuffer* buf,
DCHECK(callback);
DCHECK_GT(buf_len, 0);
- int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
+ int nwrite = InternalWrite(buf, buf_len);
if (nwrite >= 0) {
static base::StatsCounter write_bytes("tcp.write_bytes");
write_bytes.Add(nwrite);
@@ -391,6 +412,38 @@ int TCPClientSocketLibevent::Write(IOBuffer* buf,
return ERR_IO_PENDING;
}
+int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
+ int nwrite;
+ if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
+ // We have a limited amount of data to send in the SYN packet.
+ int kMaxFastOpenSendLength = 1420;
+
+ buf_len = std::min(kMaxFastOpenSendLength, buf_len);
+
+ int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN
+ nwrite = HANDLE_EINTR(sendto(socket_,
+ buf->data(),
+ buf_len,
+ flags,
+ current_ai_->ai_addr,
+ static_cast<int>(current_ai_->ai_addrlen)));
+ tcp_fastopen_connected_ = true;
+
+ if (nwrite < 0) {
+ // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
+ if (errno == EINPROGRESS)
+ errno = EAGAIN;
+
+ // Unlike "normal" nonblocking sockets, the data is already queued,
+ // so tell the app that we've consumed it.
+ return buf_len;
+ }
+ } else {
+ nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
+ }
+ return nwrite;
+}
+
bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
DCHECK(CalledOnValidThread());
int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
@@ -553,4 +606,8 @@ bool TCPClientSocketLibevent::WasEverUsed() const {
return use_history_.was_used_to_convey_data();
}
+bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
+ return use_tcp_fastopen_;
+}
+
} // namespace net
diff --git a/net/socket/tcp_client_socket_libevent.h b/net/socket/tcp_client_socket_libevent.h
index 980e4cd..890d0c2 100644
--- a/net/socket/tcp_client_socket_libevent.h
+++ b/net/socket/tcp_client_socket_libevent.h
@@ -43,6 +43,7 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
// Multiple outstanding requests are not supported.
@@ -127,6 +128,9 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe {
// Helper to add a TCP_CONNECT (end) event to the NetLog.
void LogConnectCompletion(int net_error);
+ // Internal function to write to a socket.
+ int InternalWrite(IOBuffer* buf, int buf_len);
+
int socket_;
// The list of addresses we should try in order to establish a connection.
@@ -165,10 +169,19 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe {
BoundNetLog net_log_;
+ // This socket was previously disconnected and has not been re-connected.
+ bool previously_disconnected_;
+
// Record of connectivity and transmissions, for use in speculative connection
// histograms.
UseHistory use_history_;
+ // Enables experimental TCP FastOpen option.
+ bool use_tcp_fastopen_;
+
+ // True when TCP FastOpen is in use and we have done the connect.
+ bool tcp_fastopen_connected_;
+
DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent);
};
diff --git a/net/socket/tcp_client_socket_pool.cc b/net/socket/tcp_client_socket_pool.cc
index 5f1f43f..8ec9cac 100644
--- a/net/socket/tcp_client_socket_pool.cc
+++ b/net/socket/tcp_client_socket_pool.cc
@@ -222,9 +222,9 @@ int TCPClientSocketPool::RequestSocket(
// TODO(eroman): Split out the host and port parameters.
net_log.AddEvent(
NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET,
- new NetLogStringParameter(
+ make_scoped_refptr(new NetLogStringParameter(
"host_and_port",
- casted_params->get()->destination().host_port_pair().ToString()));
+ casted_params->get()->destination().host_port_pair().ToString())));
}
return base_.RequestSocket(group_name, *casted_params, priority, handle,
@@ -243,9 +243,9 @@ void TCPClientSocketPool::RequestSockets(
// TODO(eroman): Split out the host and port parameters.
net_log.AddEvent(
NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKETS,
- new NetLogStringParameter(
+ make_scoped_refptr(new NetLogStringParameter(
"host_and_port",
- casted_params->get()->destination().host_port_pair().ToString()));
+ casted_params->get()->destination().host_port_pair().ToString())));
}
base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index 80de0aa..e53e264 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -54,6 +54,7 @@ class MockClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation() {}
virtual void SetOmniboxSpeculation() {}
virtual bool WasEverUsed() const { return false; }
+ virtual bool UsingTCPFastOpen() const { return false; }
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len,
@@ -99,6 +100,7 @@ class MockFailingClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation() {}
virtual void SetOmniboxSpeculation() {}
virtual bool WasEverUsed() const { return false; }
+ virtual bool UsingTCPFastOpen() const { return false; }
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len,
@@ -157,6 +159,7 @@ class MockPendingClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation() {}
virtual void SetOmniboxSpeculation() {}
virtual bool WasEverUsed() const { return false; }
+ virtual bool UsingTCPFastOpen() const { return false; }
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len,
@@ -247,7 +250,8 @@ class MockClientSocketFactory : public ClientSocketFactory {
ClientSocketHandle* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ DnsRRResolver* dnsrr_resolver) {
NOTIMPLEMENTED();
delete ssl_host_info;
return NULL;
@@ -294,8 +298,8 @@ class TCPClientSocketPoolTest : public testing::Test {
}
int StartRequest(const std::string& group_name, RequestPriority priority) {
- scoped_refptr<TCPSocketParams> params = new TCPSocketParams(
- HostPortPair("www.google.com", 80), MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> params(new TCPSocketParams(
+ HostPortPair("www.google.com", 80), MEDIUM, GURL(), false));
return test_base_.StartRequestUsingPool(
&pool_, group_name, priority, params);
}
@@ -343,8 +347,8 @@ TEST_F(TCPClientSocketPoolTest, InitHostResolutionFailure) {
host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name");
TestCompletionCallback callback;
ClientSocketHandle handle;
- scoped_refptr<TCPSocketParams> dest = new TCPSocketParams(
- "unresolvable.host.name", 80, kDefaultPriority, GURL(), false);
+ scoped_refptr<TCPSocketParams> dest(new TCPSocketParams(
+ "unresolvable.host.name", 80, kDefaultPriority, GURL(), false));
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a", dest, kDefaultPriority, &callback, &pool_,
BoundNetLog()));
@@ -602,8 +606,8 @@ class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
MessageLoop::current()->RunAllPending();
}
within_callback_ = true;
- scoped_refptr<TCPSocketParams> dest = new TCPSocketParams(
- HostPortPair("www.google.com", 80), LOWEST, GURL(), false);
+ scoped_refptr<TCPSocketParams> dest(new TCPSocketParams(
+ HostPortPair("www.google.com", 80), LOWEST, GURL(), false));
int rv = handle_->Init("a", dest, LOWEST, this, pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
}
@@ -623,8 +627,8 @@ class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
TEST_F(TCPClientSocketPoolTest, RequestTwice) {
ClientSocketHandle handle;
RequestSocketCallback callback(&handle, &pool_);
- scoped_refptr<TCPSocketParams> dest = new TCPSocketParams(
- HostPortPair("www.google.com", 80), LOWEST, GURL(), false);
+ scoped_refptr<TCPSocketParams> dest(new TCPSocketParams(
+ HostPortPair("www.google.com", 80), LOWEST, GURL(), false));
int rv = handle.Init("a", dest, LOWEST, &callback, &pool_,
BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index fdd966c..64d78f3 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -93,7 +93,7 @@ void TCPClientSocketTest::SetUp() {
AddressList addr;
scoped_ptr<HostResolver> resolver(
CreateSystemHostResolver(HostResolver::kDefaultParallelism,
- NULL));
+ NULL, NULL));
HostResolver::RequestInfo info(HostPortPair("localhost", listen_port_));
int rv = resolver->Resolve(info, &addr, NULL, NULL, BoundNetLog());
CHECK_EQ(rv, OK);
@@ -138,8 +138,8 @@ TEST_F(TCPClientSocketTest, Read) {
}
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<IOBuffer> request_buffer =
- new IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(
+ new IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock_->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -150,7 +150,7 @@ TEST_F(TCPClientSocketTest, Read) {
EXPECT_EQ(rv, static_cast<int>(arraysize(request_text) - 1));
}
- scoped_refptr<IOBuffer> buf = new IOBuffer(4096);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
uint32 bytes_read = 0;
while (bytes_read < arraysize(kServerReply) - 1) {
rv = sock_->Read(buf, 4096, &callback);
@@ -183,8 +183,8 @@ TEST_F(TCPClientSocketTest, Read_SmallChunks) {
}
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<IOBuffer> request_buffer =
- new IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(
+ new IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock_->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -195,7 +195,7 @@ TEST_F(TCPClientSocketTest, Read_SmallChunks) {
EXPECT_EQ(rv, static_cast<int>(arraysize(request_text) - 1));
}
- scoped_refptr<IOBuffer> buf = new IOBuffer(1);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(1));
uint32 bytes_read = 0;
while (bytes_read < arraysize(kServerReply) - 1) {
rv = sock_->Read(buf, 1, &callback);
@@ -228,8 +228,8 @@ TEST_F(TCPClientSocketTest, Read_Interrupted) {
}
const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
- scoped_refptr<IOBuffer> request_buffer =
- new IOBuffer(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(
+ new IOBuffer(arraysize(request_text) - 1));
memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
rv = sock_->Write(request_buffer, arraysize(request_text) - 1, &callback);
@@ -241,7 +241,7 @@ TEST_F(TCPClientSocketTest, Read_Interrupted) {
}
// Do a partial read and then exit. This test should not crash!
- scoped_refptr<IOBuffer> buf = new IOBuffer(16);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(16));
rv = sock_->Read(buf, 16, &callback);
EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
@@ -263,13 +263,13 @@ TEST_F(TCPClientSocketTest, DISABLED_FullDuplex_ReadFirst) {
// Read first. There's no data, so it should return ERR_IO_PENDING.
const int kBufLen = 4096;
- scoped_refptr<IOBuffer> buf = new IOBuffer(kBufLen);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen));
rv = sock_->Read(buf, kBufLen, &callback);
EXPECT_EQ(ERR_IO_PENDING, rv);
PauseServerReads();
const int kWriteBufLen = 64 * 1024;
- scoped_refptr<IOBuffer> request_buffer = new IOBuffer(kWriteBufLen);
+ scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen));
char* request_data = request_buffer->data();
memset(request_data, 'A', kWriteBufLen);
TestCompletionCallback write_callback;
@@ -305,7 +305,7 @@ TEST_F(TCPClientSocketTest, DISABLED_FullDuplex_WriteFirst) {
PauseServerReads();
const int kWriteBufLen = 64 * 1024;
- scoped_refptr<IOBuffer> request_buffer = new IOBuffer(kWriteBufLen);
+ scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen));
char* request_data = request_buffer->data();
memset(request_data, 'A', kWriteBufLen);
TestCompletionCallback write_callback;
@@ -322,7 +322,7 @@ TEST_F(TCPClientSocketTest, DISABLED_FullDuplex_WriteFirst) {
// Read() to block on ERR_IO_PENDING too.
const int kBufLen = 4096;
- scoped_refptr<IOBuffer> buf = new IOBuffer(kBufLen);
+ scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen));
while (true) {
rv = sock_->Read(buf, kBufLen, &callback);
ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc
index 9143b81..b3b79a0 100644
--- a/net/socket/tcp_client_socket_win.cc
+++ b/net/socket/tcp_client_socket_win.cc
@@ -64,8 +64,6 @@ int MapWinsockError(int os_error) {
// There are numerous Winsock error codes, but these are the ones we thus far
// find interesting.
switch (os_error) {
- // connect fails with WSAEACCES when Windows Firewall blocks the
- // connection.
case WSAEACCES:
return ERR_ACCESS_DENIED;
case WSAENETDOWN:
@@ -104,6 +102,10 @@ int MapWinsockError(int os_error) {
int MapConnectError(int os_error) {
switch (os_error) {
+ // connect fails with WSAEACCES when Windows Firewall blocks the
+ // connection.
+ case WSAEACCES:
+ return ERR_NETWORK_ACCESS_DENIED;
case WSAETIMEDOUT:
return ERR_CONNECTION_TIMED_OUT;
default: {
@@ -290,8 +292,8 @@ TCPClientSocketWin::TCPClientSocketWin(const AddressList& addresses,
write_callback_(NULL),
next_connect_state_(CONNECT_STATE_NONE),
connect_os_error_(0),
- net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
-
+ net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
+ previously_disconnected_(false) {
scoped_refptr<NetLog::EventParameters> params;
if (source.is_valid())
params = new NetLogSourceParameter("source_dependency", source);
@@ -364,6 +366,11 @@ int TCPClientSocketWin::DoConnect() {
DCHECK(ai);
DCHECK_EQ(0, connect_os_error_);
+ if (previously_disconnected_) {
+ use_history_.Reset();
+ previously_disconnected_ = false;
+ }
+
net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
new NetLogStringParameter(
"address", NetAddressToStringWithPort(current_ai_)));
@@ -478,6 +485,8 @@ void TCPClientSocketWin::DoDisconnect() {
core_->Detach();
core_ = NULL;
+
+ previously_disconnected_ = true;
}
bool TCPClientSocketWin::IsConnected() const {
@@ -536,6 +545,11 @@ bool TCPClientSocketWin::WasEverUsed() const {
return use_history_.was_used_to_convey_data();
}
+bool TCPClientSocketWin::UsingTCPFastOpen() const {
+ // Not supported on windows.
+ return false;
+}
+
int TCPClientSocketWin::Read(IOBuffer* buf,
int buf_len,
CompletionCallback* callback) {
diff --git a/net/socket/tcp_client_socket_win.h b/net/socket/tcp_client_socket_win.h
index be25157..cd6b066 100644
--- a/net/socket/tcp_client_socket_win.h
+++ b/net/socket/tcp_client_socket_win.h
@@ -40,6 +40,7 @@ class TCPClientSocketWin : public ClientSocket, NonThreadSafe {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
// Multiple outstanding requests are not supported.
@@ -117,6 +118,9 @@ class TCPClientSocketWin : public ClientSocket, NonThreadSafe {
BoundNetLog net_log_;
+ // This socket was previously disconnected and has not been re-connected.
+ bool previously_disconnected_;
+
// Record of connectivity and transmissions, for use in speculative connection
// histograms.
UseHistory use_history_;
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc
index 7c3c5e9..6d6efbe 100644
--- a/net/socket_stream/socket_stream.cc
+++ b/net/socket_stream/socket_stream.cc
@@ -138,7 +138,8 @@ void SocketStream::Connect() {
next_state_ = STATE_RESOLVE_PROXY;
net_log_.BeginEvent(
NetLog::TYPE_SOCKET_STREAM_CONNECT,
- new NetLogStringParameter("url", url_.possibly_invalid_spec()));
+ make_scoped_refptr(
+ new NetLogStringParameter("url", url_.possibly_invalid_spec())));
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &SocketStream::DoLoop, OK));
@@ -162,7 +163,8 @@ bool SocketStream::SendData(const char* data, int len) {
if (current_amount_send > max_pending_send_allowed_)
return false;
- pending_write_bufs_.push_back(new IOBufferWithSize(len));
+ pending_write_bufs_.push_back(make_scoped_refptr(
+ new IOBufferWithSize(len)));
memcpy(pending_write_bufs_.back()->data(), data, len);
return true;
}
@@ -445,8 +447,9 @@ void SocketStream::DoLoop(int result) {
// close the connection.
if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
DCHECK_EQ(next_state_, STATE_CLOSE);
- net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT,
- new NetLogIntegerParameter("net_error", result));
+ net_log_.EndEvent(
+ NetLog::TYPE_SOCKET_STREAM_CONNECT,
+ make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
}
} while (result != ERR_IO_PENDING);
}
diff --git a/net/socket_stream/socket_stream_unittest.cc b/net/socket_stream/socket_stream_unittest.cc
index 25ce17b..832b0ab 100644
--- a/net/socket_stream/socket_stream_unittest.cc
+++ b/net/socket_stream/socket_stream_unittest.cc
@@ -240,8 +240,8 @@ TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
MockHostResolver host_resolver;
- scoped_refptr<SocketStream> socket_stream =
- new SocketStream(GURL("ws://example.com/demo"), delegate.get());
+ scoped_refptr<SocketStream> socket_stream(
+ new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
socket_stream->set_context(new TestURLRequestContext());
socket_stream->SetHostResolver(&host_resolver);
@@ -331,8 +331,8 @@ TEST_F(SocketStreamTest, BasicAuthProxy) {
NewCallback(delegate.get(),
&SocketStreamEventRecorder::DoRestartWithAuth));
- scoped_refptr<SocketStream> socket_stream =
- new SocketStream(GURL("ws://example.com/demo"), delegate.get());
+ scoped_refptr<SocketStream> socket_stream(
+ new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
socket_stream->set_context(new TestURLRequestContext("myproxy:70"));
MockHostResolver host_resolver;
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 6fede6c..89002cb 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -12,6 +12,7 @@
#include "base/message_loop.h"
#include "net/base/load_flags.h"
#include "net/base/net_util.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
@@ -112,7 +113,7 @@ int SpdyHttpStream::ReadResponseBody(
memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]),
bytes_remaining);
response_body_.pop_front();
- response_body_.push_front(new_buffer);
+ response_body_.push_front(make_scoped_refptr(new_buffer));
}
bytes_read += bytes_to_copy;
}
@@ -139,7 +140,7 @@ void SpdyHttpStream::Close(bool not_reusable) {
Cancel();
}
-int SpdyHttpStream::SendRequest(const std::string& /*headers_string*/,
+int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) {
@@ -148,9 +149,6 @@ int SpdyHttpStream::SendRequest(const std::string& /*headers_string*/,
stream_->SetDelegate(this);
- HttpRequestHeaders request_headers;
- HttpUtil::BuildRequestHeaders(request_info_, request_body, NULL, false, false,
- !direct_, &request_headers);
linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock);
CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers,
headers.get(), direct_);
@@ -275,7 +273,7 @@ void SpdyHttpStream::OnDataReceived(const char* data, int length) {
// Save the received data.
IOBufferWithSize* io_buffer = new IOBufferWithSize(length);
memcpy(io_buffer->data(), data, length);
- response_body_.push_back(io_buffer);
+ response_body_.push_back(make_scoped_refptr(io_buffer));
if (user_buffer_) {
// Handing small chunks of data to the caller creates measurable overhead.
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 372db57..a878ff9 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -49,7 +49,7 @@ class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream {
// |callback| is used when this completes asynchronously.
// SpdyHttpStream takes ownership of |upload_data|. |upload_data| may be NULL.
// The actual SYN_STREAM packet will be sent if the stream is non-pushed.
- virtual int SendRequest(const std::string& headers,
+ virtual int SendRequest(const HttpRequestHeaders& headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback);
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index ee1a34e..df979ec 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -74,6 +74,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
request.url = GURL("http://www.google.com/");
TestCompletionCallback callback;
HttpResponseInfo response;
+ HttpRequestHeaders headers;
BoundNetLog net_log;
scoped_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_.get(), true));
@@ -82,7 +83,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
http_stream->InitializeStream(&request, net_log, NULL));
EXPECT_EQ(ERR_IO_PENDING,
- http_stream->SendRequest("", NULL, &response, &callback));
+ http_stream->SendRequest(headers, NULL, &response, &callback));
EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
// This triggers the MockWrite and read 2
@@ -125,6 +126,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
request.url = GURL(full_url);
TestCompletionCallback callback;
HttpResponseInfo response;
+ HttpRequestHeaders headers;
BoundNetLog net_log;
scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
ASSERT_EQ(
@@ -132,7 +134,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
http_stream->InitializeStream(&request, net_log, NULL));
EXPECT_EQ(ERR_IO_PENDING,
- http_stream->SendRequest("", NULL, &response, &callback));
+ http_stream->SendRequest(headers, NULL, &response, &callback));
spdy::SpdyHeaderBlock* spdy_header =
http_stream->stream()->spdy_headers().get();
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 99b5089..d72a2a7 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -5,6 +5,7 @@
#include <string>
#include <vector>
+#include "net/base/auth.h"
#include "net/base/net_log_unittest.h"
#include "net/http/http_network_session_peer.h"
#include "net/http/http_transaction_unittest.h"
@@ -345,7 +346,7 @@ class SpdyNetworkTransactionTest
const int kSize = 3000;
int bytes_read = 0;
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kSize);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
TestCompletionCallback callback;
while (true) {
int rv = trans->Read(buf, kSize, &callback);
@@ -461,8 +462,8 @@ INSTANTIATE_TEST_CASE_P(Spdy,
// Verify HttpNetworkTransaction constructor.
TEST_P(SpdyNetworkTransactionTest, Constructor) {
SpdySessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session =
- SpdySessionDependencies::SpdyCreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(
+ SpdySessionDependencies::SpdyCreateSession(&session_deps));
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
}
@@ -1708,7 +1709,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
// Issue a read which will cause a WINDOW_UPDATE to be sent and window
// size increased to default.
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kUploadDataSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
rv = trans->Read(buf, kUploadDataSize, NULL);
EXPECT_EQ(kUploadDataSize, rv);
std::string content(buf->data(), buf->data()+kUploadDataSize);
@@ -2074,7 +2075,7 @@ TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
StartTransactionCallback callback2(helper.session(), helper);
const int kSize = 3000;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
rv = trans->Read(buf, kSize, &callback2);
// This forces an err_IO_pending, which sets the callback.
data->CompleteRead();
@@ -2134,7 +2135,7 @@ TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
// memory holding the stream object. Note that the callback deletes trans.
DeleteSessionCallback callback2(helper);
const int kSize = 3000;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
rv = trans->Read(buf, kSize, &callback2);
ASSERT_EQ(ERR_IO_PENDING, rv);
data->CompleteRead();
@@ -3417,7 +3418,7 @@ TEST_P(SpdyNetworkTransactionTest, BufferFull) {
do {
// Read small chunks at a time.
const int kSmallReadSize = 3;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
rv = trans->Read(buf, kSmallReadSize, &read_callback);
if (rv == net::ERR_IO_PENDING) {
data->CompleteRead();
@@ -3583,7 +3584,7 @@ TEST_P(SpdyNetworkTransactionTest, Buffering) {
do {
// Read small chunks at a time.
const int kSmallReadSize = 14;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
rv = trans->Read(buf, kSmallReadSize, &read_callback);
if (rv == net::ERR_IO_PENDING) {
data->CompleteRead();
@@ -3678,7 +3679,7 @@ TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
do {
// Read small chunks at a time.
const int kSmallReadSize = 14;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
rv = trans->Read(buf, kSmallReadSize, &read_callback);
if (rv > 0) {
EXPECT_EQ(kSmallReadSize, rv);
@@ -3767,7 +3768,7 @@ TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
do {
// Read small chunks at a time.
const int kSmallReadSize = 14;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
rv = trans->Read(buf, kSmallReadSize, &read_callback);
if (rv == net::ERR_IO_PENDING) {
data->CompleteRead();
@@ -3843,7 +3844,7 @@ TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
do {
const int kReadSize = 256;
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kReadSize);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
rv = trans->Read(buf, kReadSize, &read_callback);
if (rv == net::ERR_IO_PENDING) {
// Complete the read now, which causes buffering to start.
@@ -4150,8 +4151,8 @@ TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
BoundNetLog(), GetParam());
helper.session_deps().reset(new SpdySessionDependencies(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
- helper.SetSession(SpdySessionDependencies::SpdyCreateSession(
- helper.session_deps().get()));
+ helper.SetSession(make_scoped_refptr(
+ SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
helper.RunPreTestSetup();
HttpNetworkTransaction* trans = helper.trans();
@@ -4253,8 +4254,8 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
// that the session pool key used does is just "DIRECT".
helper.session_deps().reset(new SpdySessionDependencies(
ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
- helper.SetSession(SpdySessionDependencies::SpdyCreateSession(
- helper.session_deps().get()));
+ helper.SetSession(make_scoped_refptr(
+ SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
helper.RunPreTestSetup();
@@ -4381,8 +4382,8 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
request_proxy.load_flags = 0;
scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
// Ensure that this transaction uses the same SpdySessionPool.
- scoped_refptr<HttpNetworkSession> session_proxy =
- SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get());
+ scoped_refptr<HttpNetworkSession> session_proxy(
+ SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
NormalSpdyTransactionHelper helper_proxy(request_proxy,
BoundNetLog(), GetParam());
HttpNetworkSessionPeer session_peer(session_proxy);
@@ -4511,7 +4512,8 @@ TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
};
scoped_refptr<DelayedSocketData> data(
- new DelayedSocketData(1, spdy_reads, arraysize(spdy_reads),
+ new DelayedSocketData(1,
+ spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes)));
NormalSpdyTransactionHelper helper(CreateGetRequest(),
BoundNetLog(), GetParam());
@@ -4541,4 +4543,94 @@ TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
net::HttpStreamFactory::set_spdy_enabled(true);
}
+
+// Tests that Basic authentication works over SPDY
+TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
+ net::HttpStreamFactory::set_spdy_enabled(true);
+
+ // The first request will be a bare GET, the second request will be a
+ // GET with an Authorization header.
+ scoped_ptr<spdy::SpdyFrame> req_get(
+ ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
+ const char* const kExtraAuthorizationHeaders[] = {
+ "authorization",
+ "Basic Zm9vOmJhcg==",
+ };
+ scoped_ptr<spdy::SpdyFrame> req_get_authorization(
+ ConstructSpdyGet(
+ kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
+ false, 3, LOWEST));
+ MockWrite spdy_writes[] = {
+ CreateMockWrite(*req_get, 1),
+ CreateMockWrite(*req_get_authorization, 4),
+ };
+
+ // The first response is a 401 authentication challenge, and the second
+ // response will be a 200 response since the second request includes a valid
+ // Authorization header.
+ const char* const kExtraAuthenticationHeaders[] = {
+ "WWW-Authenticate",
+ "Basic realm=\"MyRealm\""
+ };
+ scoped_ptr<spdy::SpdyFrame> resp_authentication(
+ ConstructSpdySynReplyError(
+ "401 Authentication Required",
+ kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
+ 1));
+ scoped_ptr<spdy::SpdyFrame> body_authentication(
+ ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
+ MockRead spdy_reads[] = {
+ CreateMockRead(*resp_authentication, 2),
+ CreateMockRead(*body_authentication, 3),
+ CreateMockRead(*resp_data, 5),
+ CreateMockRead(*body_data, 6),
+ MockRead(true, 0, 7),
+ };
+
+ scoped_refptr<OrderedSocketData> data(
+ new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
+ spdy_writes, arraysize(spdy_writes)));
+ HttpRequestInfo request(CreateGetRequest());
+ BoundNetLog net_log;
+ NormalSpdyTransactionHelper helper(request, net_log, GetParam());
+
+ helper.RunPreTestSetup();
+ helper.AddData(data.get());
+ HttpNetworkTransaction* trans = helper.trans();
+ TestCompletionCallback callback_start;
+ const int rv_start = trans->Start(&request, &callback_start, net_log);
+ EXPECT_EQ(ERR_IO_PENDING, rv_start);
+ const int rv_start_complete = callback_start.WaitForResult();
+ EXPECT_EQ(OK, rv_start_complete);
+
+ // Make sure the response has an auth challenge.
+ const HttpResponseInfo* const response_start = trans->GetResponseInfo();
+ ASSERT_TRUE(response_start != NULL);
+ ASSERT_TRUE(response_start->headers != NULL);
+ EXPECT_EQ(401, response_start->headers->response_code());
+ EXPECT_TRUE(response_start->was_fetched_via_spdy);
+ ASSERT_TRUE(response_start->auth_challenge.get() != NULL);
+ EXPECT_FALSE(response_start->auth_challenge->is_proxy);
+ EXPECT_EQ(L"basic", response_start->auth_challenge->scheme);
+ EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm);
+
+ // Restart with a username/password.
+ const string16 kFoo(ASCIIToUTF16("foo"));
+ const string16 kBar(ASCIIToUTF16("bar"));
+ TestCompletionCallback callback_restart;
+ const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart);
+ EXPECT_EQ(ERR_IO_PENDING, rv_restart);
+ const int rv_restart_complete = callback_restart.WaitForResult();
+ EXPECT_EQ(OK, rv_restart_complete);
+ // TODO(cbentzel): This is actually the same response object as before, but
+ // data has changed.
+ const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
+ ASSERT_TRUE(response_restart != NULL);
+ ASSERT_TRUE(response_restart->headers != NULL);
+ EXPECT_EQ(200, response_restart->headers->response_code());
+ EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
+}
+
} // namespace net
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 53bcb0d..8066007 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -120,6 +120,10 @@ bool SpdyProxyClientSocket::WasEverUsed() const {
return was_ever_used_ || (spdy_stream_ && spdy_stream_->WasEverUsed());
}
+bool SpdyProxyClientSocket::UsingTCPFastOpen() const {
+ return false;
+}
+
int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(!read_callback_);
@@ -306,8 +310,8 @@ int SpdyProxyClientSocket::DoSendRequest() {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
- new NetLogHttpRequestParameter(
- request_line, request_headers));
+ make_scoped_refptr(new NetLogHttpRequestParameter(
+ request_line, request_headers)));
}
request_.extra_headers.MergeFrom(request_headers);
@@ -346,7 +350,7 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
- new NetLogHttpResponseParameter(response_.headers));
+ make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
if (response_.headers->response_code() == 200)
@@ -400,9 +404,10 @@ int SpdyProxyClientSocket::OnResponseReceived(
void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) {
if (length > 0) {
// Save the received data.
- scoped_refptr<IOBuffer> io_buffer = new IOBuffer(length);
+ scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length));
memcpy(io_buffer->data(), data, length);
- read_buffer_.push_back(new DrainableIOBuffer(io_buffer, length));
+ read_buffer_.push_back(
+ make_scoped_refptr(new DrainableIOBuffer(io_buffer, length)));
}
if (read_callback_) {
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index b993b5e..4a0747e 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -71,6 +71,7 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index f94dfd3..7035bb8 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -216,6 +216,9 @@ bool SpdySession::use_ssl_ = true;
// static
bool SpdySession::use_flow_control_ = false;
+// static
+size_t SpdySession::max_concurrent_stream_limit_ = 256;
+
SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair,
SpdySessionPool* spdy_session_pool,
SpdySettingsStorage* spdy_settings,
@@ -252,7 +255,8 @@ SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair,
DCHECK(HttpStreamFactory::spdy_enabled());
net_log_.BeginEvent(
NetLog::TYPE_SPDY_SESSION,
- new NetLogSpdySessionParameter(host_port_proxy_pair_));
+ make_scoped_refptr(
+ new NetLogSpdySessionParameter(host_port_proxy_pair_)));
// TODO(mbelshe): consider randomization of the stream_hi_water_mark.
@@ -460,7 +464,8 @@ int SpdySession::WriteSynStream(
if (net_log().IsLoggingAllEvents()) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
- new NetLogSpdySynParameter(headers, flags, stream_id));
+ make_scoped_refptr(
+ new NetLogSpdySynParameter(headers, flags, stream_id)));
}
return ERR_IO_PENDING;
@@ -491,8 +496,10 @@ int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id,
// as stalled - because only the session knows for sure when the
// stall occurs.
stream->set_stalled_by_flow_control(true);
- net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW,
- new NetLogIntegerParameter("stream_id", stream_id));
+ net_log().AddEvent(
+ NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW,
+ make_scoped_refptr(
+ new NetLogIntegerParameter("stream_id", stream_id)));
return ERR_IO_PENDING;
}
int new_len = std::min(len, stream->send_window_size());
@@ -503,9 +510,11 @@ int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id,
stream->DecreaseSendWindowSize(len);
}
- if (net_log().IsLoggingAllEvents())
- net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_SEND_DATA,
- new NetLogSpdyDataParameter(stream_id, len, flags));
+ if (net_log().IsLoggingAllEvents()) {
+ net_log().AddEvent(
+ NetLog::TYPE_SPDY_SESSION_SEND_DATA,
+ make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags)));
+ }
// TODO(mbelshe): reduce memory copies here.
scoped_ptr<spdy::SpdyDataFrame> frame(
@@ -526,7 +535,7 @@ void SpdySession::ResetStream(
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM,
- new NetLogSpdyRstParameter(stream_id, status));
+ make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status)));
scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame(
spdy_framer_.CreateRstStream(stream_id, status));
@@ -826,8 +835,9 @@ void SpdySession::CloseSessionOnError(net::Error err, bool remove_from_pool) {
scoped_refptr<SpdySession> self(this);
DCHECK_LT(err, OK);
- net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_CLOSE,
- new NetLogIntegerParameter("status", err));
+ net_log_.AddEvent(
+ NetLog::TYPE_SPDY_SESSION_CLOSE,
+ make_scoped_refptr(new NetLogIntegerParameter("status", err)));
// Don't close twice. This can occur because we can have both
// a read and a write outstanding, and each can complete with
@@ -909,7 +919,7 @@ void SpdySession::DeleteStream(spdy::SpdyStreamId id, int status) {
void SpdySession::RemoveFromPool() {
if (spdy_session_pool_) {
- spdy_session_pool_->Remove(this);
+ spdy_session_pool_->Remove(make_scoped_refptr(this));
spdy_session_pool_ = NULL;
}
}
@@ -960,9 +970,12 @@ void SpdySession::OnError(spdy::SpdyFramer* framer) {
void SpdySession::OnStreamFrameData(spdy::SpdyStreamId stream_id,
const char* data,
size_t len) {
- if (net_log().IsLoggingAllEvents())
- net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_RECV_DATA,
- new NetLogSpdyDataParameter(stream_id, len, spdy::SpdyDataFlags()));
+ if (net_log().IsLoggingAllEvents()) {
+ net_log().AddEvent(
+ NetLog::TYPE_SPDY_SESSION_RECV_DATA,
+ make_scoped_refptr(new NetLogSpdyDataParameter(
+ stream_id, len, spdy::SpdyDataFlags())));
+ }
if (!IsStreamActive(stream_id)) {
// NOTE: it may just be that the stream was cancelled.
@@ -996,9 +1009,9 @@ void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame,
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM,
- new NetLogSpdySynParameter(
+ make_scoped_refptr(new NetLogSpdySynParameter(
headers, static_cast<spdy::SpdyControlFlags>(frame.flags()),
- stream_id));
+ stream_id)));
}
// Server-initiated streams should have even sequence numbers.
@@ -1051,8 +1064,8 @@ void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame,
return;
}
- scoped_refptr<SpdyStream> stream =
- new SpdyStream(this, stream_id, true, net_log_);
+ scoped_refptr<SpdyStream> stream(
+ new SpdyStream(this, stream_id, true, net_log_));
stream->set_path(path);
@@ -1094,9 +1107,9 @@ void SpdySession::OnSynReply(const spdy::SpdySynReplyControlFrame& frame,
if (net_log().IsLoggingAllEvents()) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
- new NetLogSpdySynParameter(
+ make_scoped_refptr(new NetLogSpdySynParameter(
headers, static_cast<spdy::SpdyControlFlags>(frame.flags()),
- stream_id));
+ stream_id)));
}
Respond(*headers, stream);
@@ -1157,7 +1170,8 @@ void SpdySession::OnRst(const spdy::SpdyRstStreamControlFrame& frame) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_RST_STREAM,
- new NetLogSpdyRstParameter(stream_id, frame.status()));
+ make_scoped_refptr(
+ new NetLogSpdyRstParameter(stream_id, frame.status())));
bool valid_stream = IsStreamActive(stream_id);
if (!valid_stream) {
@@ -1182,9 +1196,10 @@ void SpdySession::OnRst(const spdy::SpdyRstStreamControlFrame& frame) {
void SpdySession::OnGoAway(const spdy::SpdyGoAwayControlFrame& frame) {
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_GOAWAY,
- new NetLogSpdyGoAwayParameter(frame.last_accepted_stream_id(),
- active_streams_.size(),
- unclaimed_pushed_streams_.size()));
+ make_scoped_refptr(
+ new NetLogSpdyGoAwayParameter(frame.last_accepted_stream_id(),
+ active_streams_.size(),
+ unclaimed_pushed_streams_.size())));
RemoveFromPool();
CloseAllStreams(net::ERR_ABORTED);
@@ -1207,7 +1222,7 @@ void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) {
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS,
- new NetLogSpdySettingsParameter(settings));
+ make_scoped_refptr(new NetLogSpdySettingsParameter(settings)));
}
void SpdySession::OnWindowUpdate(
@@ -1235,9 +1250,8 @@ void SpdySession::OnWindowUpdate(
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_SEND_WINDOW_UPDATE,
- new NetLogSpdyWindowUpdateParameter(stream_id,
- delta_window_size,
- stream->send_window_size()));
+ make_scoped_refptr(new NetLogSpdyWindowUpdateParameter(
+ stream_id, delta_window_size, stream->send_window_size())));
}
void SpdySession::SendWindowUpdate(spdy::SpdyStreamId stream_id,
@@ -1248,9 +1262,8 @@ void SpdySession::SendWindowUpdate(spdy::SpdyStreamId stream_id,
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_RECV_WINDOW_UPDATE,
- new NetLogSpdyWindowUpdateParameter(stream_id,
- delta_window_size,
- stream->recv_window_size()));
+ make_scoped_refptr(new NetLogSpdyWindowUpdateParameter(
+ stream_id, delta_window_size, stream->recv_window_size())));
scoped_ptr<spdy::SpdyWindowUpdateControlFrame> window_update_frame(
spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size));
@@ -1265,7 +1278,7 @@ void SpdySession::SendSettings() {
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
- new NetLogSpdySettingsParameter(settings));
+ make_scoped_refptr(new NetLogSpdySettingsParameter(settings)));
// Create the SETTINGS frame and send it.
scoped_ptr<spdy::SpdySettingsControlFrame> settings_frame(
@@ -1281,7 +1294,8 @@ void SpdySession::HandleSettings(const spdy::SpdySettings& settings) {
const uint32 val = i->second;
switch (id) {
case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
- max_concurrent_streams_ = val;
+ max_concurrent_streams_ = std::min(static_cast<size_t>(val),
+ max_concurrent_stream_limit_);
ProcessPendingCreateStreams();
break;
}
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index f90907d..7d12d50 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -140,6 +140,14 @@ class SpdySession : public base::RefCounted<SpdySession>,
static void set_flow_control(bool enable) { use_flow_control_ = enable; }
static bool flow_control() { return use_flow_control_; }
+ // Sets the max concurrent streams per session.
+ static void set_max_concurrent_streams(size_t value) {
+ max_concurrent_stream_limit_ = value;
+ }
+ static size_t max_concurrent_streams() {
+ return max_concurrent_stream_limit_;
+ }
+
// Send WINDOW_UPDATE frame, called by a stream whenever receive window
// size is increased.
void SendWindowUpdate(spdy::SpdyStreamId stream_id, int delta_window_size);
@@ -199,7 +207,7 @@ class SpdySession : public base::RefCounted<SpdySession>,
CLOSED
};
- enum { kDefaultMaxConcurrentStreams = 100 }; // TODO(mbelshe) remove this
+ enum { kDefaultMaxConcurrentStreams = 6 }; // TODO(mbelshe) remove this
struct PendingCreateStream {
const GURL* url;
@@ -400,6 +408,7 @@ class SpdySession : public base::RefCounted<SpdySession>,
static bool use_ssl_;
static bool use_flow_control_;
+ static size_t max_concurrent_stream_limit_;
};
} // namespace net
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index fe2a310..aa807af 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -41,9 +41,10 @@ scoped_refptr<SpdySession> SpdySessionPool::Get(
if (list->size() >= static_cast<unsigned int>(g_max_sessions_per_domain)) {
spdy_session = list->front();
list->pop_front();
- net_log.AddEvent(NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION,
- new NetLogSourceParameter("session",
- spdy_session->net_log().source()));
+ net_log.AddEvent(
+ NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION,
+ make_scoped_refptr(new NetLogSourceParameter(
+ "session", spdy_session->net_log().source())));
}
} else {
list = AddSessionList(host_port_proxy_pair);
@@ -53,9 +54,10 @@ scoped_refptr<SpdySession> SpdySessionPool::Get(
if (!spdy_session) {
spdy_session = new SpdySession(host_port_proxy_pair, this, spdy_settings,
net_log.net_log());
- net_log.AddEvent(NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION,
- new NetLogSourceParameter("session",
- spdy_session->net_log().source()));
+ net_log.AddEvent(
+ NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION,
+ make_scoped_refptr(new NetLogSourceParameter(
+ "session", spdy_session->net_log().source())));
}
DCHECK(spdy_session);
@@ -81,9 +83,10 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket(
DCHECK(list->empty());
list->push_back(*spdy_session);
- net_log.AddEvent(NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET,
- new NetLogSourceParameter("session",
- (*spdy_session)->net_log().source()));
+ net_log.AddEvent(
+ NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET,
+ make_scoped_refptr(new NetLogSourceParameter(
+ "session", (*spdy_session)->net_log().source())));
// Now we can initialize the session with the SSL socket.
return (*spdy_session)->InitializeWithSocket(connection, is_secure,
@@ -103,9 +106,10 @@ void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) {
if (!list)
return;
list->remove(session);
- session->net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_POOL_REMOVE_SESSION,
- new NetLogSourceParameter("session",
- session->net_log().source()));
+ session->net_log().AddEvent(
+ NetLog::TYPE_SPDY_SESSION_POOL_REMOVE_SESSION,
+ make_scoped_refptr(new NetLogSourceParameter(
+ "session", session->net_log().source())));
if (list->empty())
RemoveSessionList(session->host_port_proxy_pair());
}
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 4a66406..0cfbe48 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -91,8 +91,8 @@ TEST_F(SpdySessionTest, GoAway) {
BoundNetLog());
EXPECT_TRUE(spdy_session_pool->HasSession(pair));
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
EXPECT_EQ(OK,
connection->Init(test_host_port_pair.ToString(), tcp_params, MEDIUM,
@@ -200,8 +200,8 @@ TEST_F(SpdySessionTest, OnSettings) {
BoundNetLog());
ASSERT_TRUE(spdy_session_pool->HasSession(pair));
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
EXPECT_EQ(OK,
connection->Init(test_host_port_pair.ToString(), tcp_params, MEDIUM,
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index 102d318..f26dd6d 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -60,8 +60,9 @@ SpdyStream::SpdyStream(SpdySession* session,
net_log_(net_log),
send_bytes_(0),
recv_bytes_(0) {
- net_log_.BeginEvent(NetLog::TYPE_SPDY_STREAM,
- new NetLogIntegerParameter("stream_id", stream_id_));
+ net_log_.BeginEvent(
+ NetLog::TYPE_SPDY_STREAM,
+ make_scoped_refptr(new NetLogIntegerParameter("stream_id", stream_id_)));
}
SpdyStream::~SpdyStream() {
@@ -148,9 +149,10 @@ void SpdyStream::IncreaseSendWindowSize(int delta_window_size) {
send_window_size_ = new_window_size;
- net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_SEND_WINDOW_UPDATE,
- new NetLogSpdyStreamWindowUpdateParameter(stream_id_,
- delta_window_size, send_window_size_));
+ net_log_.AddEvent(
+ NetLog::TYPE_SPDY_STREAM_SEND_WINDOW_UPDATE,
+ make_scoped_refptr(new NetLogSpdyStreamWindowUpdateParameter(
+ stream_id_, delta_window_size, send_window_size_)));
if (stalled_by_flow_control_) {
stalled_by_flow_control_ = false;
io_state_ = STATE_SEND_BODY;
@@ -170,9 +172,10 @@ void SpdyStream::DecreaseSendWindowSize(int delta_window_size) {
send_window_size_ -= delta_window_size;
- net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_SEND_WINDOW_UPDATE,
- new NetLogSpdyStreamWindowUpdateParameter(stream_id_,
- -delta_window_size, send_window_size_));
+ net_log_.AddEvent(
+ NetLog::TYPE_SPDY_STREAM_SEND_WINDOW_UPDATE,
+ make_scoped_refptr(new NetLogSpdyStreamWindowUpdateParameter(
+ stream_id_, -delta_window_size, send_window_size_)));
}
void SpdyStream::IncreaseRecvWindowSize(int delta_window_size) {
@@ -185,9 +188,10 @@ void SpdyStream::IncreaseRecvWindowSize(int delta_window_size) {
DCHECK(new_window_size > 0);
recv_window_size_ = new_window_size;
- net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_RECV_WINDOW_UPDATE,
- new NetLogSpdyStreamWindowUpdateParameter(stream_id_,
- delta_window_size, recv_window_size_));
+ net_log_.AddEvent(
+ NetLog::TYPE_SPDY_STREAM_RECV_WINDOW_UPDATE,
+ make_scoped_refptr(new NetLogSpdyStreamWindowUpdateParameter(
+ stream_id_, delta_window_size, recv_window_size_)));
session_->SendWindowUpdate(stream_id_, delta_window_size);
}
@@ -195,9 +199,10 @@ void SpdyStream::DecreaseRecvWindowSize(int delta_window_size) {
DCHECK_GE(delta_window_size, 1);
recv_window_size_ -= delta_window_size;
- net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_RECV_WINDOW_UPDATE,
- new NetLogSpdyStreamWindowUpdateParameter(stream_id_,
- -delta_window_size, recv_window_size_));
+ net_log_.AddEvent(
+ NetLog::TYPE_SPDY_STREAM_RECV_WINDOW_UPDATE,
+ make_scoped_refptr(new NetLogSpdyStreamWindowUpdateParameter(
+ stream_id_, -delta_window_size, recv_window_size_)));
// Since we never decrease the initial window size, we should never hit
// a negative |recv_window_size_|, if we do, it's a flow-control violation.
@@ -257,7 +262,7 @@ void SpdyStream::OnDataReceived(const char* data, int length) {
if (length > 0) {
IOBufferWithSize* buf = new IOBufferWithSize(length);
memcpy(buf->data(), data, length);
- pending_buffers_.push_back(buf);
+ pending_buffers_.push_back(make_scoped_refptr(buf));
} else {
pending_buffers_.push_back(NULL);
metrics_.StopStream();
@@ -298,7 +303,7 @@ void SpdyStream::OnDataReceived(const char* data, int length) {
// We'll return received data when delegate gets attached to the stream.
IOBufferWithSize* buf = new IOBufferWithSize(length);
memcpy(buf->data(), data, length);
- pending_buffers_.push_back(buf);
+ pending_buffers_.push_back(make_scoped_refptr(buf));
return;
}
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 5ece945..cdb116f 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -192,8 +192,8 @@ TEST_F(SpdyStreamTest, SendDataAfterOpen) {
GURL url("http://www.google.com/");
HostPortPair host_port_pair("www.google.com", 80);
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams(host_port_pair, LOWEST, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams(host_port_pair, LOWEST, GURL(), false));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
EXPECT_EQ(OK,
diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc
index d3b82c0..896cd9d 100644
--- a/net/spdy/spdy_test_util.cc
+++ b/net/spdy/spdy_test_util.cc
@@ -519,23 +519,23 @@ spdy::SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
associated_stream_id);
}
-// Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
-// |extra_headers| are the extra header-value pairs, which typically
-// will vary the most between calls.
+// Constructs a standard SPDY SYN_REPLY packet with the specified status code.
// Returns a SpdyFrame.
-spdy::SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
- static const char* const kStandardGetHeaders[] = {
+spdy::SpdyFrame* ConstructSpdySynReplyError(
+ const char* const status,
+ const char* const* const extra_headers,
+ int extra_header_count,
+ int stream_id) {
+ const char* const kStandardGetHeaders[] = {
"hello",
"bye",
"status",
- "301 Moved Permanently",
- "location",
- "http://www.foo.com/index.php",
+ status,
"version",
"HTTP/1.1"
};
- return ConstructSpdyControlFrame(NULL,
- 0,
+ return ConstructSpdyControlFrame(extra_headers,
+ extra_header_count,
false,
stream_id,
LOWEST,
@@ -545,35 +545,28 @@ spdy::SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
arraysize(kStandardGetHeaders));
}
+// Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
+// |extra_headers| are the extra header-value pairs, which typically
+// will vary the most between calls.
+// Returns a SpdyFrame.
+spdy::SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
+ static const char* const kExtraHeaders[] = {
+ "location",
+ "http://www.foo.com/index.php",
+ };
+ return ConstructSpdySynReplyError("301 Moved Permanently", kExtraHeaders,
+ arraysize(kExtraHeaders)/2, stream_id);
+}
+
// Constructs a standard SPDY SYN_REPLY packet with an Internal Server
// Error status code.
// Returns a SpdyFrame.
spdy::SpdyFrame* ConstructSpdySynReplyError(int stream_id) {
- return ConstructSpdySynReplyError("500 Internal Server Error", 1);
+ return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
}
-// Constructs a standard SPDY SYN_REPLY packet with the specified status code.
-// Returns a SpdyFrame.
-spdy::SpdyFrame* ConstructSpdySynReplyError(const char* const status,
- int stream_id) {
- static const char* const kStandardGetHeaders[] = {
- "hello",
- "bye",
- "status",
- status,
- "version",
- "HTTP/1.1"
- };
- return ConstructSpdyControlFrame(NULL,
- 0,
- false,
- stream_id,
- LOWEST,
- spdy::SYN_REPLY,
- spdy::CONTROL_FLAG_NONE,
- kStandardGetHeaders,
- arraysize(kStandardGetHeaders));
-}
+
+
// Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
// |extra_headers| are the extra header-value pairs, which typically
diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h
index e3e85c8..aecf08e 100644
--- a/net/spdy/spdy_test_util.h
+++ b/net/spdy/spdy_test_util.h
@@ -260,8 +260,12 @@ spdy::SpdyFrame* ConstructSpdySynReplyError(int stream_id);
// Constructs a standard SPDY SYN_REPLY packet with the specified status code.
// Returns a SpdyFrame.
-spdy::SpdyFrame* ConstructSpdySynReplyError(const char* const status,
- int stream_id);
+spdy::SpdyFrame* ConstructSpdySynReplyError(
+ const char* const status,
+ const char* const* const extra_headers,
+ int extra_header_count,
+ int stream_id);
+
// Constructs a standard SPDY POST SYN packet.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
diff --git a/net/test/test_server.cc b/net/test/test_server.cc
index c3359a4..4b426eb 100644
--- a/net/test/test_server.cc
+++ b/net/test/test_server.cc
@@ -15,8 +15,8 @@
#endif
#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
#include "base/file_util.h"
-#include "base/leak_annotations.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
@@ -30,6 +30,8 @@
#include "net/test/python_utils.h"
#include "testing/platform_test.h"
+namespace net {
+
namespace {
// Number of connection attempts for tests.
@@ -40,30 +42,43 @@ const int kServerConnectionTimeoutMs = 1000;
const char kTestServerShardFlag[] = "test-server-shard";
-int GetPortBase(net::TestServer::Type type) {
- switch (type) {
- case net::TestServer::TYPE_FTP:
- return 3117;
- case net::TestServer::TYPE_HTTP:
- return 1337;
- case net::TestServer::TYPE_HTTPS:
+int GetHTTPSPortBase(const TestServer::HTTPSOptions& options) {
+ if (options.request_client_certificate)
+ return 9543;
+
+ switch (options.server_certificate) {
+ case TestServer::HTTPSOptions::CERT_OK:
return 9443;
- case net::TestServer::TYPE_HTTPS_CLIENT_AUTH:
- return 9543;
- case net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE:
+ case TestServer::HTTPSOptions::CERT_MISMATCHED_NAME:
+ return 9643;
+ case TestServer::HTTPSOptions::CERT_EXPIRED:
// TODO(phajdan.jr): Some tests rely on this hardcoded value.
// Some uses of this are actually in .html/.js files.
return 9666;
- case net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME:
- return 9643;
default:
NOTREACHED();
}
return -1;
}
-int GetPort(net::TestServer::Type type) {
- int port = GetPortBase(type);
+int GetPortBase(TestServer::Type type,
+ const TestServer::HTTPSOptions& options) {
+ switch (type) {
+ case TestServer::TYPE_FTP:
+ return 3117;
+ case TestServer::TYPE_HTTP:
+ return 1337;
+ case TestServer::TYPE_HTTPS:
+ return GetHTTPSPortBase(options);
+ default:
+ NOTREACHED();
+ }
+ return -1;
+}
+
+int GetPort(TestServer::Type type,
+ const TestServer::HTTPSOptions& options) {
+ int port = GetPortBase(type, options);
if (CommandLine::ForCurrentProcess()->HasSwitch(kTestServerShardFlag)) {
std::string shard_str(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
kTestServerShardFlag));
@@ -78,8 +93,11 @@ int GetPort(net::TestServer::Type type) {
return port;
}
-std::string GetHostname(net::TestServer::Type type) {
- if (type == net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME) {
+std::string GetHostname(TestServer::Type type,
+ const TestServer::HTTPSOptions& options) {
+ if (type == TestServer::TYPE_HTTPS &&
+ options.server_certificate ==
+ TestServer::HTTPSOptions::CERT_MISMATCHED_NAME) {
// Return a different hostname string that resolves to the same hostname.
return "localhost";
}
@@ -89,16 +107,59 @@ std::string GetHostname(net::TestServer::Type type) {
} // namespace
-namespace net {
-
#if defined(OS_MACOSX)
void SetMacTestCertificate(X509Certificate* cert);
#endif
+TestServer::HTTPSOptions::HTTPSOptions()
+ : server_certificate(CERT_OK),
+ request_client_certificate(false),
+ bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {}
+
+TestServer::HTTPSOptions::HTTPSOptions(
+ TestServer::HTTPSOptions::ServerCertificate cert)
+ : server_certificate(cert),
+ request_client_certificate(false),
+ bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {}
+
+TestServer::HTTPSOptions::~HTTPSOptions() {}
+
+FilePath TestServer::HTTPSOptions::GetCertificateFile() const {
+ switch (server_certificate) {
+ case CERT_OK:
+ case CERT_MISMATCHED_NAME:
+ return FilePath(FILE_PATH_LITERAL("ok_cert.pem"));
+ case CERT_EXPIRED:
+ return FilePath(FILE_PATH_LITERAL("expired_cert.pem"));
+ default:
+ NOTREACHED();
+ }
+ return FilePath();
+}
+
TestServer::TestServer(Type type, const FilePath& document_root)
- : host_port_pair_(GetHostname(type), GetPort(type)),
- process_handle_(base::kNullProcessHandle),
- type_(type) {
+ : type_(type) {
+ Init(document_root);
+}
+
+TestServer::TestServer(const HTTPSOptions& https_options,
+ const FilePath& document_root)
+ : https_options_(https_options), type_(TYPE_HTTPS) {
+ Init(document_root);
+}
+
+TestServer::~TestServer() {
+#if defined(OS_MACOSX)
+ SetMacTestCertificate(NULL);
+#endif
+ Stop();
+}
+
+void TestServer::Init(const FilePath& document_root) {
+ host_port_pair_ = HostPortPair(GetHostname(type_, https_options_),
+ GetPort(type_, https_options_));
+ process_handle_ = base::kNullProcessHandle;
+
FilePath src_dir;
PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
@@ -110,15 +171,8 @@ TestServer::TestServer(Type type, const FilePath& document_root)
.Append(FILE_PATH_LITERAL("certificates"));
}
-TestServer::~TestServer() {
-#if defined(OS_MACOSX)
- SetMacTestCertificate(NULL);
-#endif
- Stop();
-}
-
bool TestServer::Start() {
- if (GetScheme() == "https") {
+ if (type_ == TYPE_HTTPS) {
if (!LoadTestRootCert())
return false;
if (!CheckCATrusted())
@@ -177,9 +231,6 @@ std::string TestServer::GetScheme() const {
case TYPE_HTTP:
return "http";
case TYPE_HTTPS:
- case TYPE_HTTPS_CLIENT_AUTH:
- case TYPE_HTTPS_MISMATCHED_HOSTNAME:
- case TYPE_HTTPS_EXPIRED_CERTIFICATE:
return "https";
default:
NOTREACHED();
@@ -191,7 +242,7 @@ bool TestServer::GetAddressList(AddressList* address_list) const {
DCHECK(address_list);
scoped_ptr<HostResolver> resolver(
- CreateSystemHostResolver(HostResolver::kDefaultParallelism, NULL));
+ CreateSystemHostResolver(HostResolver::kDefaultParallelism, NULL, NULL));
HostResolver::RequestInfo info(host_port_pair_);
int rv = resolver->Resolve(info, address_list, NULL, NULL, BoundNetLog());
if (rv != net::OK) {
@@ -292,21 +343,51 @@ bool TestServer::LoadTestRootCert() {
#endif
}
-FilePath TestServer::GetCertificatePath() {
- switch (type_) {
- case TYPE_FTP:
- case TYPE_HTTP:
- return FilePath();
- case TYPE_HTTPS:
- case TYPE_HTTPS_CLIENT_AUTH:
- case TYPE_HTTPS_MISMATCHED_HOSTNAME:
- return certificates_dir_.AppendASCII("ok_cert.pem");
- case TYPE_HTTPS_EXPIRED_CERTIFICATE:
- return certificates_dir_.AppendASCII("expired_cert.pem");
- default:
- NOTREACHED();
+bool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
+ command_line->AppendSwitchASCII("port",
+ base::IntToString(host_port_pair_.port()));
+ command_line->AppendSwitchPath("data-dir", document_root_);
+
+ if (type_ == TYPE_FTP) {
+ command_line->AppendArg("-f");
+ } else if (type_ == TYPE_HTTPS) {
+ FilePath certificate_path(certificates_dir_);
+ certificate_path = certificate_path.Append(
+ https_options_.GetCertificateFile());
+ if (!file_util::PathExists(certificate_path)) {
+ LOG(ERROR) << "Certificate path " << certificate_path.value()
+ << " doesn't exist. Can't launch https server.";
+ return false;
+ }
+ command_line->AppendSwitchPath("https", certificate_path);
+
+ if (https_options_.request_client_certificate)
+ command_line->AppendSwitch("ssl-client-auth");
+
+ for (std::vector<FilePath>::const_iterator it =
+ https_options_.client_authorities.begin();
+ it != https_options_.client_authorities.end(); ++it) {
+ if (!file_util::PathExists(*it)) {
+ LOG(ERROR) << "Client authority path " << it->value()
+ << " doesn't exist. Can't launch https server.";
+ return false;
+ }
+
+ command_line->AppendSwitchPath("ssl-client-ca", *it);
+ }
+
+ const char kBulkCipherSwitch[] = "ssl-bulk-cipher";
+ if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_RC4)
+ command_line->AppendSwitchASCII(kBulkCipherSwitch, "rc4");
+ if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES128)
+ command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes128");
+ if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES256)
+ command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes256");
+ if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_3DES)
+ command_line->AppendSwitchASCII(kBulkCipherSwitch, "3des");
}
- return FilePath();
+
+ return true;
}
} // namespace net
diff --git a/net/test/test_server.h b/net/test/test_server.h
index 4e68fd9..8affc12 100644
--- a/net/test/test_server.h
+++ b/net/test/test_server.h
@@ -6,9 +6,10 @@
#define NET_TEST_TEST_SERVER_H_
#pragma once
-#include "build/build_config.h"
-
#include <string>
+#include <vector>
+
+#include "build/build_config.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
@@ -25,6 +26,7 @@
#include "net/base/x509_certificate.h"
#endif
+class CommandLine;
class GURL;
namespace net {
@@ -39,12 +41,70 @@ class TestServer {
TYPE_FTP,
TYPE_HTTP,
TYPE_HTTPS,
- TYPE_HTTPS_CLIENT_AUTH,
- TYPE_HTTPS_MISMATCHED_HOSTNAME,
- TYPE_HTTPS_EXPIRED_CERTIFICATE,
+ };
+
+ // Container for various options to control how the HTTPS server is
+ // initialized.
+ struct HTTPSOptions {
+ enum ServerCertificate {
+ CERT_OK,
+ CERT_MISMATCHED_NAME,
+ CERT_EXPIRED,
+ };
+
+ // Bitmask of bulk encryption algorithms that the test server supports
+ // and that can be selectively enabled or disabled.
+ enum BulkCipher {
+ // Special value used to indicate that any algorithm the server supports
+ // is acceptable. Preferred over explicitly OR-ing all ciphers.
+ BULK_CIPHER_ANY = 0,
+
+ BULK_CIPHER_RC4 = (1 << 0),
+ BULK_CIPHER_AES128 = (1 << 1),
+ BULK_CIPHER_AES256 = (1 << 2),
+
+ // NOTE: 3DES support in the Python test server has external
+ // dependencies and not be available on all machines. Clients may not
+ // be able to connect if only 3DES is specified.
+ BULK_CIPHER_3DES = (1 << 3),
+ };
+
+ // Initialize a new HTTPSOptions using CERT_OK as the certificate.
+ HTTPSOptions();
+
+ // Initialize a new HTTPSOptions that will use the specified certificate.
+ explicit HTTPSOptions(ServerCertificate cert);
+ ~HTTPSOptions();
+
+ // Returns the relative filename of the file that contains the
+ // |server_certificate|.
+ FilePath GetCertificateFile() const;
+
+ // The certificate to use when serving requests.
+ ServerCertificate server_certificate;
+
+ // True if a CertificateRequest should be sent to the client during
+ // handshaking.
+ bool request_client_certificate;
+
+ // If |request_client_certificate| is true, an optional list of files,
+ // each containing a single, PEM-encoded X.509 certificates. The subject
+ // from each certificate will be added to the certificate_authorities
+ // field of the CertificateRequest.
+ std::vector<FilePath> client_authorities;
+
+ // A bitwise-OR of BulkCipher that should be used by the
+ // HTTPS server, or BULK_CIPHER_ANY to indicate that all implemented
+ // ciphers are acceptable.
+ int bulk_ciphers;
};
TestServer(Type type, const FilePath& document_root);
+
+ // Initialize a HTTPS TestServer with a specific set of HTTPSOptions.
+ TestServer(const HTTPSOptions& https_options,
+ const FilePath& document_root);
+
~TestServer();
bool Start() WARN_UNUSED_RESULT;
@@ -67,6 +127,8 @@ class TestServer {
const std::string& password);
private:
+ void Init(const FilePath& document_root);
+
// Modify PYTHONPATH to contain libraries we need.
bool SetPythonPath() WARN_UNUSED_RESULT;
@@ -85,9 +147,9 @@ class TestServer {
// Load the test root cert, if it hasn't been loaded yet.
bool LoadTestRootCert() WARN_UNUSED_RESULT;
- // Returns path to the SSL certificate we should use, or empty path
- // if not applicable.
- FilePath GetCertificatePath();
+ // Add the command line arguments for the Python test server to
+ // |command_line|. Return true on success.
+ bool AddCommandLineArguments(CommandLine* command_line) const;
// Document root of the test server.
FilePath document_root_;
@@ -105,8 +167,11 @@ class TestServer {
// JobObject used to clean up orphaned child processes.
ScopedHandle job_handle_;
- // The file handle the child writes to when it starts.
- ScopedHandle child_fd_;
+ // The pipe file handle we read from.
+ ScopedHandle child_read_fd_;
+
+ // The pipe file handle the child and we write to.
+ ScopedHandle child_write_fd_;
#endif
#if defined(OS_POSIX)
@@ -115,6 +180,9 @@ class TestServer {
file_util::ScopedFD child_fd_closer_;
#endif
+ // If |type_| is TYPE_HTTPS, the TLS settings to use for the test server.
+ HTTPSOptions https_options_;
+
#if defined(USE_NSS)
scoped_refptr<X509Certificate> cert_;
#endif
diff --git a/net/test/test_server_posix.cc b/net/test/test_server_posix.cc
index 6e65bcf..707eb93 100644
--- a/net/test/test_server_posix.cc
+++ b/net/test/test_server_posix.cc
@@ -4,13 +4,17 @@
#include "net/test/test_server.h"
+#include <poll.h>
+
#include <vector>
+#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
+#include "base/test/test_timeouts.h"
namespace {
@@ -52,28 +56,12 @@ class OrphanedTestServerFilter : public base::ProcessFilter {
} // namespace
namespace net {
-bool TestServer::LaunchPython(const FilePath& testserver_path) {
- std::vector<std::string> command_line;
- command_line.push_back("python");
- command_line.push_back(testserver_path.value());
- command_line.push_back("--port=" + base::IntToString(host_port_pair_.port()));
- command_line.push_back("--data-dir=" + document_root_.value());
-
- if (type_ == TYPE_FTP)
- command_line.push_back("-f");
-
- FilePath certificate_path(GetCertificatePath());
- if (!certificate_path.value().empty()) {
- if (!file_util::PathExists(certificate_path)) {
- LOG(ERROR) << "Certificate path " << certificate_path.value()
- << " doesn't exist. Can't launch https server.";
- return false;
- }
- command_line.push_back("--https=" + certificate_path.value());
- }
- if (type_ == TYPE_HTTPS_CLIENT_AUTH)
- command_line.push_back("--ssl-client-auth");
+bool TestServer::LaunchPython(const FilePath& testserver_path) {
+ CommandLine python_command(FilePath(FILE_PATH_LITERAL("python")));
+ python_command.AppendArgPath(testserver_path);
+ if (!AddCommandLineArguments(&python_command))
+ return false;
int pipefd[2];
if (pipe(pipefd) != 0) {
@@ -88,7 +76,8 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
base::file_handle_mapping_vector map_write_fd;
map_write_fd.push_back(std::make_pair(pipefd[1], pipefd[1]));
- command_line.push_back("--startup-pipe=" + base::IntToString(pipefd[1]));
+ python_command.AppendSwitchASCII("startup-pipe",
+ base::IntToString(pipefd[1]));
// Try to kill any orphaned testserver processes that may be running.
OrphanedTestServerFilter filter(testserver_path.value(),
@@ -98,8 +87,10 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
}
// Launch a new testserver process.
- if (!base::LaunchApp(command_line, map_write_fd, false, &process_handle_)) {
- LOG(ERROR) << "Failed to launch " << command_line[0] << " ...";
+ if (!base::LaunchApp(python_command.argv(), map_write_fd, false,
+ &process_handle_)) {
+ LOG(ERROR) << "Failed to launch " << python_command.command_line_string()
+ << " ...";
return false;
}
@@ -107,6 +98,19 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
}
bool TestServer::WaitToStart() {
+ struct pollfd poll_fds[1];
+
+ poll_fds[0].fd = child_fd_;
+ poll_fds[0].events = POLLIN | POLLPRI;
+ poll_fds[0].revents = 0;
+
+ int rv = HANDLE_EINTR(poll(poll_fds, 1,
+ TestTimeouts::action_max_timeout_ms()));
+ if (rv != 1) {
+ LOG(ERROR) << "Failed to poll for the child file descriptor.";
+ return false;
+ }
+
char buf[8];
ssize_t n = HANDLE_EINTR(read(child_fd_, buf, sizeof(buf)));
// We don't need the FD anymore.
diff --git a/net/test/test_server_win.cc b/net/test/test_server_win.cc
index a8b3678..c6e10d5 100644
--- a/net/test/test_server_win.cc
+++ b/net/test/test_server_win.cc
@@ -8,17 +8,21 @@
#include <wincrypt.h>
#include "base/base_paths.h"
+#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
+#include "base/test/test_timeouts.h"
+#include "base/thread.h"
#include "base/utf_string_conversions.h"
#pragma comment(lib, "crypt32.lib")
namespace {
-bool LaunchTestServerAsJob(const std::wstring& cmdline,
+bool LaunchTestServerAsJob(const CommandLine& cmdline,
bool start_hidden,
base::ProcessHandle* process_handle,
ScopedHandle* job_handle) {
@@ -32,10 +36,10 @@ bool LaunchTestServerAsJob(const std::wstring& cmdline,
// If this code is run under a debugger, the test server process is
// automatically associated with a job object created by the debugger.
// The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this.
- if (!CreateProcess(NULL,
- const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
- TRUE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL,
- &startup_info, &process_info)) {
+ if (!CreateProcess(
+ NULL, const_cast<wchar_t*>(cmdline.command_line_string().c_str()),
+ NULL, NULL, TRUE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL,
+ &startup_info, &process_info)) {
LOG(ERROR) << "Could not create process.";
return false;
}
@@ -71,9 +75,21 @@ bool LaunchTestServerAsJob(const std::wstring& cmdline,
return true;
}
+void UnblockPipe(HANDLE handle, bool* unblocked) {
+ static const char kUnblock[] = "UNBLOCK";
+ // Unblock the ReadFile in TestServer::WaitToStart by writing to the pipe.
+ // Make sure the call succeeded, otherwise we are very likely to hang.
+ DWORD bytes_written = 0;
+ CHECK(WriteFile(handle, kUnblock, arraysize(kUnblock), &bytes_written,
+ NULL));
+ CHECK_EQ(arraysize(kUnblock), bytes_written);
+ *unblocked = true;
+}
+
} // namespace
namespace net {
+
bool TestServer::LaunchPython(const FilePath& testserver_path) {
FilePath python_exe;
if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_exe))
@@ -83,29 +99,10 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
.Append(FILE_PATH_LITERAL("python_24"))
.Append(FILE_PATH_LITERAL("python.exe"));
- std::wstring command_line =
- L"\"" + python_exe.value() + L"\" " +
- L"\"" + testserver_path.value() +
- L"\" --port=" + ASCIIToWide(base::IntToString(host_port_pair_.port())) +
- L" --data-dir=\"" + document_root_.value() + L"\"";
-
- if (type_ == TYPE_FTP)
- command_line.append(L" -f");
-
- FilePath certificate_path(GetCertificatePath());
- if (!certificate_path.value().empty()) {
- if (!file_util::PathExists(certificate_path)) {
- LOG(ERROR) << "Certificate path " << certificate_path.value()
- << " doesn't exist. Can't launch https server.";
- return false;
- }
- command_line.append(L" --https=\"");
- command_line.append(certificate_path.value());
- command_line.append(L"\"");
- }
-
- if (type_ == TYPE_HTTPS_CLIENT_AUTH)
- command_line.append(L" --ssl-client-auth");
+ CommandLine python_command(python_exe);
+ python_command.AppendArgPath(testserver_path);
+ if (!AddCommandLineArguments(&python_command))
+ return false;
HANDLE child_read = NULL;
HANDLE child_write = NULL;
@@ -113,8 +110,8 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
PLOG(ERROR) << "Failed to create pipe";
return false;
}
- child_fd_.Set(child_read);
- ScopedHandle scoped_child_write(child_write);
+ child_read_fd_.Set(child_read);
+ child_write_fd_.Set(child_write);
// Have the child inherit the write half.
if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT,
@@ -133,15 +130,15 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
// safe to truncate the handle (when passing it from 64-bit to
// 32-bit) or sign-extend the handle (when passing it from 32-bit to
// 64-bit)."
- command_line.append(
- L" --startup-pipe=" +
- ASCIIToWide(base::IntToString(reinterpret_cast<uintptr_t>(child_write))));
+ python_command.AppendSwitchASCII(
+ "startup-pipe",
+ base::IntToString(reinterpret_cast<uintptr_t>(child_write)));
- if (!LaunchTestServerAsJob(command_line,
+ if (!LaunchTestServerAsJob(python_command,
true,
&process_handle_,
&job_handle_)) {
- LOG(ERROR) << "Failed to launch " << command_line;
+ LOG(ERROR) << "Failed to launch " << python_command.command_line_string();
return false;
}
@@ -149,10 +146,29 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
}
bool TestServer::WaitToStart() {
+ base::Thread thread("test_server_watcher");
+ if (!thread.Start())
+ return false;
+
+ // Prepare a timeout in case the server fails to start.
+ bool unblocked = false;
+ thread.message_loop()->PostDelayedTask(FROM_HERE,
+ NewRunnableFunction(UnblockPipe, child_write_fd_.Get(), &unblocked),
+ TestTimeouts::action_max_timeout_ms());
+
char buf[8];
DWORD bytes_read;
- BOOL result = ReadFile(child_fd_, buf, sizeof(buf), &bytes_read, NULL);
- child_fd_.Close();
+ BOOL result = ReadFile(child_read_fd_.Get(), buf, sizeof(buf), &bytes_read,
+ NULL);
+
+ thread.Stop();
+ child_read_fd_.Close();
+ child_write_fd_.Close();
+
+ // If we hit the timeout, fail.
+ if (unblocked)
+ return false;
+
return result && bytes_read > 0;
}
diff --git a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
index f4ec31a..4b49929 100644
--- a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
+++ b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
@@ -221,15 +221,8 @@ SetCertTrust(const net::X509Certificate* cert,
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
nsscert,
trust.GetTrust());
- } else if (type == net::EMAIL_CERT) {
- // always start with untrusted and move up
- trust.SetValidPeer();
- trust.AddPeerTrust(0, trusted & net::CertDatabase::TRUSTED_EMAIL, 0);
- srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
- nsscert,
- trust.GetTrust());
} else {
- // ignore user certs
+ // ignore user and email/unknown certs
return true;
}
if (srv != SECSuccess)
diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp
index a804e92..7a0d21e 100644
--- a/net/third_party/nss/ssl.gyp
+++ b/net/third_party/nss/ssl.gyp
@@ -53,6 +53,7 @@
'ssl/sslmutex.c',
'ssl/sslmutex.h',
'ssl/sslnonce.c',
+ 'ssl/sslplatf.c',
'ssl/sslproto.h',
'ssl/sslreveal.c',
'ssl/sslsecur.c',
@@ -83,6 +84,13 @@
'NO_NSPR_10_SUPPORT',
],
'conditions': [
+ [ 'OS=="mac"', {
+ 'defines': [
+ 'XP_UNIX',
+ 'DARWIN',
+ 'XP_MACOSX',
+ ],
+ }],
[ 'OS == "win"', {
'sources!': [
'ssl/unix_err.c',
@@ -122,6 +130,9 @@
'sources/': [
['exclude', 'ssl/bodge/'],
],
+ 'defines': [
+ 'NSS_PLATFORM_CLIENT_AUTH',
+ ],
'dependencies': [
'../../../third_party/zlib/zlib.gyp:zlib',
'../../../third_party/nss/nss.gyp:nss',
@@ -130,6 +141,9 @@
'include_dirs': [
'ssl',
],
+ 'defines': [
+ 'NSS_PLATFORM_CLIENT_AUTH',
+ ],
},
}],
],
diff --git a/net/third_party/nss/ssl/snapstart.c b/net/third_party/nss/ssl/snapstart.c
index ca2cafa..92406a7 100644
--- a/net/third_party/nss/ssl/snapstart.c
+++ b/net/third_party/nss/ssl/snapstart.c
@@ -48,10 +48,6 @@
/* TODO(agl): Add support for snap starting with compression. */
-/* TODO(agl): Free snapStartApplicationData as soon as the handshake has
-** completed.
-*/
-
#include "pk11pub.h"
#include "ssl.h"
#include "sslimpl.h"
@@ -821,6 +817,7 @@ ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
rv = ssl3_AppendSnapStartApplicationData(
ss, ss->ssl3.snapStartApplicationData.data,
ss->ssl3.snapStartApplicationData.len);
+ SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
if (rv != SECSuccess)
goto loser;
}
@@ -1056,6 +1053,8 @@ ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->ssl3.hs.snapStartType = snap_start_resume_recovery;
}
+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT;
+
ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/);
return SECSuccess;
diff --git a/net/third_party/nss/ssl/ssl.def b/net/third_party/nss/ssl/ssl.def
index effc35d..60ebbb1 100644
--- a/net/third_party/nss/ssl/ssl.def
+++ b/net/third_party/nss/ssl/ssl.def
@@ -163,6 +163,7 @@ SSL_SetNextProtoNego;
;+ global:
SSL_GetPredictedServerHelloData;
SSL_GetSnapStartResult;
+SSL_PeerCertificateChain;
SSL_SetPredictedPeerCertificates;
SSL_SetPredictedServerHelloData;
SSL_SetSnapStartApplicationData;
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index 8217d2e..9d3da0c 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -273,6 +273,17 @@ SSL_IMPORT SECStatus SSL_SecurityStatus(PRFileDesc *fd, int *on, char **cipher,
SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd);
/*
+** Return references to the certificates presented by the SSL peer. On entry,
+** |*certs_size| must contain the size of the |certs| array. On successful
+** return, |*certs_size| contains the number of certificates available and
+** |certs| will contain references to as many certificates as would fit.
+** Therefore if, on exit, |*certs_size| contains a value less than, or equal to,
+** the entry value then all certificates were returned.
+*/
+SSL_IMPORT SECStatus SSL_PeerCertificateChain(
+ PRFileDesc *fd, CERTCertificate **certs, unsigned int *certs_size);
+
+/*
** Authenticate certificate hook. Called when a certificate comes in
** (because of SSL_REQUIRE_CERTIFICATE in SSL_Enable) to authenticate the
** certificate.
@@ -312,6 +323,35 @@ typedef SECStatus (PR_CALLBACK *SSLGetClientAuthData)(void *arg,
SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
SSLGetClientAuthData f, void *a);
+/*
+ * Prototype for SSL callback to get client auth data from the application,
+ * when using the underlying platform's cryptographic primitives. Returning
+ * SECFailure will cause the socket to send no client certificate.
+ * arg - application passed argument
+ * caNames - pointer to distinguished names of CAs that the server likes
+ * pRetCerts - pointer to pointer to list of certs, with the first being
+ * the client cert, and any following being used for chain
+ * building
+ * pRetKey - pointer to native key pointer, for return of key
+ * - Windows: pointer to HCRYPTPROV
+ * - Mac OS X: pointer to SecKeyRef
+ */
+typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
+ PRFileDesc *fd,
+ CERTDistNames *caNames,
+ CERTCertList **pRetCerts,/*return */
+ void **pRetKey);/* return */
+
+/*
+ * Set the client side callback for SSL to retrieve user's private key
+ * and certificate.
+ * fd - the file descriptor for the connection in question
+ * f - the application's callback that delivers the key and cert
+ * a - application specific data
+ */
+SSL_IMPORT SECStatus
+SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
+ SSLGetPlatformClientAuthData f, void *a);
/*
** SNI extension processing callback function.
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index 1a6612f..d3d2727 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -2011,6 +2011,12 @@ ssl3_ComputeRecordMAC(
static PRBool
ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (!sid || !sid->u.ssl3.clPlatformAuthValid) {
+ return PR_TRUE;
+ }
+ return ssl_PlatformAuthTokenPresent(&sid->u.ssl3.clPlatformAuthInfo);
+#else
PK11SlotInfo *slot = NULL;
PRBool isPresent = PR_TRUE;
@@ -2034,6 +2040,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
PK11_FreeSlot(slot);
}
return isPresent;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
}
SECStatus
@@ -4827,6 +4834,20 @@ ssl3_SendCertificateVerify(sslSocket *ss)
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ rv = ssl3_PlatformSignHashes(&hashes, ss->ssl3.platformClientKey,
+ &buf, isTLS);
+ if (rv == SECSuccess) {
+ sslSessionID * sid = ss->sec.ci.sid;
+ ssl_GetPlatformAuthInfoForKey(ss->ssl3.platformClientKey,
+ &sid->u.ssl3.clPlatformAuthInfo);
+ sid->u.ssl3.clPlatformAuthValid = PR_TRUE;
+ }
+ if (ss->ssl3.hs.kea_def->exchKeyType == kt_rsa) {
+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
+ }
+#else /* NSS_PLATFORM_CLIENT_AUTH */
rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
if (rv == SECSuccess) {
PK11SlotInfo * slot;
@@ -4851,6 +4872,7 @@ ssl3_SendCertificateVerify(sslSocket *ss)
SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
ss->ssl3.clientPrivateKey = NULL;
}
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
if (rv != SECSuccess) {
goto done; /* err code was set by ssl3_SignHashes */
}
@@ -5481,6 +5503,10 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SSL3AlertDescription desc = illegal_parameter;
SECItem cert_types = {siBuffer, NULL, 0};
CERTDistNames ca_list;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ CERTCertList * platform_cert_list = NULL;
+ CERTCertListNode * certNode = NULL;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
SSL_GETPID(), ss->fd));
@@ -5507,6 +5533,12 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
ss->ssl3.clientPrivateKey = NULL;
}
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (ss->ssl3.platformClientKey) {
+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
+ }
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
@@ -5573,6 +5605,18 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
desc = no_certificate;
ss->ssl3.hs.ws = wait_hello_done;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (ss->getPlatformClientAuthData == NULL) {
+ rv = SECFailure; /* force it to send a no_certificate alert */
+ } else {
+ /* XXX Should pass cert_types in this call!! */
+ rv = (SECStatus)(*ss->getPlatformClientAuthData)(
+ ss->getPlatformClientAuthDataArg,
+ ss->fd, &ca_list,
+ &platform_cert_list,
+ (void**)&ss->ssl3.platformClientKey);
+ }
+#else
if (ss->getClientAuthData == NULL) {
rv = SECFailure; /* force it to send a no_certificate alert */
} else {
@@ -5582,12 +5626,51 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
&ss->ssl3.clientCertificate,
&ss->ssl3.clientPrivateKey);
}
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
switch (rv) {
case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
ssl_SetAlwaysBlock(ss);
break; /* not an error */
case SECSuccess:
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
+ !ss->ssl3.platformClientKey) {
+ if (platform_cert_list) {
+ CERT_DestroyCertList(platform_cert_list);
+ platform_cert_list = NULL;
+ }
+ if (ss->ssl3.platformClientKey) {
+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
+ }
+ goto send_no_certificate;
+ }
+
+ certNode = CERT_LIST_HEAD(platform_cert_list);
+ ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
+
+ /* Setting ssl3.clientCertChain non-NULL will cause
+ * ssl3_HandleServerHelloDone to call SendCertificate.
+ * Note: clientCertChain should include the EE cert as
+ * clientCertificate is ignored during the actual sending
+ */
+ ss->ssl3.clientCertChain =
+ hack_NewCertificateListFromCertList(platform_cert_list);
+ CERT_DestroyCertList(platform_cert_list);
+ platform_cert_list = NULL;
+ if (ss->ssl3.clientCertChain == NULL) {
+ if (ss->ssl3.clientCertificate != NULL) {
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ ss->ssl3.clientCertificate = NULL;
+ }
+ if (ss->ssl3.platformClientKey) {
+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
+ }
+ goto send_no_certificate;
+ }
+#else
/* check what the callback function returned */
if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
/* we are missing either the key or cert */
@@ -5620,6 +5703,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
goto send_no_certificate;
}
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
break; /* not an error */
case SECFailure:
@@ -5650,6 +5734,10 @@ loser:
done:
if (arena != NULL)
PORT_FreeArena(arena, PR_FALSE);
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (platform_cert_list)
+ CERT_DestroyCertList(platform_cert_list);
+#endif
return rv;
}
@@ -5758,6 +5846,16 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
goto loser; /* error code is set. */
}
} else
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (ss->ssl3.clientCertChain != NULL &&
+ ss->ssl3.platformClientKey) {
+ send_verify = PR_TRUE;
+ rv = ssl3_SendCertificate(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
+ }
+#else
if (ss->ssl3.clientCertChain != NULL &&
ss->ssl3.clientPrivateKey != NULL) {
send_verify = PR_TRUE;
@@ -5766,6 +5864,7 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
goto loser; /* error code is set. */
}
}
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
rv = ssl3_SendClientKeyExchange(ss);
if (rv != SECSuccess) {
@@ -8366,20 +8465,6 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
}
}
- if ((ss->ssl3.hs.snapStartType == snap_start_recovery ||
- ss->ssl3.hs.snapStartType == snap_start_resume_recovery) &&
- ss->ssl3.snapStartApplicationData.data) {
- /* In the event that the server ignored the application data in our
- * snap start extension, we need to retransmit it now. */
- PRInt32 sent = ssl3_SendRecord(ss, content_application_data,
- ss->ssl3.snapStartApplicationData.data,
- ss->ssl3.snapStartApplicationData.len,
- flags);
- SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
- if (sent < 0)
- return (SECStatus)sent; /* error code set by ssl3_SendRecord */
- }
-
return SECSuccess;
fail:
@@ -9640,6 +9725,10 @@ ssl3_DestroySSL3Info(sslSocket *ss)
if (ss->ssl3.clientPrivateKey != NULL)
SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (ss->ssl3.platformClientKey)
+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
if (ss->ssl3.peerCertArena != NULL)
ssl3_CleanupPeerCerts(ss);
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
index a7ae062..f044e1c 100644
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ b/net/third_party/nss/ssl/ssl3ext.c
@@ -46,8 +46,8 @@
#include "nssrenam.h"
#include "nss.h"
#include "ssl.h"
-#include "sslproto.h"
#include "sslimpl.h"
+#include "sslproto.h"
#include "pk11pub.h"
#include "blapi.h"
#include "prinit.h"
diff --git a/net/third_party/nss/ssl/sslauth.c b/net/third_party/nss/ssl/sslauth.c
index 39c630d..3f4924d 100644
--- a/net/third_party/nss/ssl/sslauth.c
+++ b/net/third_party/nss/ssl/sslauth.c
@@ -60,6 +60,42 @@ SSL_PeerCertificate(PRFileDesc *fd)
}
/* NEED LOCKS IN HERE. */
+SECStatus
+SSL_PeerCertificateChain(PRFileDesc *fd, CERTCertificate **certs,
+ unsigned int *certsSize)
+{
+ sslSocket *ss;
+ unsigned int inSize = *certsSize;
+ ssl3CertNode* cur;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+ if (!ss->opt.useSecurity)
+ return SECFailure;
+
+ if (ss->sec.peerCert == NULL) {
+ *certsSize = 0;
+ return SECSuccess;
+ }
+
+ *certsSize = 1; /* for the leaf certificate */
+ if (inSize > 0)
+ certs[0] = CERT_DupCertificate(ss->sec.peerCert);
+
+ for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) {
+ if (*certsSize < inSize)
+ certs[*certsSize] = CERT_DupCertificate(cur->cert);
+ (*certsSize)++;
+ }
+
+ return SECSuccess;
+}
+
+/* NEED LOCKS IN HERE. */
CERTCertificate *
SSL_LocalCertificate(PRFileDesc *fd)
{
@@ -216,6 +252,28 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
return SECSuccess;
}
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+/* NEED LOCKS IN HERE. */
+SECStatus
+SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
+ SSLGetPlatformClientAuthData func,
+ void *arg)
+{
+ sslSocket *ss;
+
+ ss = ssl_FindSocket(s);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
+ SSL_GETPID(), s));
+ return SECFailure;
+ }
+
+ ss->getPlatformClientAuthData = func;
+ ss->getPlatformClientAuthDataArg = arg;
+ return SECSuccess;
+}
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
/* NEED LOCKS IN HERE. */
SECStatus
SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
index f708696..b84511b 100644
--- a/net/third_party/nss/ssl/sslimpl.h
+++ b/net/third_party/nss/ssl/sslimpl.h
@@ -65,6 +65,15 @@
#include "sslt.h" /* for some formerly private types, now public */
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+#if defined(XP_WIN32)
+#include <windows.h>
+#include <wincrypt.h>
+#elif defined(XP_MACOSX)
+#include <Security/Security.h>
+#endif
+#endif
+
/* to make some of these old enums public without namespace pollution,
** it was necessary to prepend ssl_ to the names.
** These #defines preserve compatibility with the old code here in libssl.
@@ -573,6 +582,19 @@ typedef enum { never_cached,
#define MAX_PEER_CERT_CHAIN_SIZE 8
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+typedef struct {
+#if defined(XP_WIN32)
+ char * provider;
+ char * container;
+ DWORD provType;
+#elif defined(XP_MACOSX)
+ SecKeychainRef keychain;
+ CFDataRef persistentKey;
+#endif
+} PlatformAuthInfo;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
struct sslSessionIDStr {
sslSessionID * next; /* chain used for client sockets, only */
@@ -657,6 +679,11 @@ struct sslSessionIDStr {
char masterValid;
char clAuthValid;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ PlatformAuthInfo clPlatformAuthInfo;
+ char clPlatformAuthValid;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
/* Session ticket if we have one, is sent as an extension in the
* ClientHello message. This field is used by clients.
*/
@@ -816,6 +843,15 @@ const ssl3CipherSuiteDef *suite_def;
PRBool nextProtoNego;/* Our peer has sent this extension */
} SSL3HandshakeState;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+#if defined(XP_WIN32)
+typedef HCRYPTPROV PlatformKey;
+#elif defined(XP_MACOSX)
+typedef SecKeyRef PlatformKey;
+#else
+typedef void *PlatformKey;
+#endif
+#endif
/*
@@ -839,6 +875,9 @@ struct ssl3StateStr {
CERTCertificate * clientCertificate; /* used by client */
SECKEYPrivateKey * clientPrivateKey; /* used by client */
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ PlatformKey platformClientKey; /* used by client */
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
CERTCertificateList *clientCertChain; /* used by client */
PRBool sendEmptyCert; /* used by client */
@@ -1100,6 +1139,10 @@ const unsigned char * preferredCipher;
void *authCertificateArg;
SSLGetClientAuthData getClientAuthData;
void *getClientAuthDataArg;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ SSLGetPlatformClientAuthData getPlatformClientAuthData;
+ void *getPlatformClientAuthDataArg;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
SSLSNISocketConfig sniSocketConfig;
void *sniSocketConfigArg;
SSLBadCertHandler handleBadCert;
@@ -1691,6 +1734,43 @@ extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit);
extern SECStatus ssl_FreeSessionCacheLocks(void);
+/***************** platform client auth ****************/
+
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+// Releases the platform key.
+extern void ssl_FreePlatformKey(PlatformKey key);
+
+// Frees any memory allocated to store a persistent reference to the
+// platform key.
+extern void ssl_FreePlatformAuthInfo(PlatformAuthInfo* info);
+
+// Initializes the PlatformAuthInfo to empty/invalid values.
+extern void ssl_InitPlatformAuthInfo(PlatformAuthInfo* info);
+
+// Determine if the given key is still present in the system. This is used
+// to check for things like smart cards being ejected after handshaking,
+// since no further operations on the key will happen which would detect this.
+extern PRBool ssl_PlatformAuthTokenPresent(PlatformAuthInfo* info);
+
+// Obtain a persistent reference to a key, sufficient for
+// ssl_PlatformAuthTokenPresent to determine if the key is still present.
+extern void ssl_GetPlatformAuthInfoForKey(PlatformKey key,
+ PlatformAuthInfo* info);
+
+// Implement the client CertificateVerify message for SSL3/TLS1.0
+extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
+ PlatformKey key, SECItem *buf,
+ PRBool isTLS);
+
+// Converts a CERTCertList* (A collection of CERTCertificates) into a
+// CERTCertificateList* (A collection of SECItems), or returns NULL if
+// it cannot be converted.
+// This is to allow the platform-supplied chain to be created with purely
+// public API functions, using the preferred CERTCertList mutators, rather
+// pushing this hack to clients.
+extern CERTCertificateList* hack_NewCertificateListFromCertList(
+ CERTCertList* list);
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
/********************** misc calls *********************/
diff --git a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
index 64adc1f..345f041 100644
--- a/net/third_party/nss/ssl/sslnonce.c
+++ b/net/third_party/nss/ssl/sslnonce.c
@@ -226,6 +226,11 @@ ssl_DestroySID(sslSessionID *sid)
if (sid->u.ssl3.sessionTicket.ticket.data) {
SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
}
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (sid->u.ssl3.clPlatformAuthValid) {
+ ssl_FreePlatformAuthInfo(&sid->u.ssl3.clPlatformAuthInfo);
+ }
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
PORT_ZFree(sid, sizeof(sslSessionID));
}
diff --git a/net/third_party/nss/ssl/sslplatf.c b/net/third_party/nss/ssl/sslplatf.c
new file mode 100644
index 0000000..7119543
--- /dev/null
+++ b/net/third_party/nss/ssl/sslplatf.c
@@ -0,0 +1,561 @@
+/*
+ * Platform specific crypto wrappers
+ *
+ * ***** 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):
+ * Ryan Sleevi <ryan.sleevi@gmail.com>
+ *
+ * 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 ***** */
+/* $Id$ */
+#include "ssl.h"
+#include "certt.h"
+#include "keythi.h"
+#include "sslimpl.h"
+#include "cryptohi.h"
+#include "secitem.h"
+
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+CERTCertificateList*
+hack_NewCertificateListFromCertList(CERTCertList* list)
+{
+ CERTCertificateList * chain = NULL;
+ PRArenaPool * arena = NULL;
+ CERTCertListNode * node;
+ int len;
+
+ if (CERT_LIST_EMPTY(list))
+ goto loser;
+
+ arena = PORT_NewArena(4096);
+ if (arena == NULL)
+ goto loser;
+
+ for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
+ len++, node = CERT_LIST_NEXT(node)) {
+ }
+
+ chain = PORT_ArenaNew(arena, CERTCertificateList);
+ if (chain == NULL)
+ goto loser;
+
+ chain->certs = PORT_ArenaNewArray(arena, SECItem, len);
+ if (!chain->certs)
+ goto loser;
+ chain->len = len;
+
+ for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
+ len++, node = CERT_LIST_NEXT(node)) {
+ // Check to see if the last cert to be sent is a self-signed cert,
+ // and if so, omit it from the list of certificates. However, if
+ // there is only one cert (len == 0), include the cert, as it means
+ // the EE cert is self-signed.
+ if (len > 0 && (len == chain->len - 1) && node->cert->isRoot) {
+ chain->len = len;
+ break;
+ }
+ SECITEM_CopyItem(arena, &chain->certs[len], &node->cert->derCert);
+ }
+
+ chain->arena = arena;
+ return chain;
+
+loser:
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return NULL;
+}
+
+#if defined(XP_WIN32)
+void
+ssl_FreePlatformKey(PlatformKey key)
+{
+ CryptReleaseContext(key, 0);
+}
+
+void
+ssl_FreePlatformAuthInfo(PlatformAuthInfo* info)
+{
+ if (info->provider != NULL) {
+ PORT_Free(info->provider);
+ info->provider = NULL;
+ }
+ if (info->container != NULL) {
+ PORT_Free(info->container);
+ info->container = NULL;
+ }
+ info->provType = 0;
+}
+
+void
+ssl_InitPlatformAuthInfo(PlatformAuthInfo* info)
+{
+ info->provider = NULL;
+ info->container = NULL;
+ info->provType = 0;
+}
+
+PRBool
+ssl_PlatformAuthTokenPresent(PlatformAuthInfo *info)
+{
+ HCRYPTPROV prov = 0;
+
+ if (!info || !info->provider || !info->container)
+ return PR_FALSE;
+
+ if (!CryptAcquireContextA(&prov, info->container, info->provider,
+ info->provType, 0))
+ return PR_FALSE;
+
+ CryptReleaseContext(prov, 0);
+ return PR_TRUE;
+}
+
+void
+ssl_GetPlatformAuthInfoForKey(PlatformKey key,
+ PlatformAuthInfo *info)
+{
+ DWORD bytesNeeded = 0;
+ ssl_InitPlatformAuthInfo(info);
+ bytesNeeded = sizeof(info->provType);
+ if (!CryptGetProvParam(key, PP_PROVTYPE, (BYTE*)&info->provType,
+ &bytesNeeded, 0))
+ goto error;
+
+ bytesNeeded = 0;
+ if (!CryptGetProvParam(key, PP_CONTAINER, NULL, &bytesNeeded, 0))
+ goto error;
+ info->container = (char*)PORT_Alloc(bytesNeeded);
+ if (info->container == NULL)
+ goto error;
+ if (!CryptGetProvParam(key, PP_CONTAINER, (BYTE*)info->container,
+ &bytesNeeded, 0))
+ goto error;
+
+ bytesNeeded = 0;
+ if (!CryptGetProvParam(key, PP_NAME, NULL, &bytesNeeded, 0))
+ goto error;
+ info->provider = (char*)PORT_Alloc(bytesNeeded);
+ if (info->provider == NULL)
+ goto error;
+ if (!CryptGetProvParam(key, PP_NAME, (BYTE*)info->provider,
+ &bytesNeeded, 0))
+ goto error;
+
+ goto done;
+error:
+ ssl_FreePlatformAuthInfo(info);
+
+done:
+ return;
+}
+
+SECStatus
+ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
+ PRBool isTLS)
+{
+ SECStatus rv = SECFailure;
+ PRBool doDerEncode = PR_FALSE;
+ SECItem hashItem;
+ /* TODO(rsleevi): Should AT_SIGNATURE also be checked if doing client
+ * auth?
+ */
+ DWORD keySpec = AT_KEYEXCHANGE;
+ HCRYPTKEY hKey = 0;
+ DWORD argLen = 0;
+ ALG_ID keyAlg = 0;
+ DWORD signatureLen = 0;
+ ALG_ID hashAlg = 0;
+ HCRYPTHASH hHash = 0;
+ DWORD hashLen = 0;
+ unsigned int i = 0;
+
+ buf->data = NULL;
+ if (!CryptGetUserKey(key, keySpec, &hKey)) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ argLen = sizeof(keyAlg);
+ if (!CryptGetKeyParam(hKey, KP_ALGID, (BYTE*)&keyAlg, &argLen, 0)) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ switch (keyAlg) {
+ case CALG_RSA_KEYX:
+ case CALG_RSA_SIGN:
+ hashAlg = CALG_SSL3_SHAMD5;
+ hashItem.data = hash->md5;
+ hashItem.len = sizeof(SSL3Hashes);
+ break;
+ case CALG_DSS_SIGN:
+ /* TODO: Support CALG_ECDSA once tested */
+ case CALG_ECDSA:
+ if (keyAlg == CALG_ECDSA) {
+ doDerEncode = PR_TRUE;
+ } else {
+ doDerEncode = isTLS;
+ }
+ hashAlg = CALG_SHA1;
+ hashItem.data = hash->sha;
+ hashItem.len = sizeof(hash->sha);
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ goto done;
+ }
+ PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
+
+ if (!CryptCreateHash(key, hashAlg, 0, 0, &hHash)) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ argLen = sizeof(hashLen);
+ if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashLen, &argLen, 0)) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ if (hashLen != hashItem.len) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ if (!CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)hashItem.data, 0)) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ if (!CryptSignHash(hHash, keySpec, NULL, CRYPT_NOHASHOID,
+ NULL, &signatureLen) || signatureLen == 0) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ buf->len = signatureLen;
+ buf->data = (unsigned char *)PORT_Alloc(signatureLen);
+ if (!buf->data)
+ goto done; /* error code was set. */
+
+ if (!CryptSignHash(hHash, keySpec, NULL, CRYPT_NOHASHOID,
+ (BYTE*)buf->data, &signatureLen)) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+
+ /* CryptoAPI signs in little-endian, so reverse */
+ for (i = 0; i < buf->len / 2; ++i) {
+ unsigned char tmp = buf->data[i];
+ buf->data[i] = buf->data[buf->len - 1 - i];
+ buf->data[buf->len - 1 - i] = tmp;
+ }
+ if (doDerEncode) {
+ SECItem derSig = {siBuffer, NULL, 0};
+
+ /* This also works for an ECDSA signature */
+ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
+ if (rv == SECSuccess) {
+ PORT_Free(buf->data); /* discard unencoded signature. */
+ *buf = derSig; /* give caller encoded signature. */
+ } else if (derSig.data) {
+ PORT_Free(derSig.data);
+ }
+ }
+
+ PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));
+ rv = SECSuccess;
+done:
+ if (hHash)
+ CryptDestroyHash(hHash);
+ if (hKey)
+ CryptDestroyKey(hKey);
+ if (rv != SECSuccess && buf->data) {
+ PORT_Free(buf->data);
+ buf->data = NULL;
+ }
+ return rv;
+}
+
+#elif defined(XP_MACOSX)
+#include <Security/cssm.h>
+
+/*
+ * In Mac OS X 10.5, these two functions are private but implemented, and
+ * in Mac OS X 10.6, these are exposed publicly. To compile with the 10.5
+ * SDK, we declare them here.
+ */
+OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef *persistentItemRef);
+OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef *itemRef);
+
+void
+ssl_FreePlatformKey(PlatformKey key)
+{
+ CFRelease(key);
+}
+
+void
+ssl_FreePlatformAuthInfo(PlatformAuthInfo* info)
+{
+ if (info->keychain != NULL) {
+ CFRelease(info->keychain);
+ info->keychain = NULL;
+ }
+ if (info->persistentKey != NULL) {
+ CFRelease(info->persistentKey);
+ info->persistentKey = NULL;
+ }
+}
+
+void
+ssl_InitPlatformAuthInfo(PlatformAuthInfo* info)
+{
+ info->keychain = NULL;
+ info->persistentKey = NULL;
+}
+
+PRBool
+ssl_PlatformAuthTokenPresent(PlatformAuthInfo* info)
+{
+ if (!info || !info->keychain || !info->persistentKey)
+ return PR_FALSE;
+
+ // Not actually interested in the status, but it can be used to make sure
+ // that the keychain still exists (as smart card ejection will remove
+ // the keychain)
+ SecKeychainStatus keychainStatus;
+ OSStatus rv = SecKeychainGetStatus(info->keychain, &keychainStatus);
+ if (rv != noErr)
+ return PR_FALSE;
+
+ // Make sure the individual key still exists within the keychain, if
+ // the keychain is present
+ SecKeychainItemRef keychainItem;
+ rv = SecKeychainItemCopyFromPersistentReference(info->persistentKey,
+ &keychainItem);
+ if (rv != noErr)
+ return PR_FALSE;
+
+ CFRelease(keychainItem);
+ return PR_TRUE;
+}
+
+void
+ssl_GetPlatformAuthInfoForKey(PlatformKey key,
+ PlatformAuthInfo *info)
+{
+ SecKeychainItemRef keychainItem = (SecKeychainItemRef)key;
+ OSStatus rv = SecKeychainItemCopyKeychain(keychainItem, &info->keychain);
+ if (rv == noErr) {
+ rv = SecKeychainItemCreatePersistentReference(keychainItem,
+ &info->persistentKey);
+ }
+ if (rv != noErr) {
+ ssl_FreePlatformAuthInfo(info);
+ }
+ return;
+}
+
+SECStatus
+ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
+ PRBool isTLS)
+{
+ SECStatus rv = SECFailure;
+ PRBool doDerEncode = PR_FALSE;
+ unsigned int signatureLen;
+ OSStatus status = noErr;
+ CSSM_CSP_HANDLE cspHandle = 0;
+ const CSSM_KEY *cssmKey = NULL;
+ CSSM_ALGORITHMS sigAlg;
+ const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL;
+ CSSM_RETURN cssmRv;
+ CSSM_DATA hashData;
+ CSSM_DATA signatureData;
+ CSSM_CC_HANDLE cssmSignature = 0;
+
+ buf->data = NULL;
+
+ status = SecKeyGetCSPHandle(key, &cspHandle);
+ if (status != noErr) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ status = SecKeyGetCSSMKey(key, &cssmKey);
+ if (status != noErr || !cssmKey) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ /* SecKeyGetBlockSize wasn't addeded until OS X 10.6 - but the
+ * needed information is readily available on the key itself.
+ */
+ signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8;
+
+ if (signatureLen == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ buf->len = signatureLen;
+ buf->data = (unsigned char *)PORT_Alloc(signatureLen);
+ if (!buf->data)
+ goto done; /* error code was set. */
+
+ sigAlg = cssmKey->KeyHeader.AlgorithmId;
+ switch (sigAlg) {
+ case CSSM_ALGID_RSA:
+ hashData.Data = hash->md5;
+ hashData.Length = sizeof(SSL3Hashes);
+ break;
+ case CSSM_ALGID_ECDSA:
+ case CSSM_ALGID_DSA:
+ if (sigAlg == CSSM_ALGID_ECDSA) {
+ doDerEncode = PR_TRUE;
+ } else {
+ doDerEncode = isTLS;
+ }
+ hashData.Data = hash->sha;
+ hashData.Length = sizeof(hash->sha);
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+ PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length));
+
+ /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least,
+ * you can prevent the UI by setting the provider handle on the
+ * certificate to be opened with CRYPT_SILENT, but is there an equivalent?
+ */
+ status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN,
+ kSecCredentialTypeDefault, &cssmCreds);
+ if (status != noErr) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+
+ signatureData.Length = buf->len;
+ signatureData.Data = (uint8*)buf->data;
+
+ cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds,
+ cssmKey, &cssmSignature);
+ if (cssmRv) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+
+ /* See "Apple Cryptographic Service Provider Functional Specification" */
+ if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) {
+ /* To set RSA blinding for RSA keys */
+ CSSM_CONTEXT_ATTRIBUTE blindingAttr;
+ blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING;
+ blindingAttr.AttributeLength = sizeof(uint32);
+ blindingAttr.Attribute.Uint32 = 1;
+ cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr);
+ if (cssmRv) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+ }
+
+ cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, CSSM_ALGID_NONE,
+ &signatureData);
+ if (cssmRv) {
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ goto done;
+ }
+
+ if (doDerEncode) {
+ SECItem derSig = {siBuffer, NULL, 0};
+
+ /* This also works for an ECDSA signature */
+ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
+ if (rv == SECSuccess) {
+ PORT_Free(buf->data); /* discard unencoded signature. */
+ *buf = derSig; /* give caller encoded signature. */
+ } else if (derSig.data) {
+ PORT_Free(derSig.data);
+ }
+ }
+
+ PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));
+ rv = SECSuccess;
+done:
+ /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and
+ * should not be freed. When the PlatformKey is freed, they will be
+ * released.
+ */
+ if (cssmSignature)
+ CSSM_DeleteContext(cssmSignature);
+
+ if (rv != SECSuccess && buf->data) {
+ PORT_Free(buf->data);
+ buf->data = NULL;
+ }
+ return rv;
+}
+#else
+void
+ssl_FreePlatformKey(PlatformKey key)
+{
+}
+
+void
+ssl_FreePlatformAuthInfo(PlatformAuthInfo *info)
+{
+}
+
+void
+ssl_InitPlatformAuthInfo(PlatformAuthInfo *info)
+{
+}
+
+PRBool
+ssl_PlatformAuthTokenPresent(PlatformAuthInfo *info)
+{
+ return PR_FALSE;
+}
+
+void
+ssl_GetPlatformAuthInfoForKey(PlatformKey key, PlatformAuthInfo *info)
+{
+}
+
+SECStatus
+ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
+ PRBool isTLS)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return SECFailure;
+}
+#endif
+
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c
index 6c73f25..4176ac8 100644
--- a/net/third_party/nss/ssl/sslsnce.c
+++ b/net/third_party/nss/ssl/sslsnce.c
@@ -638,6 +638,11 @@ ConvertToSID(sidCacheEntry * from,
to->u.ssl3.clAuthSeries = 0;
to->u.ssl3.clAuthValid = PR_FALSE;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ ssl_InitPlatformAuthInfo(&to->u.ssl3.clPlatformAuthInfo);
+ to->u.ssl3.clPlatformAuthValid = PR_FALSE;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
+
if (from->u.ssl3.certIndex != -1 && pcce) {
SECItem derCert;
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
index 2898b88..33e7f3e 100644
--- a/net/third_party/nss/ssl/sslsock.c
+++ b/net/third_party/nss/ssl/sslsock.c
@@ -336,6 +336,10 @@ ssl_DupSocket(sslSocket *os)
ss->authCertificateArg = os->authCertificateArg;
ss->getClientAuthData = os->getClientAuthData;
ss->getClientAuthDataArg = os->getClientAuthDataArg;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ ss->getPlatformClientAuthData = os->getPlatformClientAuthData;
+ ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
+#endif
ss->sniSocketConfig = os->sniSocketConfig;
ss->sniSocketConfigArg = os->sniSocketConfigArg;
ss->handleBadCert = os->handleBadCert;
@@ -1443,6 +1447,12 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->getClientAuthData = sm->getClientAuthData;
if (sm->getClientAuthDataArg)
ss->getClientAuthDataArg = sm->getClientAuthDataArg;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ if (sm->getPlatformClientAuthData)
+ ss->getPlatformClientAuthData = sm->getPlatformClientAuthData;
+ if (sm->getPlatformClientAuthDataArg)
+ ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
+#endif
if (sm->sniSocketConfig)
ss->sniSocketConfig = sm->sniSocketConfig;
if (sm->sniSocketConfigArg)
@@ -2456,6 +2466,10 @@ ssl_NewSocket(PRBool makeLocks)
ss->sniSocketConfig = NULL;
ss->sniSocketConfigArg = NULL;
ss->getClientAuthData = NULL;
+#ifdef NSS_PLATFORM_CLIENT_AUTH
+ ss->getPlatformClientAuthData = NULL;
+ ss->getPlatformClientAuthDataArg = NULL;
+#endif /* NSS_PLATFORM_CLIENT_AUTH */
ss->handleBadCert = NULL;
ss->badCertArg = NULL;
ss->pkcs11PinArg = NULL;
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
index 42949c8..3bdbcbf 100644
--- a/net/tools/fetch/fetch_client.cc
+++ b/net/tools/fetch/fetch_client.cc
@@ -137,7 +137,7 @@ int main(int argc, char**argv) {
scoped_ptr<net::HostResolver> host_resolver(
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
- NULL));
+ NULL, NULL));
scoped_refptr<net::ProxyService> proxy_service(
net::ProxyService::CreateDirect());
diff --git a/net/tools/fetch/http_listen_socket.cc b/net/tools/fetch/http_listen_socket.cc
index fd788c8..0db714f 100644
--- a/net/tools/fetch/http_listen_socket.cc
+++ b/net/tools/fetch/http_listen_socket.cc
@@ -30,8 +30,8 @@ void HttpListenSocket::Accept() {
if (conn == ListenSocket::kInvalidSocket) {
// TODO
} else {
- scoped_refptr<HttpListenSocket> sock =
- new HttpListenSocket(conn, delegate_);
+ scoped_refptr<HttpListenSocket> sock(
+ new HttpListenSocket(conn, delegate_));
// it's up to the delegate to AddRef if it wants to keep it around
DidAccept(this, sock);
}
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index c3fe86b..55aa6a9 100644..100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -21,7 +21,7 @@ import shutil
import SocketServer
import sys
import time
-import urllib2
+import urlparse
import warnings
# Ignore deprecation warnings, they make our output more cluttered.
@@ -64,7 +64,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer):
"""This is a specialization of StoppableHTTPerver that add https support."""
def __init__(self, server_address, request_hander_class, cert_path,
- ssl_client_auth, ssl_client_cas):
+ ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers):
s = open(cert_path).read()
x509 = tlslite.api.X509()
x509.parse(s)
@@ -78,6 +78,9 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer):
x509 = tlslite.api.X509()
x509.parse(s)
self.ssl_client_cas.append(x509.subject)
+ self.ssl_handshake_settings = tlslite.api.HandshakeSettings()
+ if ssl_bulk_ciphers is not None:
+ self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers
self.session_cache = tlslite.api.SessionCache()
StoppableHTTPServer.__init__(self, server_address, request_hander_class)
@@ -89,6 +92,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer):
privateKey=self.private_key,
sessionCache=self.session_cache,
reqCert=self.ssl_client_auth,
+ settings=self.ssl_handshake_settings,
reqCAs=self.ssl_client_cas)
tlsConnection.ignoreAbruptClose = True
return True
@@ -569,6 +573,24 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.end_headers()
return True
+ def _ReplaceFileData(self, data, query_parameters):
+ """Replaces matching substrings in a file.
+
+ If the 'replace_orig' and 'replace_new' URL query parameters are present,
+ a new string is returned with all occasions of the 'replace_orig' value
+ replaced by the 'replace_new' value.
+
+ If the parameters are not present, |data| is returned.
+ """
+ query_dict = cgi.parse_qs(query_parameters)
+ orig_values = query_dict.get('replace_orig', [])
+ new_values = query_dict.get('replace_new', [])
+ if not orig_values or not new_values:
+ return data
+ orig_value = orig_values[0]
+ new_value = new_values[0]
+ return data.replace(orig_value, new_value)
+
def FileHandler(self):
"""This handler sends the contents of the requested file. Wow, it's like
a real webserver!"""
@@ -581,29 +603,27 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if self.command == 'POST' or self.command == 'PUT' :
self.rfile.read(int(self.headers.getheader('content-length')))
- file = self.path[len(prefix):]
- if file.find('?') > -1:
- # Ignore the query parameters entirely.
- url, querystring = file.split('?')
- else:
- url = file
- entries = url.split('/')
- path = os.path.join(self.server.data_dir, *entries)
- if os.path.isdir(path):
- path = os.path.join(path, 'index.html')
-
- if not os.path.isfile(path):
- print "File not found " + file + " full path:" + path
+ _, _, url_path, _, query, _ = urlparse.urlparse(self.path)
+ sub_path = url_path[len(prefix):]
+ entries = sub_path.split('/')
+ file_path = os.path.join(self.server.data_dir, *entries)
+ if os.path.isdir(file_path):
+ file_path = os.path.join(file_path, 'index.html')
+
+ if not os.path.isfile(file_path):
+ print "File not found " + sub_path + " full path:" + file_path
self.send_error(404)
return True
- f = open(path, "rb")
+ f = open(file_path, "rb")
data = f.read()
f.close()
+ data = self._ReplaceFileData(data, query)
+
# If file.mock-http-headers exists, it contains the headers we
# should send. Read them in and parse them.
- headers_path = path + '.mock-http-headers'
+ headers_path = file_path + '.mock-http-headers'
if os.path.isfile(headers_path):
f = open(headers_path, "r")
@@ -623,7 +643,7 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# Could be more generic once we support mime-type sniffing, but for
# now we need to set it explicitly.
self.send_response(200)
- self.send_header('Content-type', self.GetMIMETypeFromName(file))
+ self.send_header('Content-type', self.GetMIMETypeFromName(file_path))
self.send_header('Content-Length', len(data))
self.end_headers()
@@ -1169,7 +1189,8 @@ def main(options, args):
' exiting...'
return
server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert,
- options.ssl_client_auth, options.ssl_client_ca)
+ options.ssl_client_auth, options.ssl_client_ca,
+ options.ssl_bulk_cipher)
print 'HTTPS server started on port %d...' % port
else:
server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler)
@@ -1240,8 +1261,18 @@ if __name__ == '__main__':
help='Require SSL client auth on every connection.')
option_parser.add_option('', '--ssl-client-ca', action='append', default=[],
help='Specify that the client certificate request '
- 'should indicate that it supports the CA contained '
- 'in the specified certificate file')
+ 'should include the CA named in the subject of '
+ 'the DER-encoded certificate contained in the '
+ 'specified file. This option may appear multiple '
+ 'times, indicating multiple CA names should be '
+ 'sent in the request.')
+ option_parser.add_option('', '--ssl-bulk-cipher', action='append',
+ help='Specify the bulk encryption algorithm(s)'
+ 'that will be accepted by the SSL server. Valid '
+ 'values are "aes256", "aes128", "3des", "rc4". If '
+ 'omitted, all algorithms will be used. This '
+ 'option may appear multiple times, indicating '
+ 'multiple algorithms should be enabled.');
option_parser.add_option('', '--file-root-url', default='/files/',
help='Specify a root URL for files served.')
option_parser.add_option('', '--startup-pipe', type='int',
diff --git a/net/tools/testserver/xmppserver.py b/net/tools/testserver/xmppserver.py
new file mode 100644
index 0000000..ad99571
--- /dev/null
+++ b/net/tools/testserver/xmppserver.py
@@ -0,0 +1,527 @@
+#!/usr/bin/python2.4
+# Copyright (c) 2010 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.
+
+"""A bare-bones and non-compliant XMPP server.
+
+Just enough of the protocol is implemented to get it to work with
+Chrome's sync notification system.
+"""
+
+import asynchat
+import asyncore
+import base64
+import re
+import socket
+from xml.dom import minidom
+
+# pychecker complains about the use of fileno(), which is implemented
+# by asyncore by forwarding to an internal object via __getattr__.
+__pychecker__ = 'no-classattr'
+
+
+class Error(Exception):
+ """Error class for this module."""
+ pass
+
+
+class UnexpectedXml(Error):
+ """Raised when an unexpected XML element has been encountered."""
+
+ def __init__(self, xml_element):
+ xml_text = xml_element.toxml()
+ Error.__init__(self, 'Unexpected XML element', xml_text)
+
+
+def ParseXml(xml_string):
+ """Parses the given string as XML and returns a minidom element
+ object.
+ """
+ dom = minidom.parseString(xml_string)
+
+ # minidom handles xmlns specially, but there's a bug where it sets
+ # the attribute value to None, which causes toxml() or toprettyxml()
+ # to break.
+ def FixMinidomXmlnsBug(xml_element):
+ if xml_element.getAttribute('xmlns') is None:
+ xml_element.setAttribute('xmlns', '')
+
+ def ApplyToAllDescendantElements(xml_element, fn):
+ fn(xml_element)
+ for node in xml_element.childNodes:
+ if node.nodeType == node.ELEMENT_NODE:
+ ApplyToAllDescendantElements(node, fn)
+
+ root = dom.documentElement
+ ApplyToAllDescendantElements(root, FixMinidomXmlnsBug)
+ return root
+
+
+def CloneXml(xml):
+ """Returns a deep copy of the given XML element.
+
+ Args:
+ xml: The XML element, which should be something returned from
+ ParseXml() (i.e., a root element).
+ """
+ return xml.ownerDocument.cloneNode(True).documentElement
+
+
+class StanzaParser(object):
+ """A hacky incremental XML parser.
+
+ StanzaParser consumes data incrementally via FeedString() and feeds
+ its delegate complete parsed stanzas (i.e., XML documents) via
+ FeedStanza(). Any stanzas passed to FeedStanza() are unlinked after
+ the callback is done.
+
+ Use like so:
+
+ class MyClass(object):
+ ...
+ def __init__(self, ...):
+ ...
+ self._parser = StanzaParser(self)
+ ...
+
+ def SomeFunction(self, ...):
+ ...
+ self._parser.FeedString(some_data)
+ ...
+
+ def FeedStanza(self, stanza):
+ ...
+ print stanza.toprettyxml()
+ ...
+ """
+
+ # NOTE(akalin): The following regexps are naive, but necessary since
+ # none of the existing Python 2.4/2.5 XML libraries support
+ # incremental parsing. This works well enough for our purposes.
+ #
+ # The regexps below assume that any present XML element starts at
+ # the beginning of the string, but there may be trailing whitespace.
+
+ # Matches an opening stream tag (e.g., '<stream:stream foo="bar">')
+ # (assumes that the stream XML namespace is defined in the tag).
+ _stream_re = re.compile(r'^(<stream:stream [^>]*>)\s*')
+
+ # Matches an empty element tag (e.g., '<foo bar="baz"/>').
+ _empty_element_re = re.compile(r'^(<[^>]*/>)\s*')
+
+ # Matches a non-empty element (e.g., '<foo bar="baz">quux</foo>').
+ # Does *not* handle nested elements.
+ _non_empty_element_re = re.compile(r'^(<([^ >]*)[^>]*>.*?</\2>)\s*')
+
+ # The closing tag for a stream tag. We have to insert this
+ # ourselves since all XML stanzas are children of the stream tag,
+ # which is never closed until the connection is closed.
+ _stream_suffix = '</stream:stream>'
+
+ def __init__(self, delegate):
+ self._buffer = ''
+ self._delegate = delegate
+
+ def FeedString(self, data):
+ """Consumes the given string data, possibly feeding one or more
+ stanzas to the delegate.
+ """
+ self._buffer += data
+ while (self._ProcessBuffer(self._stream_re, self._stream_suffix) or
+ self._ProcessBuffer(self._empty_element_re) or
+ self._ProcessBuffer(self._non_empty_element_re)):
+ pass
+
+ def _ProcessBuffer(self, regexp, xml_suffix=''):
+ """If the buffer matches the given regexp, removes the match from
+ the buffer, appends the given suffix, parses it, and feeds it to
+ the delegate.
+
+ Returns:
+ Whether or not the buffer matched the given regexp.
+ """
+ results = regexp.match(self._buffer)
+ if not results:
+ return False
+ xml_text = self._buffer[:results.end()] + xml_suffix
+ self._buffer = self._buffer[results.end():]
+ stanza = ParseXml(xml_text)
+ self._delegate.FeedStanza(stanza)
+ # Needed because stanza may have cycles.
+ stanza.unlink()
+ return True
+
+
+class Jid(object):
+ """Simple struct for an XMPP jid (essentially an e-mail address with
+ an optional resource string).
+ """
+
+ def __init__(self, username, domain, resource=''):
+ self.username = username
+ self.domain = domain
+ self.resource = resource
+
+ def __str__(self):
+ jid_str = "%s@%s" % (self.username, self.domain)
+ if self.resource:
+ jid_str += '/' + self.resource
+ return jid_str
+
+ def GetBareJid(self):
+ return Jid(self.username, self.domain)
+
+
+class IdGenerator(object):
+ """Simple class to generate unique IDs for XMPP messages."""
+
+ def __init__(self, prefix):
+ self._prefix = prefix
+ self._id = 0
+
+ def GetNextId(self):
+ next_id = "%s.%s" % (self._prefix, self._id)
+ self._id += 1
+ return next_id
+
+
+class HandshakeTask(object):
+ """Class to handle the initial handshake with a connected XMPP
+ client.
+ """
+
+ # The handshake states in order.
+ (_INITIAL_STREAM_NEEDED,
+ _AUTH_NEEDED,
+ _AUTH_STREAM_NEEDED,
+ _BIND_NEEDED,
+ _SESSION_NEEDED,
+ _FINISHED) = range(6)
+
+ # Used when in the _INITIAL_STREAM_NEEDED and _AUTH_STREAM_NEEDED
+ # states. Not an XML object as it's only the opening tag.
+ #
+ # The from and id attributes are filled in later.
+ _STREAM_DATA = (
+ '<stream:stream from="%s" id="%s" '
+ 'version="1.0" xmlns:stream="http://etherx.jabber.org/streams" '
+ 'xmlns="jabber:client">')
+
+ # Used when in the _INITIAL_STREAM_NEEDED state.
+ _AUTH_STANZA = ParseXml(
+ '<stream:features xmlns:stream="http://etherx.jabber.org/streams">'
+ ' <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">'
+ ' <mechanism>PLAIN</mechanism>'
+ ' <mechanism>X-GOOGLE-TOKEN</mechanism>'
+ ' </mechanisms>'
+ '</stream:features>')
+
+ # Used when in the _AUTH_NEEDED state.
+ _AUTH_SUCCESS_STANZA = ParseXml(
+ '<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>')
+
+ # Used when in the _AUTH_STREAM_NEEDED state.
+ _BIND_STANZA = ParseXml(
+ '<stream:features xmlns:stream="http://etherx.jabber.org/streams">'
+ ' <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>'
+ ' <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>'
+ '</stream:features>')
+
+ # Used when in the _BIND_NEEDED state.
+ #
+ # The id and jid attributes are filled in later.
+ _BIND_RESULT_STANZA = ParseXml(
+ '<iq id="" type="result">'
+ ' <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">'
+ ' <jid/>'
+ ' </bind>'
+ '</iq>')
+
+ # Used when in the _SESSION_NEEDED state.
+ #
+ # The id attribute is filled in later.
+ _IQ_RESPONSE_STANZA = ParseXml('<iq id="" type="result"/>')
+
+ def __init__(self, connection, id_generator, resource_prefix):
+ self._connection = connection
+ self._id_generator = id_generator
+ self._username = ''
+ self._domain = ''
+ self._jid = None
+ self._resource_prefix = resource_prefix
+ self._state = self._INITIAL_STREAM_NEEDED
+
+ def FeedStanza(self, stanza):
+ """Inspects the given stanza and changes the handshake state if needed.
+
+ Called when a stanza is received from the client. Inspects the
+ stanza to make sure it has the expected attributes given the
+ current state, advances the state if needed, and sends a reply to
+ the client if needed.
+ """
+ def ExpectStanza(stanza, name):
+ if stanza.tagName != name:
+ raise UnexpectedXml(stanza)
+
+ def ExpectIq(stanza, type, name):
+ ExpectStanza(stanza, 'iq')
+ if (stanza.getAttribute('type') != type or
+ stanza.firstChild.tagName != name):
+ raise UnexpectedXml(stanza)
+
+ def GetStanzaId(stanza):
+ return stanza.getAttribute('id')
+
+ def HandleStream(stanza):
+ ExpectStanza(stanza, 'stream:stream')
+ domain = stanza.getAttribute('to')
+ if domain:
+ self._domain = domain
+ SendStreamData()
+
+ def SendStreamData():
+ next_id = self._id_generator.GetNextId()
+ stream_data = self._STREAM_DATA % (self._domain, next_id)
+ self._connection.SendData(stream_data)
+
+ def GetUserDomain(stanza):
+ encoded_username_password = stanza.firstChild.data
+ username_password = base64.b64decode(encoded_username_password)
+ (_, username_domain, _) = username_password.split('\0')
+ # The domain may be omitted.
+ #
+ # If we were using python 2.5, we'd be able to do:
+ #
+ # username, _, domain = username_domain.partition('@')
+ # if not domain:
+ # domain = self._domain
+ at_pos = username_domain.find('@')
+ if at_pos != -1:
+ username = username_domain[:at_pos]
+ domain = username_domain[at_pos+1:]
+ else:
+ username = username_domain
+ domain = self._domain
+ return (username, domain)
+
+ if self._state == self._INITIAL_STREAM_NEEDED:
+ HandleStream(stanza)
+ self._connection.SendStanza(self._AUTH_STANZA, False)
+ self._state = self._AUTH_NEEDED
+
+ elif self._state == self._AUTH_NEEDED:
+ ExpectStanza(stanza, 'auth')
+ (self._username, self._domain) = GetUserDomain(stanza)
+ self._connection.SendStanza(self._AUTH_SUCCESS_STANZA, False)
+ self._state = self._AUTH_STREAM_NEEDED
+
+ elif self._state == self._AUTH_STREAM_NEEDED:
+ HandleStream(stanza)
+ self._connection.SendStanza(self._BIND_STANZA, False)
+ self._state = self._BIND_NEEDED
+
+ elif self._state == self._BIND_NEEDED:
+ ExpectIq(stanza, 'set', 'bind')
+ stanza_id = GetStanzaId(stanza)
+ resource_element = stanza.getElementsByTagName('resource')[0]
+ resource = resource_element.firstChild.data
+ full_resource = '%s.%s' % (self._resource_prefix, resource)
+ response = CloneXml(self._BIND_RESULT_STANZA)
+ response.setAttribute('id', stanza_id)
+ self._jid = Jid(self._username, self._domain, full_resource)
+ jid_text = response.parentNode.createTextNode(str(self._jid))
+ response.getElementsByTagName('jid')[0].appendChild(jid_text)
+ self._connection.SendStanza(response)
+ self._state = self._SESSION_NEEDED
+
+ elif self._state == self._SESSION_NEEDED:
+ ExpectIq(stanza, 'set', 'session')
+ stanza_id = GetStanzaId(stanza)
+ xml = CloneXml(self._IQ_RESPONSE_STANZA)
+ xml.setAttribute('id', stanza_id)
+ self._connection.SendStanza(xml)
+ self._state = self._FINISHED
+ self._connection.HandshakeDone(self._jid)
+
+
+def AddrString(addr):
+ return '%s:%d' % addr
+
+
+class XmppConnection(asynchat.async_chat):
+ """A single XMPP client connection.
+
+ This class handles the connection to a single XMPP client (via a
+ socket). It does the XMPP handshake and also implements the (old)
+ Google notification protocol.
+ """
+
+ # We use this XML template for subscription responses as well as
+ # notifications (conveniently enough, the same template works
+ # for both).
+ #
+ # The from, to, id, and type attributes are filled in later.
+ _NOTIFIER_STANZA = ParseXml(
+ """<iq from="" to="" id="" type="">
+ <not:getAll xmlns:not="google:notifier">
+ <Result xmlns=""/>
+ </not:getAll>
+ </iq>
+ """)
+
+ def __init__(self, sock, socket_map, connections, addr):
+ """Starts up the xmpp connection.
+
+ Args:
+ sock: The socket to the client.
+ socket_map: A map from sockets to their owning objects.
+ connections: The set of handshake-completed connections.
+ addr: The host/port of the client.
+ """
+ asynchat.async_chat.__init__(self, sock)
+ self.set_terminator(None)
+ # async_chat in Python 2.4 has a bug where it ignores a
+ # socket_map argument. So we handle that ourselves.
+ self._socket_map = socket_map
+ self._socket_map[self.fileno()] = self
+
+ self._connections = connections
+ self._parser = StanzaParser(self)
+ self._jid = None
+
+ self._addr = addr
+ addr_str = AddrString(self._addr)
+ self._id_generator = IdGenerator(addr_str)
+ self._handshake_task = (
+ HandshakeTask(self, self._id_generator, addr_str))
+ print 'Starting connection to %s' % self
+
+ def __str__(self):
+ if self._jid:
+ return str(self._jid)
+ else:
+ return AddrString(self._addr)
+
+ # async_chat implementation.
+
+ def collect_incoming_data(self, data):
+ self._parser.FeedString(data)
+
+ # This is only here to make pychecker happy.
+ def found_terminator(self):
+ asynchat.async_chat.found_terminator(self)
+
+ def handle_close(self):
+ print "Closing connection to %s" % self
+ # Remove ourselves from anywhere we possibly installed ourselves.
+ self._connections.discard(self)
+ del self._socket_map[self.fileno()]
+
+ # Called by self._parser.FeedString().
+ def FeedStanza(self, stanza):
+ if self._handshake_task:
+ self._handshake_task.FeedStanza(stanza)
+ elif stanza.tagName == 'iq':
+ self._HandleIq(stanza)
+ else:
+ raise UnexpectedXml(stanza)
+
+ # Called by self._handshake_task.
+ def HandshakeDone(self, jid):
+ self._jid = jid
+ self._handshake_task = None
+ self._connections.add(self)
+ print "Handshake done for %s" % self
+
+ def _HandleIq(self, iq):
+ if (iq.firstChild and
+ iq.firstChild.namespaceURI == 'google:notifier'):
+ iq_id = iq.getAttribute('id')
+ self._HandleNotifierCommand(iq_id, iq.firstChild)
+ elif iq.getAttribute('type') == 'result':
+ # Ignore all client acks.
+ pass
+ else:
+ raise UnexpectedXml(iq)
+
+ def _HandleNotifierCommand(self, id, command_xml):
+ command = command_xml.tagName
+ if command == 'getAll':
+ # Subscription request.
+ if not command_xml.getElementsByTagName('SubscribedServiceUrl'):
+ raise UnexpectedXml(command_xml)
+ self._SendNotifierStanza(id, 'result')
+ elif command == 'set':
+ # Send notification request.
+ SendNotification(self._connections)
+ else:
+ raise UnexpectedXml(command_xml)
+
+ def _SendNotifierStanza(self, id, type):
+ stanza = CloneXml(self._NOTIFIER_STANZA)
+ stanza.setAttribute('from', str(self._jid.GetBareJid()))
+ stanza.setAttribute('to', str(self._jid))
+ stanza.setAttribute('id', id)
+ stanza.setAttribute('type', type)
+ self.SendStanza(stanza)
+
+ def SendStanza(self, stanza, unlink=True):
+ """Sends a stanza to the client.
+
+ Args:
+ stanza: The stanza to send.
+ unlink: Whether to unlink stanza after sending it. (Pass in
+ False if stanza is a constant.)
+ """
+ self.SendData(stanza.toxml())
+ if unlink:
+ stanza.unlink()
+
+ def SendData(self, data):
+ """Sends raw data to the client.
+ """
+ # We explicitly encode to ascii as that is what the client expects
+ # (some minidom library functions return unicode strings).
+ self.push(data.encode('ascii'))
+
+ def SendNotification(self):
+ """Sends a notification to the client."""
+ next_id = self._id_generator.GetNextId()
+ self._SendNotifierStanza(next_id, 'set')
+
+
+def SendNotification(connections):
+ """Sends a notification to all connections in the given sequence."""
+ for connection in connections:
+ print 'Sending notification to %s' % connection
+ connection.SendNotification()
+
+
+class XmppServer(asyncore.dispatcher):
+ """The main XMPP server class.
+
+ The XMPP server starts accepting connections on the given address
+ and spawns off XmppConnection objects for each one.
+
+ Use like so:
+
+ socket_map = {}
+ xmpp_server = xmppserver.XmppServer(socket_map, ('127.0.0.1', 5222))
+ asyncore.loop(30.0, False, socket_map)
+ """
+
+ def __init__(self, socket_map, addr):
+ asyncore.dispatcher.__init__(self, None, socket_map)
+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.set_reuse_addr()
+ self.bind(addr)
+ self.listen(5)
+ self._socket_map = socket_map
+ self._socket_map[self.fileno()] = self
+ self._connections = set()
+ print 'XMPP server running at %s' % AddrString(addr)
+
+ def handle_accept(self):
+ (sock, addr) = self.accept()
+ XmppConnection(sock, self._socket_map, self._connections, addr)
diff --git a/net/tools/testserver/xmppserver_test.py b/net/tools/testserver/xmppserver_test.py
new file mode 100644
index 0000000..e033a69
--- /dev/null
+++ b/net/tools/testserver/xmppserver_test.py
@@ -0,0 +1,250 @@
+#!/usr/bin/python2.4
+# Copyright (c) 2010 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.
+
+"""Tests exercising the various classes in xmppserver.py."""
+
+import unittest
+
+import base64
+import xmppserver
+
+class XmlUtilsTest(unittest.TestCase):
+
+ def testParseXml(self):
+ xml_text = """<foo xmlns=""><bar xmlns=""><baz/></bar></foo>"""
+ xml = xmppserver.ParseXml(xml_text)
+ self.assertEqual(xml.toxml(), xml_text)
+
+ def testCloneXml(self):
+ xml = xmppserver.ParseXml('<foo/>')
+ xml_clone = xmppserver.CloneXml(xml)
+ xml_clone.setAttribute('bar', 'baz')
+ self.assertEqual(xml, xml)
+ self.assertEqual(xml_clone, xml_clone)
+ self.assertNotEqual(xml, xml_clone)
+
+ def testCloneXmlUnlink(self):
+ xml_text = '<foo/>'
+ xml = xmppserver.ParseXml(xml_text)
+ xml_clone = xmppserver.CloneXml(xml)
+ xml.unlink()
+ self.assertEqual(xml.parentNode, None)
+ self.assertNotEqual(xml_clone.parentNode, None)
+ self.assertEqual(xml_clone.toxml(), xml_text)
+
+class StanzaParserTest(unittest.TestCase):
+
+ def setUp(self):
+ self.stanzas = []
+
+ def FeedStanza(self, stanza):
+ # We can't append stanza directly because it is unlinked after
+ # this callback.
+ self.stanzas.append(stanza.toxml())
+
+ def testBasic(self):
+ parser = xmppserver.StanzaParser(self)
+ parser.FeedString('<foo')
+ self.assertEqual(len(self.stanzas), 0)
+ parser.FeedString('/><bar></bar>')
+ self.assertEqual(self.stanzas[0], '<foo/>')
+ self.assertEqual(self.stanzas[1], '<bar/>')
+
+ def testStream(self):
+ parser = xmppserver.StanzaParser(self)
+ parser.FeedString('<stream')
+ self.assertEqual(len(self.stanzas), 0)
+ parser.FeedString(':stream foo="bar" xmlns:stream="baz">')
+ self.assertEqual(self.stanzas[0],
+ '<stream:stream foo="bar" xmlns:stream="baz"/>')
+
+ def testNested(self):
+ parser = xmppserver.StanzaParser(self)
+ parser.FeedString('<foo')
+ self.assertEqual(len(self.stanzas), 0)
+ parser.FeedString(' bar="baz"')
+ parser.FeedString('><baz/><blah>meh</blah></foo>')
+ self.assertEqual(self.stanzas[0],
+ '<foo bar="baz"><baz/><blah>meh</blah></foo>')
+
+
+class JidTest(unittest.TestCase):
+
+ def testBasic(self):
+ jid = xmppserver.Jid('foo', 'bar.com')
+ self.assertEqual(str(jid), 'foo@bar.com')
+
+ def testResource(self):
+ jid = xmppserver.Jid('foo', 'bar.com', 'resource')
+ self.assertEqual(str(jid), 'foo@bar.com/resource')
+
+ def testGetBareJid(self):
+ jid = xmppserver.Jid('foo', 'bar.com', 'resource')
+ self.assertEqual(str(jid.GetBareJid()), 'foo@bar.com')
+
+
+class IdGeneratorTest(unittest.TestCase):
+
+ def testBasic(self):
+ id_generator = xmppserver.IdGenerator('foo')
+ for i in xrange(0, 100):
+ self.assertEqual('foo.%d' % i, id_generator.GetNextId())
+
+
+class HandshakeTaskTest(unittest.TestCase):
+
+ def setUp(self):
+ self.data_received = 0
+
+ def SendData(self, _):
+ self.data_received += 1
+
+ def SendStanza(self, _, unused=True):
+ self.data_received += 1
+
+ def HandshakeDone(self, jid):
+ self.jid = jid
+
+ def DoHandshake(self, resource_prefix, resource, username,
+ initial_stream_domain, auth_domain, auth_stream_domain):
+ self.data_received = 0
+ id_generator = xmppserver.IdGenerator('foo')
+ handshake_task = (
+ xmppserver.HandshakeTask(self, id_generator, resource_prefix))
+ stream_xml = xmppserver.ParseXml('<stream:stream xmlns:stream="foo"/>')
+ stream_xml.setAttribute('to', initial_stream_domain)
+ self.assertEqual(self.data_received, 0)
+ handshake_task.FeedStanza(stream_xml)
+ self.assertEqual(self.data_received, 2)
+
+ if auth_domain:
+ username_domain = '%s@%s' % (username, auth_domain)
+ else:
+ username_domain = username
+ auth_string = base64.b64encode('\0%s\0bar' % username_domain)
+ auth_xml = xmppserver.ParseXml('<auth>%s</auth>'% auth_string)
+ handshake_task.FeedStanza(auth_xml)
+ self.assertEqual(self.data_received, 3)
+
+ stream_xml = xmppserver.ParseXml('<stream:stream xmlns:stream="foo"/>')
+ stream_xml.setAttribute('to', auth_stream_domain)
+ handshake_task.FeedStanza(stream_xml)
+ self.assertEqual(self.data_received, 5)
+
+ bind_xml = xmppserver.ParseXml(
+ '<iq type="set"><bind><resource>%s</resource></bind></iq>' % resource)
+ handshake_task.FeedStanza(bind_xml)
+ self.assertEqual(self.data_received, 6)
+
+ session_xml = xmppserver.ParseXml(
+ '<iq type="set"><session></session></iq>')
+ handshake_task.FeedStanza(session_xml)
+ self.assertEqual(self.data_received, 7)
+
+ self.assertEqual(self.jid.username, username)
+ self.assertEqual(self.jid.domain,
+ auth_stream_domain or auth_domain or
+ initial_stream_domain)
+ self.assertEqual(self.jid.resource,
+ '%s.%s' % (resource_prefix, resource))
+
+ def testBasic(self):
+ self.DoHandshake('resource_prefix', 'resource',
+ 'foo', 'bar.com', 'baz.com', 'quux.com')
+
+ def testDomainBehavior(self):
+ self.DoHandshake('resource_prefix', 'resource',
+ 'foo', 'bar.com', 'baz.com', 'quux.com')
+ self.DoHandshake('resource_prefix', 'resource',
+ 'foo', 'bar.com', 'baz.com', '')
+ self.DoHandshake('resource_prefix', 'resource',
+ 'foo', 'bar.com', '', '')
+ self.DoHandshake('resource_prefix', 'resource',
+ 'foo', '', '', '')
+
+
+class XmppConnectionTest(unittest.TestCase):
+
+ def setUp(self):
+ self.data = []
+
+ # socket-like methods.
+ def fileno(self):
+ return 0
+
+ def setblocking(self, int):
+ pass
+
+ def getpeername(self):
+ return ('', 0)
+
+ def send(self, data):
+ self.data.append(data)
+ pass
+
+ def testBasic(self):
+ connections = set()
+ xmpp_connection = xmppserver.XmppConnection(
+ self, {}, connections, ('', 0))
+ self.assertEqual(len(connections), 0)
+ xmpp_connection.HandshakeDone(xmppserver.Jid('foo', 'bar'))
+ self.assertEqual(len(connections), 1)
+
+ # Test subscription request.
+ self.assertEqual(len(self.data), 0)
+ xmpp_connection.collect_incoming_data(
+ '<iq><getAll xmlns="google:notifier">'
+ '<SubscribedServiceUrl/></getAll></iq>')
+ self.assertEqual(len(self.data), 1)
+
+ # Test acks.
+ xmpp_connection.collect_incoming_data('<iq type="result"/>')
+ self.assertEqual(len(self.data), 1)
+
+ # Test notification.
+ xmpp_connection.collect_incoming_data(
+ '<iq><set xmlns="google:notifier"/></iq>')
+ self.assertEqual(len(self.data), 2)
+
+ # Test unexpected stanza.
+ def SendUnexpectedStanza():
+ xmpp_connection.collect_incoming_data('<foo/>')
+ self.assertRaises(xmppserver.UnexpectedXml, SendUnexpectedStanza)
+
+ # Test unexpected notifier command.
+ def SendUnexpectedNotifierCommand():
+ xmpp_connection.collect_incoming_data(
+ '<iq><foo xmlns="google:notifier"/></iq>')
+ self.assertRaises(xmppserver.UnexpectedXml,
+ SendUnexpectedNotifierCommand)
+
+
+class XmppServerTest(unittest.TestCase):
+
+ # socket-like methods.
+ def fileno(self):
+ return 0
+
+ def setblocking(self, int):
+ pass
+
+ def getpeername(self):
+ return ('', 0)
+
+ def testBasic(self):
+ class FakeXmppServer(xmppserver.XmppServer):
+ def accept(self2):
+ return (self, ('', 0))
+
+ socket_map = {}
+ self.assertEqual(len(socket_map), 0)
+ xmpp_server = FakeXmppServer(socket_map, ('', 0))
+ self.assertEqual(len(socket_map), 1)
+ xmpp_server.handle_accept()
+ self.assertEqual(len(socket_map), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index c8dd874..c4f20c4 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -315,8 +315,8 @@ void URLRequest::StartJob(URLRequestJob* job) {
net_log_.BeginEvent(
net::NetLog::TYPE_URL_REQUEST_START_JOB,
- new URLRequestStartEventParameters(
- url_, method_, load_flags_, priority_));
+ make_scoped_refptr(new URLRequestStartEventParameters(
+ url_, method_, load_flags_, priority_)));
job_ = job;
job_->SetExtraRequestHeaders(extra_request_headers_);
@@ -493,8 +493,8 @@ int URLRequest::Redirect(const GURL& location, int http_status_code) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
net::NetLog::TYPE_URL_REQUEST_REDIRECTED,
- new net::NetLogStringParameter(
- "location", location.possibly_invalid_spec()));
+ make_scoped_refptr(new net::NetLogStringParameter(
+ "location", location.possibly_invalid_spec())));
}
if (redirect_limit_ <= 0) {
DVLOG(1) << "disallowing redirect: exceeds limit";
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 31b732e..f573111 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -10,7 +10,7 @@
#include <string>
#include <vector>
-#include "base/leak_tracker.h"
+#include "base/debug/leak_tracker.h"
#include "base/linked_ptr.h"
#include "base/logging.h"
#include "base/non_thread_safe.h"
@@ -634,7 +634,7 @@ class URLRequest : public NonThreadSafe {
// this to determine which URLRequest to allocate sockets to first.
net::RequestPriority priority_;
- base::LeakTracker<URLRequest> leak_tracker_;
+ base::debug::LeakTracker<URLRequest> leak_tracker_;
DISALLOW_COPY_AND_ASSIGN(URLRequest);
};
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc
index 8c282ff..fff85c3 100644
--- a/net/url_request/url_request_file_job.cc
+++ b/net/url_request/url_request_file_job.cc
@@ -23,6 +23,7 @@
#include "base/message_loop.h"
#include "base/platform_file.h"
#include "base/string_util.h"
+#include "base/thread_restrictions.h"
#include "build/build_config.h"
#include "googleurl/src/gurl.h"
#include "net/base/io_buffer.h"
@@ -128,8 +129,15 @@ void URLRequestFileJob::Start() {
return;
}
#endif
+
+ // URL requests should not block on the disk!
+ // http://code.google.com/p/chromium/issues/detail?id=59849
+ bool exists;
base::PlatformFileInfo file_info;
- bool exists = file_util::GetFileInfo(file_path_, &file_info);
+ {
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ exists = file_util::GetFileInfo(file_path_, &file_info);
+ }
// Continue asynchronously.
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
@@ -195,6 +203,10 @@ bool URLRequestFileJob::GetContentEncodings(
}
bool URLRequestFileJob::GetMimeType(std::string* mime_type) const {
+ // URL requests should not block on the disk! On Windows this goes to the
+ // registry.
+ // http://code.google.com/p/chromium/issues/detail?id=59849
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
DCHECK(request_);
return net::GetMimeTypeFromFile(file_path_, mime_type);
}
@@ -244,6 +256,10 @@ void URLRequestFileJob::DidResolve(
if (!exists) {
rv = net::ERR_FILE_NOT_FOUND;
} else if (!is_directory_) {
+ // URL requests should not block on the disk!
+ // http://code.google.com/p/chromium/issues/detail?id=59849
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h
index adf9d24..c5e1d2f 100644
--- a/net/url_request/url_request_file_job.h
+++ b/net/url_request/url_request_file_job.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -7,6 +7,7 @@
#pragma once
#include <string>
+#include <vector>
#include "base/file_path.h"
#include "net/base/completion_callback.h"
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index 37d6ab0..aec8248 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -82,7 +82,7 @@ void URLRequestFtpJob::GetAuthChallengeInfo(
scoped_refptr<net::AuthChallengeInfo>* result) {
DCHECK((server_auth_ != NULL) &&
(server_auth_->state == net::AUTH_STATE_NEED_AUTH));
- scoped_refptr<net::AuthChallengeInfo> auth_info = new net::AuthChallengeInfo;
+ scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
auth_info->is_proxy = false;
auth_info->host_and_port = ASCIIToWide(
net::GetHostAndPort(request_->url()));
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 2a4d036..a059a00 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -452,7 +452,7 @@ void URLRequestJob::NotifyHeadersComplete() {
// check the request pointer to see if it still exists, and return
// immediately if it has been destroyed. self_preservation ensures our
// survival until we can get out of this method.
- scoped_refptr<URLRequestJob> self_preservation = this;
+ scoped_refptr<URLRequestJob> self_preservation(this);
GURL new_location;
int http_status_code;
@@ -558,7 +558,7 @@ void URLRequestJob::NotifyReadComplete(int bytes_read) {
// check the request pointer to see if it still exists, and return
// immediately if it has been destroyed. self_preservation ensures our
// survival until we can get out of this method.
- scoped_refptr<URLRequestJob> self_preservation = this;
+ scoped_refptr<URLRequestJob> self_preservation(this);
prefilter_bytes_read_ += bytes_read;
if (filter_.get()) {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 3c5d05f..d0f488d 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -69,7 +69,7 @@ bool ContainsString(const std::string& haystack, const char* needle) {
haystack.end(),
needle,
needle + strlen(needle),
- CaseInsensitiveCompare<char>());
+ base::CaseInsensitiveCompare<char>());
return it != haystack.end();
}
@@ -89,7 +89,7 @@ void FillBuffer(char* buffer, size_t len) {
}
scoped_refptr<net::UploadData> CreateSimpleUploadData(const char* data) {
- scoped_refptr<net::UploadData> upload = new net::UploadData;
+ scoped_refptr<net::UploadData> upload(new net::UploadData);
upload->AppendBytes(data, strlen(data));
return upload;
}
@@ -146,7 +146,7 @@ class URLRequestTestHTTP : public URLRequestTest {
}
uploadBytes[kMsgSize] = '\0';
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
for (int i = 0; i < kIterations; ++i) {
TestDelegate d;
@@ -310,7 +310,9 @@ TEST_F(HTTPSRequestTest, HTTPSGetTest) {
}
TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME,
+ net::TestServer::HTTPSOptions https_options(
+ net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME);
+ net::TestServer test_server(https_options,
FilePath(FILE_PATH_LITERAL("net/data/ssl")));
ASSERT_TRUE(test_server.Start());
@@ -340,7 +342,9 @@ TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) {
}
TEST_F(HTTPSRequestTest, HTTPSExpiredTest) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE,
+ net::TestServer::HTTPSOptions https_options(
+ net::TestServer::HTTPSOptions::CERT_EXPIRED);
+ net::TestServer test_server(https_options,
FilePath(FILE_PATH_LITERAL("net/data/ssl")));
ASSERT_TRUE(test_server.Start());
@@ -398,7 +402,9 @@ class SSLClientAuthTestDelegate : public TestDelegate {
// - Getting a certificate request in an SSL renegotiation sending the
// HTTP request.
TEST_F(HTTPSRequestTest, ClientAuthTest) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_CLIENT_AUTH,
+ net::TestServer::HTTPSOptions https_options;
+ https_options.request_client_certificate = true;
+ net::TestServer test_server(https_options,
FilePath(FILE_PATH_LITERAL("net/data/ssl")));
ASSERT_TRUE(test_server.Start());
@@ -521,7 +527,7 @@ TEST_F(URLRequestTestHTTP, CancelTest4) {
TEST_F(URLRequestTestHTTP, CancelTest5) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
// populate cache
{
@@ -1128,7 +1134,7 @@ TEST_F(URLRequestTestHTTP, CancelDeferredRedirect) {
TEST_F(URLRequestTestHTTP, VaryHeader) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
// populate the cache
{
@@ -1174,7 +1180,7 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
TEST_F(URLRequestTestHTTP, BasicAuth) {
ASSERT_TRUE(test_server_.Start());
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
// populate the cache
{
@@ -1224,7 +1230,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
// Request a page that will give a 401 containing a Set-Cookie header.
// Verify that when the transaction is restarted, it includes the new cookie.
{
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
TestDelegate d;
d.set_username(kUser);
d.set_password(kSecret);
@@ -1245,7 +1251,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
// Same test as above, except this time the restart is initiated earlier
// (without user intervention since identity is embedded in the URL).
{
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
TestDelegate d;
GURL::Replacements replacements;
@@ -1273,7 +1279,7 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1322,7 +1328,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<URLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1378,7 +1384,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1432,7 +1438,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1489,7 +1495,7 @@ TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
// Set up an empty cookie.
{
@@ -1509,7 +1515,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1564,7 +1570,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
// Set up a cookie.
{
@@ -1621,7 +1627,7 @@ TEST_F(URLRequestTest, CancelTest_During_CookiePolicy) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
TestCookiePolicy cookie_policy(TestCookiePolicy::ASYNC);
context->set_cookie_policy(&cookie_policy);
@@ -1652,7 +1658,7 @@ TEST_F(URLRequestTest, CancelTest_During_OnGetCookies) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
TestCookiePolicy cookie_policy(TestCookiePolicy::NO_GET_COOKIES);
context->set_cookie_policy(&cookie_policy);
@@ -1681,7 +1687,7 @@ TEST_F(URLRequestTest, CancelTest_During_OnSetCookie) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
TestCookiePolicy cookie_policy(TestCookiePolicy::NO_SET_COOKIE);
context->set_cookie_policy(&cookie_policy);
@@ -1715,7 +1721,7 @@ TEST_F(URLRequestTest, CookiePolicy_ForceSession) {
net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
ASSERT_TRUE(test_server.Start());
- scoped_refptr<TestURLRequestContext> context = new TestURLRequestContext();
+ scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
TestCookiePolicy cookie_policy(TestCookiePolicy::FORCE_SESSION);
context->set_cookie_policy(&cookie_policy);
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
index 2a3ae41..abb6ab5 100644
--- a/net/url_request/url_request_unittest.h
+++ b/net/url_request/url_request_unittest.h
@@ -126,7 +126,7 @@ class TestURLRequestContext : public URLRequestContext {
TestURLRequestContext() {
host_resolver_ =
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
- NULL);
+ NULL, NULL);
proxy_service_ = net::ProxyService::CreateDirect();
Init();
}
@@ -134,7 +134,7 @@ class TestURLRequestContext : public URLRequestContext {
explicit TestURLRequestContext(const std::string& proxy) {
host_resolver_ =
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
- NULL);
+ NULL, NULL);
net::ProxyConfig proxy_config;
proxy_config.proxy_rules().ParseFromString(proxy);
proxy_service_ = net::ProxyService::CreateFixed(proxy_config);
diff --git a/net/url_request/view_cache_helper_unittest.cc b/net/url_request/view_cache_helper_unittest.cc
index e82ff15..5338ee5 100644
--- a/net/url_request/view_cache_helper_unittest.cc
+++ b/net/url_request/view_cache_helper_unittest.cc
@@ -40,8 +40,8 @@ void WriteHeaders(disk_cache::Entry* entry, int flags, const std::string data) {
pickle.WriteInt64(0);
pickle.WriteString(data);
- scoped_refptr<net::WrappedIOBuffer> buf = new net::WrappedIOBuffer(
- reinterpret_cast<const char*>(pickle.data()));
+ scoped_refptr<net::WrappedIOBuffer> buf(new net::WrappedIOBuffer(
+ reinterpret_cast<const char*>(pickle.data())));
int len = static_cast<int>(pickle.size());
TestCompletionCallback cb;
diff --git a/net/websockets/websocket.cc b/net/websockets/websocket.cc
index 3bf1da8..f8d9eb9 100644
--- a/net/websockets/websocket.cc
+++ b/net/websockets/websocket.cc
@@ -80,7 +80,7 @@ void WebSocket::Send(const std::string& msg) {
*p = '\0';
memcpy(p + 1, msg.data(), msg.size());
*(p + 1 + msg.size()) = '\xff';
- pending_write_bufs_.push_back(buf);
+ pending_write_bufs_.push_back(make_scoped_refptr(buf));
SendPending();
}
@@ -172,7 +172,7 @@ void WebSocket::OnConnected(SocketStream* socket_stream,
const std::string msg = handshake_->CreateClientHandshakeMessage();
IOBufferWithSize* buf = new IOBufferWithSize(msg.size());
memcpy(buf->data(), msg.data(), msg.size());
- pending_write_bufs_.push_back(buf);
+ pending_write_bufs_.push_back(make_scoped_refptr(buf));
origin_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &WebSocket::SendPending));
}
@@ -430,7 +430,7 @@ void WebSocket::StartClosingHandshake() {
client_closing_handshake_ = true;
IOBufferWithSize* buf = new IOBufferWithSize(2);
memcpy(buf->data(), kClosingFrame, 2);
- pending_write_bufs_.push_back(buf);
+ pending_write_bufs_.push_back(make_scoped_refptr(buf));
SendPending();
}
diff --git a/net/websockets/websocket_job.cc b/net/websockets/websocket_job.cc
index 64af45b..a1e2dde 100644
--- a/net/websockets/websocket_job.cc
+++ b/net/websockets/websocket_job.cc
@@ -313,7 +313,8 @@ void WebSocketJob::OnCanGetCookiesCompleted(int policy) {
handshake_request_sent_ = 0;
socket_->net_log()->AddEvent(
NetLog::TYPE_WEB_SOCKET_SEND_REQUEST_HEADERS,
- new NetLogWebSocketHandshakeParameter(handshake_request));
+ make_scoped_refptr(
+ new NetLogWebSocketHandshakeParameter(handshake_request)));
socket_->SendData(handshake_request.data(),
handshake_request.size());
}
@@ -354,8 +355,8 @@ void WebSocketJob::OnReceivedHandshakeResponse(
// handshake message is completed.
socket_->net_log()->AddEvent(
NetLog::TYPE_WEB_SOCKET_READ_RESPONSE_HEADERS,
- new NetLogWebSocketHandshakeParameter(
- handshake_response_->GetRawResponse()));
+ make_scoped_refptr(new NetLogWebSocketHandshakeParameter(
+ handshake_response_->GetRawResponse())));
if (len - response_length > 0) {
// If we received extra data, it should be frame data.
receive_frame_handler_->AppendData(data + response_length,
diff --git a/net/websockets/websocket_throttle_unittest.cc b/net/websockets/websocket_throttle_unittest.cc
index c4bf59f..7eb18fa 100644
--- a/net/websockets/websocket_throttle_unittest.cc
+++ b/net/websockets/websocket_throttle_unittest.cc
@@ -83,9 +83,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
struct addrinfo* addr = AddAddr(1, 2, 3, 4, NULL);
addr = AddAddr(1, 2, 3, 5, addr);
addr = AddAddr(1, 2, 3, 6, addr);
- scoped_refptr<WebSocketJob> w1 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s1 =
- new SocketStream(GURL("ws://host1/"), w1.get());
+ scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s1(
+ new SocketStream(GURL("ws://host1/"), w1.get()));
w1->InitSocketStream(s1.get());
WebSocketThrottleTest::MockSocketStreamConnect(s1, addr);
DeleteAddrInfo(addr);
@@ -103,9 +103,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
// For host2: 1.2.3.4
addr = AddAddr(1, 2, 3, 4, NULL);
- scoped_refptr<WebSocketJob> w2 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s2 =
- new SocketStream(GURL("ws://host2/"), w2.get());
+ scoped_refptr<WebSocketJob> w2(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s2(
+ new SocketStream(GURL("ws://host2/"), w2.get()));
w2->InitSocketStream(s2.get());
WebSocketThrottleTest::MockSocketStreamConnect(s2, addr);
DeleteAddrInfo(addr);
@@ -122,9 +122,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
// For host3: 1.2.3.5
addr = AddAddr(1, 2, 3, 5, NULL);
- scoped_refptr<WebSocketJob> w3 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s3 =
- new SocketStream(GURL("ws://host3/"), w3.get());
+ scoped_refptr<WebSocketJob> w3(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s3(
+ new SocketStream(GURL("ws://host3/"), w3.get()));
w3->InitSocketStream(s3.get());
WebSocketThrottleTest::MockSocketStreamConnect(s3, addr);
DeleteAddrInfo(addr);
@@ -141,9 +141,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
// For host4: 1.2.3.4, 1.2.3.6
addr = AddAddr(1, 2, 3, 4, NULL);
addr = AddAddr(1, 2, 3, 6, addr);
- scoped_refptr<WebSocketJob> w4 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s4 =
- new SocketStream(GURL("ws://host4/"), w4.get());
+ scoped_refptr<WebSocketJob> w4(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s4(
+ new SocketStream(GURL("ws://host4/"), w4.get()));
w4->InitSocketStream(s4.get());
WebSocketThrottleTest::MockSocketStreamConnect(s4, addr);
DeleteAddrInfo(addr);
@@ -159,9 +159,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
// For host5: 1.2.3.6
addr = AddAddr(1, 2, 3, 6, NULL);
- scoped_refptr<WebSocketJob> w5 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s5 =
- new SocketStream(GURL("ws://host5/"), w5.get());
+ scoped_refptr<WebSocketJob> w5(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s5(
+ new SocketStream(GURL("ws://host5/"), w5.get()));
w5->InitSocketStream(s5.get());
WebSocketThrottleTest::MockSocketStreamConnect(s5, addr);
DeleteAddrInfo(addr);
@@ -177,9 +177,9 @@ TEST_F(WebSocketThrottleTest, Throttle) {
// For host6: 1.2.3.6
addr = AddAddr(1, 2, 3, 6, NULL);
- scoped_refptr<WebSocketJob> w6 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s6 =
- new SocketStream(GURL("ws://host6/"), w6.get());
+ scoped_refptr<WebSocketJob> w6(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s6(
+ new SocketStream(GURL("ws://host6/"), w6.get()));
w6->InitSocketStream(s6.get());
WebSocketThrottleTest::MockSocketStreamConnect(s6, addr);
DeleteAddrInfo(addr);
@@ -286,9 +286,9 @@ TEST_F(WebSocketThrottleTest, NoThrottleForDuplicateAddress) {
// For localhost: 127.0.0.1, 127.0.0.1
struct addrinfo* addr = AddAddr(127, 0, 0, 1, NULL);
addr = AddAddr(127, 0, 0, 1, addr);
- scoped_refptr<WebSocketJob> w1 = new WebSocketJob(&delegate);
- scoped_refptr<SocketStream> s1 =
- new SocketStream(GURL("ws://localhost/"), w1.get());
+ scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
+ scoped_refptr<SocketStream> s1(
+ new SocketStream(GURL("ws://localhost/"), w1.get()));
w1->InitSocketStream(s1.get());
WebSocketThrottleTest::MockSocketStreamConnect(s1, addr);
DeleteAddrInfo(addr);